add some struct definitions

This commit is contained in:
Szymon Walter 2018-03-18 17:42:59 +01:00
parent 062e4847e1
commit 568ebd3207
4 changed files with 383 additions and 1 deletions

29
src/block_group.rs Normal file
View 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
View 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;
}
}

View file

@ -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
View 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;
}
}