add some struct definitions
This commit is contained in:
parent
062e4847e1
commit
568ebd3207
29
src/block_group.rs
Normal file
29
src/block_group.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/// The Block Group Descriptor Table contains a descriptor for each block group
|
||||||
|
/// within the file system. The number of block groups within the file system,
|
||||||
|
/// and correspondingly, the number of entries in the Block Group Descriptor
|
||||||
|
/// Table, is described above. Each descriptor contains information regarding
|
||||||
|
/// where important data structures for that group are located.
|
||||||
|
///
|
||||||
|
/// The (`BlockGroupDescriptor`) table is located in the block immediately
|
||||||
|
/// following the Superblock. So if the block size (determined from a field in
|
||||||
|
/// the superblock) is 1024 bytes per block, the Block Group Descriptor Table
|
||||||
|
/// will begin at block 2. For any other block size, it will begin at block 1.
|
||||||
|
/// Remember that blocks are numbered starting at 0, and that block numbers
|
||||||
|
/// don't usually correspond to physical block addresses.
|
||||||
|
#[repr(C, packed)]
|
||||||
|
pub struct BlockGroupDescriptor {
|
||||||
|
/// Block address of block usage bitmap
|
||||||
|
block_usage_addr: u32,
|
||||||
|
/// Block address of inode usage bitmap
|
||||||
|
inode_usage_addr: u32,
|
||||||
|
/// Starting block address of inode table
|
||||||
|
inode_table_block: u32,
|
||||||
|
/// Number of unallocated blocks in group
|
||||||
|
free_blocks_count: u16,
|
||||||
|
/// Number of unallocated inodes in group
|
||||||
|
free_inodes_count: u16,
|
||||||
|
/// Number of directories in group
|
||||||
|
dirs_count: u16,
|
||||||
|
#[doc(hidden)]
|
||||||
|
_reserved: [u8; 14],
|
||||||
|
}
|
124
src/inode.rs
Normal file
124
src/inode.rs
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
#[repr(C, packed)]
|
||||||
|
pub struct Inode {
|
||||||
|
/// Type and Permissions (see below)
|
||||||
|
type_perm: u16,
|
||||||
|
/// User ID
|
||||||
|
uid: u16,
|
||||||
|
/// Lower 32 bits of size in bytes
|
||||||
|
size_low: u32,
|
||||||
|
/// Last Access Time (in POSIX time)
|
||||||
|
atime: u32,
|
||||||
|
/// Creation Time (in POSIX time)
|
||||||
|
ctime: u32,
|
||||||
|
/// Last Modification time (in POSIX time)
|
||||||
|
mtime: u32,
|
||||||
|
/// Deletion time (in POSIX time)
|
||||||
|
dtime: u32,
|
||||||
|
/// Group ID
|
||||||
|
gid: u16,
|
||||||
|
/// Count of hard links (directory entries) to this inode. When this
|
||||||
|
/// reaches 0, the data blocks are marked as unallocated.
|
||||||
|
hard_links: u16,
|
||||||
|
/// Count of disk sectors (not Ext2 blocks) in use by this inode, not
|
||||||
|
/// counting the actual inode structure nor directory entries linking
|
||||||
|
/// to the inode.
|
||||||
|
sectors_count: u32,
|
||||||
|
/// Flags
|
||||||
|
flags: u32,
|
||||||
|
/// Operating System Specific value #1
|
||||||
|
_os_specific_1: u32,
|
||||||
|
/// Direct block pointers
|
||||||
|
direct_pointer: [u32; 12],
|
||||||
|
/// Singly Indirect Block Pointer (Points to a block that is a list of
|
||||||
|
/// block pointers to data)
|
||||||
|
indirect_pointer: u32,
|
||||||
|
/// Doubly Indirect Block Pointer (Points to a block that is a list of
|
||||||
|
/// block pointers to Singly Indirect Blocks)
|
||||||
|
doubly_indirect: u32,
|
||||||
|
/// Triply Indirect Block Pointer (Points to a block that is a list of
|
||||||
|
/// block pointers to Doubly Indirect Blocks)
|
||||||
|
triply_indirect: u32,
|
||||||
|
/// Generation number (Primarily used for NFS)
|
||||||
|
gen_number: u32,
|
||||||
|
/// In Ext2 version 0, this field is reserved. In version >= 1,
|
||||||
|
/// Extended attribute block (File ACL).
|
||||||
|
ext_attribute_block: u32,
|
||||||
|
/// In Ext2 version 0, this field is reserved. In version >= 1, Upper
|
||||||
|
/// 32 bits of file size (if feature bit set) if it's a file,
|
||||||
|
/// Directory ACL if it's a directory
|
||||||
|
size_high: u32,
|
||||||
|
/// Block address of fragment
|
||||||
|
frag_block_addr: u32,
|
||||||
|
/// Operating System Specific Value #2
|
||||||
|
_os_specific_2: [u8; 12],
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct TypePerm: u16 {
|
||||||
|
/// FIFO
|
||||||
|
const FIFO = 0x1000;
|
||||||
|
/// Character device
|
||||||
|
const CHAR_DEVICE = 0x2000;
|
||||||
|
/// Directory
|
||||||
|
const DIRECTORY = 0x4000;
|
||||||
|
/// Block device
|
||||||
|
const BLOCK_DEVICE = 0x6000;
|
||||||
|
/// Regular file
|
||||||
|
const FILE = 0x8000;
|
||||||
|
/// Symbolic link
|
||||||
|
const SYMLINK = 0xA000;
|
||||||
|
/// Unix socket
|
||||||
|
const SOCKET = 0xC000;
|
||||||
|
/// Other—execute permission
|
||||||
|
const O_EXEC = 0x001;
|
||||||
|
/// Other—write permission
|
||||||
|
const O_WRITE = 0x002;
|
||||||
|
/// Other—read permission
|
||||||
|
const O_READ = 0x004;
|
||||||
|
/// Group—execute permission
|
||||||
|
const G_EXEC = 0x008;
|
||||||
|
/// Group—write permission
|
||||||
|
const G_WRITE = 0x010;
|
||||||
|
/// Group—read permission
|
||||||
|
const G_READ = 0x020;
|
||||||
|
/// User—execute permission
|
||||||
|
const U_EXEC = 0x040;
|
||||||
|
/// User—write permission
|
||||||
|
const U_WRITE = 0x080;
|
||||||
|
/// User—read permission
|
||||||
|
const U_READ = 0x100;
|
||||||
|
/// Sticky Bit
|
||||||
|
const STICKY = 0x200;
|
||||||
|
/// Set group ID
|
||||||
|
const SET_GID = 0x400;
|
||||||
|
/// Set user ID
|
||||||
|
const SET_UID = 0x800;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct InodeFlags: u32 {
|
||||||
|
/// Secure deletion (not used)
|
||||||
|
const SECURE_DEL = 0x00000001;
|
||||||
|
/// Keep a copy of data when deleted (not used)
|
||||||
|
const KEEP_COPY = 0x00000002;
|
||||||
|
/// File compression (not used)
|
||||||
|
const COMPRESSION = 0x00000004;
|
||||||
|
/// Synchronous updates—new data is written immediately to disk
|
||||||
|
const SYNC_UPDATE = 0x00000008;
|
||||||
|
/// Immutable file (content cannot be changed)
|
||||||
|
const IMMUTABLE = 0x00000010;
|
||||||
|
/// Append only
|
||||||
|
const APPEND_ONLY = 0x00000020;
|
||||||
|
/// File is not included in 'dump' command
|
||||||
|
const NODUMP = 0x00000040;
|
||||||
|
/// Last accessed time should not updated
|
||||||
|
const DONT_ATIME = 0x00000080;
|
||||||
|
/// Hash indexed directory
|
||||||
|
const HASH_DIR = 0x00010000;
|
||||||
|
/// AFS directory
|
||||||
|
const AFS_DIR = 0x00020000;
|
||||||
|
/// Journal file data
|
||||||
|
const JOURNAL_DATA = 0x00040000;
|
||||||
|
}
|
||||||
|
}
|
21
src/lib.rs
21
src/lib.rs
|
@ -1,4 +1,23 @@
|
||||||
#![cfg_attr(not(test), no_std)]
|
#![cfg_attr(not(test), no_std)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate bitflags;
|
||||||
|
|
||||||
|
pub mod superblock;
|
||||||
|
pub mod block_group;
|
||||||
|
pub mod inode;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {}
|
mod tests {
|
||||||
|
use super::superblock::*;
|
||||||
|
use super::block_group::*;
|
||||||
|
use super::inode::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sizes() {
|
||||||
|
use std::mem::size_of;
|
||||||
|
assert_eq!(size_of::<Superblock>(), 1024);
|
||||||
|
assert_eq!(size_of::<BlockGroupDescriptor>(), 32);
|
||||||
|
assert_eq!(size_of::<Inode>(), 128);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
210
src/superblock.rs
Normal file
210
src/superblock.rs
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
/// Ext2 signature (0xef53), used to help confirm the presence of Ext2 on a
|
||||||
|
/// volume
|
||||||
|
pub const EXT2_MAGIC: u16 = 0xef53;
|
||||||
|
|
||||||
|
/// Filesystem is free of errors
|
||||||
|
pub const FS_CLEAN: u16 = 1;
|
||||||
|
/// Filesystem has errors
|
||||||
|
pub const FS_ERR: u16 = 2;
|
||||||
|
|
||||||
|
/// Ignore errors
|
||||||
|
pub const ERR_IGNORE: u16 = 1;
|
||||||
|
/// Remount as read-only on error
|
||||||
|
pub const ERR_RONLY: u16 = 2;
|
||||||
|
/// Panic on error
|
||||||
|
pub const ERR_PANIC: u16 = 3;
|
||||||
|
|
||||||
|
/// Creator OS is Linux
|
||||||
|
pub const OS_LINUX: u32 = 0;
|
||||||
|
/// Creator OS is Hurd
|
||||||
|
pub const OS_HURD: u32 = 1;
|
||||||
|
/// Creator OS is Masix
|
||||||
|
pub const OS_MASIX: u32 = 2;
|
||||||
|
/// Creator OS is FreeBSD
|
||||||
|
pub const OS_FREEBSD: u32 = 3;
|
||||||
|
/// Creator OS is a BSD4.4-Lite derivative
|
||||||
|
pub const OS_LITE: u32 = 4;
|
||||||
|
|
||||||
|
/// The Superblock contains all information about the layout of the file system
|
||||||
|
/// and possibly contains other important information like what optional
|
||||||
|
/// features were used to create the file system.
|
||||||
|
///
|
||||||
|
/// The Superblock is always located at byte 1024 from the beginning of the
|
||||||
|
/// volume and is exactly 1024 bytes in length. For example, if the disk uses
|
||||||
|
/// 512 byte sectors, the Superblock will begin at LBA 2 and will occupy all of
|
||||||
|
/// sector 2 and 3.
|
||||||
|
#[repr(C, packed)]
|
||||||
|
pub struct Superblock {
|
||||||
|
// taken from https://wiki.osdev.org/Ext2
|
||||||
|
/// Total number of inodes in file system
|
||||||
|
inodes_count: u32,
|
||||||
|
/// Total number of blocks in file system
|
||||||
|
blocks_count: u32,
|
||||||
|
/// Number of blocks reserved for superuser (see offset 80)
|
||||||
|
r_blocks_count: u32,
|
||||||
|
/// Total number of unallocated blocks
|
||||||
|
free_blocks_count: u32,
|
||||||
|
/// Total number of unallocated inodes
|
||||||
|
free_inodes_count: u32,
|
||||||
|
/// Block number of the block containing the superblock
|
||||||
|
first_data_block: u32,
|
||||||
|
/// log2 (block size) - 10. (In other words, the number to shift 1,024
|
||||||
|
/// to the left by to obtain the block size)
|
||||||
|
log_block_size: u32,
|
||||||
|
/// log2 (fragment size) - 10. (In other words, the number to shift
|
||||||
|
/// 1,024 to the left by to obtain the fragment size)
|
||||||
|
log_frag_size: i32,
|
||||||
|
/// Number of blocks in each block group
|
||||||
|
blocks_per_group: u32,
|
||||||
|
/// Number of fragments in each block group
|
||||||
|
frags_per_group: u32,
|
||||||
|
/// Number of inodes in each block group
|
||||||
|
inodes_per_group: u32,
|
||||||
|
/// Last mount time (in POSIX time)
|
||||||
|
mtime: u32,
|
||||||
|
/// Last written time (in POSIX time)
|
||||||
|
wtime: u32,
|
||||||
|
/// Number of times the volume has been mounted since its last
|
||||||
|
/// consistency check (fsck)
|
||||||
|
mnt_count: u16,
|
||||||
|
/// Number of mounts allowed before a consistency check (fsck) must be
|
||||||
|
/// done
|
||||||
|
max_mnt_count: i16,
|
||||||
|
/// Ext2 signature (0xef53), used to help confirm the presence of Ext2
|
||||||
|
/// on a volume
|
||||||
|
magic: u16,
|
||||||
|
/// File system state (see `FS_CLEAN` and `FS_ERR`)
|
||||||
|
state: u16,
|
||||||
|
/// What to do when an error is detected (see `ERR_IGNORE`, `ERR_RONLY` and
|
||||||
|
/// `ERR_PANIC`)
|
||||||
|
errors: u16,
|
||||||
|
/// Minor portion of version (combine with Major portion below to
|
||||||
|
/// construct full version field)
|
||||||
|
rev_minor: u16,
|
||||||
|
/// POSIX time of last consistency check (fsck)
|
||||||
|
lastcheck: u32,
|
||||||
|
/// Interval (in POSIX time) between forced consistency checks (fsck)
|
||||||
|
checkinterval: u32,
|
||||||
|
/// Operating system ID from which the filesystem on this volume was
|
||||||
|
/// created
|
||||||
|
creator_os: u32,
|
||||||
|
/// Major portion of version (combine with Minor portion above to
|
||||||
|
/// construct full version field)
|
||||||
|
rev_major: u32,
|
||||||
|
/// User ID that can use reserved blocks
|
||||||
|
block_uid: u16,
|
||||||
|
/// Group ID that can use reserved blocks
|
||||||
|
block_gid: u16,
|
||||||
|
|
||||||
|
/// First non-reserved inode in file system.
|
||||||
|
first_inode: u32,
|
||||||
|
/// Size of each inode structure in bytes.
|
||||||
|
inode_size: u16,
|
||||||
|
/// Block group that this superblock is part of (if backup copy)
|
||||||
|
block_group: u16,
|
||||||
|
/// Optional features present (features that are not required to read
|
||||||
|
/// or write, but usually result in a performance increase)
|
||||||
|
features_opt: FeaturesOptional,
|
||||||
|
/// Required features present (features that are required to be
|
||||||
|
/// supported to read or write)
|
||||||
|
features_req: FeaturesRequired,
|
||||||
|
/// Features that if not supported, the volume must be mounted
|
||||||
|
/// read-only)
|
||||||
|
features_ronly: FeaturesROnly,
|
||||||
|
/// File system ID (what is output by blkid)
|
||||||
|
fs_id: [u8; 16],
|
||||||
|
/// Volume name (C-style string: characters terminated by a 0 byte)
|
||||||
|
volume_name: [u8; 16],
|
||||||
|
/// Path volume was last mounted to (C-style string: characters
|
||||||
|
/// terminated by a 0 byte)
|
||||||
|
last_mnt_path: [u8; 64],
|
||||||
|
/// Compression algorithms used (see Required features above)
|
||||||
|
compression: u32,
|
||||||
|
/// Number of blocks to preallocate for files
|
||||||
|
prealloc_blocks_files: u8,
|
||||||
|
/// Number of blocks to preallocate for directories
|
||||||
|
prealloc_blocks_dirs: u8,
|
||||||
|
#[doc(hidden)]
|
||||||
|
_unused: [u8; 2],
|
||||||
|
/// Journal ID (same style as the File system ID above)
|
||||||
|
journal_id: [u8; 16],
|
||||||
|
/// Journal inode
|
||||||
|
journal_inode: u32,
|
||||||
|
/// Journal device
|
||||||
|
journal_dev: u32,
|
||||||
|
/// Head of orphan inode list
|
||||||
|
journal_orphan_head: u32,
|
||||||
|
#[doc(hidden)]
|
||||||
|
_reserved: [u8; 788],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Superblock {
|
||||||
|
#[inline]
|
||||||
|
pub fn block_size(&self) -> usize {
|
||||||
|
1024 << self.log_block_size
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn frag_size(&self) -> usize {
|
||||||
|
1024 << self.log_frag_size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn block_group_count(&self) -> Result<u32, (u32, u32)> {
|
||||||
|
let blocks_mod = self.blocks_count % self.blocks_per_group;
|
||||||
|
let inodes_mod = self.inodes_count % self.inodes_per_group;
|
||||||
|
let blocks_inc = if blocks_mod == 0 { 0 } else { 1 };
|
||||||
|
let inodes_inc = if inodes_mod == 0 { 0 } else { 1 };
|
||||||
|
let by_blocks = self.blocks_count / self.blocks_per_group + blocks_inc;
|
||||||
|
let by_inodes = self.inodes_count / self.inodes_per_group + inodes_inc;
|
||||||
|
if by_blocks == by_inodes {
|
||||||
|
Ok(by_blocks)
|
||||||
|
} else {
|
||||||
|
Err((by_blocks, by_inodes))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
/// Optional features
|
||||||
|
pub struct FeaturesOptional: u32 {
|
||||||
|
/// Preallocate some number of (contiguous?) blocks (see
|
||||||
|
/// `Superblock::prealloc_blocks_dirs`) to a directory when creating a new one
|
||||||
|
const PREALLOCATE = 0x0001;
|
||||||
|
/// AFS server inodes exist
|
||||||
|
const AFS = 0x0002;
|
||||||
|
/// File system has a journal (Ext3)
|
||||||
|
const JOURNAL = 0x0004;
|
||||||
|
/// Inodes have extended attributes
|
||||||
|
const EXTENDED_INODE = 0x0008;
|
||||||
|
/// File system can resize itself for larger partitions
|
||||||
|
const SELF_RESIZE = 0x0010;
|
||||||
|
/// Directories use hash index
|
||||||
|
const HASH_INDEX = 0x0020;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
/// Required features. If these are not supported; can't mount
|
||||||
|
pub struct FeaturesRequired: u32 {
|
||||||
|
/// Compression is used
|
||||||
|
const REQ_COMPRESSION = 0x0001;
|
||||||
|
/// Directory entries contain a type field
|
||||||
|
const REQ_DIRECTORY_TYPE = 0x0002;
|
||||||
|
/// File system needs to replay its journal
|
||||||
|
const REQ_REPLAY_JOURNAL = 0x0004;
|
||||||
|
/// File system uses a journal device
|
||||||
|
const REQ_JOURNAL_DEVICE = 0x0008;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
/// ROnly features. If these are not supported; remount as read-only
|
||||||
|
pub struct FeaturesROnly: u32 {
|
||||||
|
/// Sparse superblocks and group descriptor tables
|
||||||
|
const RONLY_SPARSE = 0x0001;
|
||||||
|
/// File system uses a 64-bit file size
|
||||||
|
const RONLY_FILE_SIZE_64 = 0x0002;
|
||||||
|
/// Directory contents are stored in the form of a Binary Tree
|
||||||
|
const RONLY_BTREE_DIRECTORY = 0x0004;
|
||||||
|
}
|
||||||
|
}
|
Reference in a new issue