### Read GPT from Disk Source: https://github.com/rust-disk-partition-management/gptman/blob/main/README.md Opens a disk image file and reads its GUID partition table. Prints the disk GUID and details of each used partition, including its type, size, and starting LBA. ```rust let mut f = std::fs::File::open("tests/fixtures/disk1.img") .expect("could not open disk"); let gpt = gptman::GPT::find_from(&mut f) .expect("could not find GPT"); println!("Disk GUID: {:?}", gpt.header.disk_guid); for (i, p) in gpt.iter() { if p.is_used() { println!("Partition #{}: type = {:?}, size = {} bytes, starting lba = {}", i, p.partition_type_guid, p.size().unwrap() * gpt.sector_size, p.starting_lba); } } ``` -------------------------------- ### Install GPTMan Crate Source: https://github.com/rust-disk-partition-management/gptman/blob/main/README.md Add the gptman crate to your Cargo.toml file to include it in your project dependencies. ```toml [dependencies] gptman = "3" ``` -------------------------------- ### Create a Fresh GPT (gptman) Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Initialize a new GPT on a writer (like a file or Cursor) with a specified sector size and disk GUID. All partition slots are pre-initialized to empty, and header fields are computed based on the writer's length. ```rust use std::io::Cursor; fn main() -> gptman::Result<()> { let sector_size: u64 = 512; // 50 MiB virtual disk let data = vec![0u8; 50 * 1024 * 1024]; let mut cur = Cursor::new(data); // Random-looking but deterministic disk GUID (use uuid crate in production) let disk_guid = [0xde, 0xad, 0xbe, 0xef, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]; let mut gpt = gptman::GPT::new_from(&mut cur, sector_size, disk_guid)?; println!("First usable LBA : {}", gpt.header.first_usable_lba); println!("Last usable LBA : {}", gpt.header.last_usable_lba); println!("Partition entries: {}", gpt.header.number_of_partition_entries); // First usable LBA : 34 // Last usable LBA : 102366 // Partition entries: 128 // Persist the empty table to the buffer gpt.write_into(&mut cur)?; Ok(()) } ``` -------------------------------- ### Write Primary and Backup GPT Headers Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Validates partition consistency and writes both primary and backup GPT headers to disk. Returns the backup GPTHeader on success. Ensure partition GUIDs are unique and within usable ranges. ```rust use std::io::Cursor; fn main() -> gptman::Result<()> { let ss: u64 = 512; let mut cur = Cursor::new(vec![0u8; 100 * ss as usize]); let mut gpt = gptman::GPT::new_from(&mut cur, ss, [0xff; 16])?; // Add a Linux data partition let linux_data_guid = [ 0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44, 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7, ]; gpt[1] = gptman::GPTPartitionEntry { partition_type_guid: linux_data_guid, unique_partition_guid: [0x01; 16], starting_lba: gpt.header.first_usable_lba, ending_lba: gpt.header.last_usable_lba, attribute_bits: 0, partition_name: "rootfs".into(), }; // write_into validates and writes both primary + backup headers let _backup_header = gpt.write_into(&mut cur)?; // Round-trip: read it back and confirm let gpt2 = gptman::GPT::read_from(&mut cur, ss)?; assert_eq!(gpt2[1].partition_name.as_str(), "rootfs"); println!("Written and verified successfully"); Ok(()) } ``` -------------------------------- ### Sort GPT Partitions by Starting LBA Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Sorts all used partition entries by `starting_lba` in ascending order, moving them to the beginning of the partition array. Unused entries are compacted to the end. This is useful after inserting partitions out of order. Ensure `gpt.align` is set appropriately if needed. ```rust use std::fs::File; fn main() -> gptman::Result<()> { let mut f = File::open("tests/fixtures/disk1.img")?; let mut gpt = gptman::GPT::find_from(&mut f)?; gpt.align = 1; let start = gpt.find_first_place(4).expect("no free space"); gpt[10] = gptman::GPTPartitionEntry { partition_type_guid: [0x01; 16], unique_partition_guid: [0x10; 16], starting_lba: start, ending_lba: start + 3, attribute_bits: 0, partition_name: "new-part".into(), }; println!("Before sort: {:?}", gpt.iter() .filter(|(_, p)| p.is_used()) .map(|(i, p)| (i, p.partition_name.as_str())) .collect::>()); gpt.sort(); println!("After sort: {:?}", gpt.iter() .filter(|(_, p)| p.is_used()) .map(|(i, p)| (i, p.partition_name.as_str())) .collect::>()); // After sort: [(1, "Foo"), (2, "new-part"), (3, "Bar")] Ok(()) } ``` -------------------------------- ### Create New Partition Entry Source: https://github.com/rust-disk-partition-management/gptman/blob/main/README.md Finds an unused partition slot and the maximum available partition size on a disk. It then creates a new GPT partition entry with specified GUIDs, name, and calculated LBA range. ```rust let mut f = std::fs::File::open("tests/fixtures/disk1.img") .expect("could not open disk"); let mut gpt = gptman::GPT::find_from(&mut f) .expect("could not find GPT"); let free_partition_number = gpt.iter().find(|(i, p)| p.is_unused()).map(|(i, _)| i) .expect("no more places available"); let size = gpt.get_maximum_partition_size() .expect("no more space available"); let starting_lba = gpt.find_optimal_place(size) .expect("could not find a place to put the partition"); let ending_lba = starting_lba + size - 1; gpt[free_partition_number] = gptman::GPTPartitionEntry { partition_type_guid: [0xff; 16], unique_partition_guid: [0xff; 16], starting_lba, ending_lba, attribute_bits: 0, partition_name: "A Robot Named Fight!".into(), }; ``` -------------------------------- ### GPTPartitionEntry Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Represents a 128-byte GPT partition record, including type GUID, unique GUID, LBA range, attribute bits, and UTF-16LE name. Provides methods to create unused entries, test their status, and compute size and range. ```APIDOC ## `GPTPartitionEntry` — Partition entry construction and inspection Represents a single 128-byte GPT partition record. Fields include type GUID, unique GUID, LBA range, attribute bits, and UTF-16LE name (up to 36 code units). `empty()` creates an unused entry; `is_used()` / `is_unused()` test the type GUID; `size()` and `range()` compute the sector count and inclusive range. ### Usage Example ```rust use std::io::Cursor; fn main() -> gptman::Result<()> { let ss: u64 = 512; let mut cur = Cursor::new(vec![0u8; 100 * ss as usize]); let mut gpt = gptman::GPT::new_from(&mut cur, ss, [0xff; 16])?; // Construct a partition entry let entry = gptman::GPTPartitionEntry { partition_type_guid: [0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_partition_guid: [0x99; 16], starting_lba: gpt.header.first_usable_lba, ending_lba: gpt.header.first_usable_lba + 2047, attribute_bits: 0, partition_name: "EFI System".into(), }; println!("Used? {}", entry.is_used()); // true println!("Size: {} sectors", entry.size()?); println!("Range: {:?}", entry.range()?); println!("Name: {}", entry.partition_name); // Empty (unused) entry let empty = gptman::GPTPartitionEntry::empty(); assert!(empty.is_unused()); assert_eq!(empty.partition_type_guid, [0u8; 16]); // Assign to slot 1 in the table gpt[1] = entry; assert!(gpt[1].is_used()); Ok(()) } ``` ``` -------------------------------- ### Linux ioctl Helpers: Get Sector Size and Reread Partition Table Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Demonstrates using `get_sector_size` to detect the logical sector size of a block device and `reread_partition_table` to notify the kernel of partition table changes. Requires root privileges to open block devices. ```rust #[cfg(all(target_os = "linux", feature = "nix"))] fn main() -> Result<(), Box> { use std::fs::OpenOptions; // Open a real block device (requires appropriate permissions, e.g. root) let mut dev = OpenOptions::new() .read(true) .write(true) .open("/dev/sda")?; // Auto-detect sector size match gptman::linux::get_sector_size(&mut dev) { Ok(ss) => println!("Sector size: {ss} bytes"), Err(gptman::linux::BlockError::NotBlock) => println!("Not a block device"), Err(e) => eprintln!("ioctl error: {e}"), } // Write a new GPT, then notify the kernel let ss = gptman::linux::get_sector_size(&mut dev)?; let mut gpt = gptman::GPT::find_from(&mut dev)?; // ... modify gpt ... gpt.write_into(&mut dev)?; // Ask the kernel to reread partition table match gptman::linux::reread_partition_table(&mut dev) { Ok(()) => println!("Kernel updated partition table"), Err(e) => eprintln!("Could not reread: {e}"), } Ok(()) } ``` -------------------------------- ### GPT::find_free_sectors Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Lists all unallocated disk regions within the usable area, returning a vector of tuples containing the starting LBA and the length in sectors. This method respects the `gpt.align` setting and is useful for diagnostics. ```APIDOC ## `GPT::find_free_sectors` — List unallocated disk regions Returns a `Vec<(starting_lba, length_in_sectors)>` of every free region in the usable area, automatically aligned to `gpt.align`. Used internally by the placement helpers, but also useful for diagnostics. ```rust use std::io::Cursor; fn main() -> gptman::Result<()> { let ss: u64 = 512; let mut cur = Cursor::new(vec![0u8; 100 * ss as usize]); let mut gpt = gptman::GPT::new_from(&mut cur, ss, [0xff; 16])?; gpt.align = 1; // no alignment padding for clarity // Carve out a partition in the middle gpt[1] = gptman::GPTPartitionEntry { partition_type_guid: [0xff; 16], unique_partition_guid: [0x01; 16], starting_lba: gpt.header.first_usable_lba + 5, ending_lba: gpt.header.last_usable_lba - 5, attribute_bits: 0, partition_name: "middle".into(), }; let free = gpt.find_free_sectors(); for (start, len) in &free { println!("Free: LBA {start} .. +{len} sectors ({} bytes)", len * ss); } // Free: LBA 34 .. +5 sectors (2560 bytes) // Free: LBA 61 .. +5 sectors (2560 bytes) Ok(()) } ``` ``` -------------------------------- ### Direct GPT Header Access and Manipulation Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Provides direct access to raw GPT header fields for reading, writing, and CRC32 checksum recomputation. Useful for fine-grained control over disk GUIDs or inspecting backup headers. ```rust use std::io::{Cursor, SeekFrom, Seek}; fn main() -> gptman::Result<()> { let ss: u64 = 512; let mut cur = Cursor::new(vec![0u8; 100 * ss as usize]); let mut gpt = gptman::GPT::new_from(&mut cur, ss, [0x42; 16])?; gpt.write_into(&mut cur)?; // Read the primary header directly cur.seek(SeekFrom::Start(ss)).unwrap(); let header = gptman::GPTHeader::read_from(&mut cur)?; println!("Primary? {}", header.is_primary()); // true println!("Backup? {}", header.is_backup()); // false println!("Disk GUID: {:02x?}", header.disk_guid); println!("Entries: {}", header.number_of_partition_entries); // Verify checksums are intact assert_eq!(header.crc32_checksum, header.generate_crc32_checksum()); // Read partition entries for this header let partitions = header.read_partitions(&mut cur, ss)?; let used: Vec<_> = partitions.iter().filter(|p| p.is_used()).collect(); println!("Used partitions: {}", used.len()); Ok(()) } ``` -------------------------------- ### GPT Partition Entry Construction and Inspection Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Represents a GPT partition record, including type and unique GUIDs, LBA range, attributes, and name. Use `empty()` for unused entries and `is_used()`/`is_unused()` to test status. Computes size and range. ```rust use std::io::Cursor; fn main() -> gptman::Result<()> { let ss: u64 = 512; let mut cur = Cursor::new(vec![0u8; 100 * ss as usize]); let mut gpt = gptman::GPT::new_from(&mut cur, ss, [0xff; 16])?; // Construct a partition entry let entry = gptman::GPTPartitionEntry { partition_type_guid: [0xef, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_partition_guid: [0x99; 16], starting_lba: gpt.header.first_usable_lba, ending_lba: gpt.header.first_usable_lba + 2047, attribute_bits: 0, partition_name: "EFI System".into(), }; println!("Used? {}", entry.is_used()); // true println!("Size: {} sectors", entry.size()?); println!("Range: {:?}", entry.range()?); println!("Name: {}", entry.partition_name); // Empty (unused) entry let empty = gptman::GPTPartitionEntry::empty(); assert!(empty.is_unused()); assert_eq!(empty.partition_type_guid, [0u8; 16]); // Assign to slot 1 in the table gpt[1] = entry; assert!(gpt[1].is_used()); Ok(()) } ``` -------------------------------- ### Get Maximum Contiguous Partition Size Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Returns the size of the largest contiguous free region, aligned to `gpt.align`. Returns `Err(Error::NoSpaceLeft)` if the disk is full. This is useful for determining the largest possible single partition. ```rust use std::io::Cursor; fn main() -> gptman::Result<()> { let ss: u64 = 512; let mut cur = Cursor::new(vec![0u8; 100 * ss as usize]); let mut gpt = gptman::GPT::new_from(&mut cur, ss, [0xff; 16])?; gpt.align = 1; let max = gpt.get_maximum_partition_size()?; println!("Max partition size: {max} sectors ({} bytes)", max * ss); // After filling the disk, no space remains gpt[1] = gptman::GPTPartitionEntry { partition_type_guid: [0xff; 16], unique_partition_guid: [0x01; 16], starting_lba: gpt.header.first_usable_lba, ending_lba: gpt.header.last_usable_lba, attribute_bits: 0, partition_name: "full".into(), }; assert!(matches!( gpt.get_maximum_partition_size(), Err(gptman::Error::NoSpaceLeft) )); Ok(()) } ``` -------------------------------- ### GPTHeader Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Provides direct access and manipulation methods for GPT header fields, including reading, writing, and recomputing CRC32 checksums. Useful for fine-grained control over header values like disk GUID and backup header inspection. ```APIDOC ## `GPTHeader` — Direct header access and manipulation `GPTHeader` exposes all raw GPT header fields and provides methods to read, write, and recompute CRC32 checksums. Useful when you need fine-grained control over header values (e.g., changing the disk GUID or inspecting backup header fields). ### Usage Example ```rust use std::io::{Cursor, SeekFrom, Seek}; fn main() -> gptman::Result<()> { let ss: u64 = 512; let mut cur = Cursor::new(vec![0u8; 100 * ss as usize]); let mut gpt = gptman::GPT::new_from(&mut cur, ss, [0x42; 16])?; gpt.write_into(&mut cur)?; // Read the primary header directly cur.seek(SeekFrom::Start(ss)).unwrap(); let header = gptman::GPTHeader::read_from(&mut cur)?; println!("Primary? {}", header.is_primary()); // true println!("Backup? {}", header.is_backup()); // false println!("Disk GUID: {:02x?}", header.disk_guid); println!("Entries: {}", header.number_of_partition_entries); // Verify checksums are intact assert_eq!(header.crc32_checksum, header.generate_crc32_checksum()); // Read partition entries for this header let partitions = header.read_partitions(&mut cur, ss)?; let used: Vec<_> = partitions.iter().filter(|p| p.is_used()).collect(); println!("Used partitions: {}", used.len()); Ok(()) } ``` ``` -------------------------------- ### Convert GPT Partition Sector Range to Byte Range Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Calculates the byte offset range for a given partition, relative to the start of the disk. This is useful for direct I/O operations like reading or writing raw partition data using `seek`. An invalid partition number will return an error. ```rust use std::io::Cursor; fn main() -> gptman::Result<()> { let ss: u64 = 512; let mut cur = Cursor::new(vec![0u8; 100 * ss as usize]); let mut gpt = gptman::GPT::new_from(&mut cur, ss, [0xff; 16])?; gpt[1] = gptman::GPTPartitionEntry { partition_type_guid: [0xff; 16], unique_partition_guid: [0x01; 16], starting_lba: 2048, ending_lba: 2048, // 1-sector partition attribute_bits: 0, partition_name: "tiny".into(), }; let range = gpt.get_partition_byte_range(1)?; println!("Byte range: {range:?}"); // Byte range: 1048576..=1049087 (2048 * 512 = 1 MiB start) assert!(matches!( gpt.get_partition_byte_range(0), Err(gptman::Error::InvalidPartitionNumber(0)) )); Ok(()) } ``` -------------------------------- ### GPT::sort Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Reorders all used partition entries by their starting LBA in ascending order. This operation compacts the used entries to the beginning of the partition array and moves unused entries to the end. It is particularly useful after inserting new partitions that might not be in sequential order. ```APIDOC ## `GPT::sort` — Reorder entries by starting LBA Sorts all used partition entries by `starting_lba` ascending, compacting them to the front of the 128-slot array. Unused entries are moved to the end. Useful after inserting partitions out of order. ### Usage ```rust use std::fs::File; fn main() -> gptman::Result<()> { let mut f = File::open("tests/fixtures/disk1.img")?; let mut gpt = gptman::GPT::find_from(&mut f)?; gpt.align = 1; let start = gpt.find_first_place(4).expect("no free space"); gpt[10] = gptman::GPTPartitionEntry { partition_type_guid: [0x01; 16], unique_partition_guid: [0x10; 16], starting_lba: start, ending_lba: start + 3, attribute_bits: 0, partition_name: "new-part".into(), }; println!("Before sort: {:?}", gpt.iter() .filter(|(_, p)| p.is_used()) .map(|(i, p)| (i, p.partition_name.as_str())) .collect::>()); gpt.sort(); println!("After sort: {:?}", gpt.iter() .filter(|(_, p)| p.is_used()) .map(|(i, p)| (i, p.partition_name.as_str())) .collect::>()); // After sort: [(1, "Foo"), (2, "new-part"), (3, "Bar")] Ok(()) } ``` ``` -------------------------------- ### GPT::new_from Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Initializes a blank partition table on any `Read + Seek` writer. All 128 partition slots are pre-populated with empty entries. The header LBA fields are computed from the actual length of the reader. ```APIDOC ## GPT::new_from — Create a fresh GPT ### Description Initializes a blank partition table on any `Read + Seek` writer (file, `Cursor`, etc.). All 128 partition slots are pre-populated with empty entries. The header LBA fields are computed from the actual length of the reader. ### Method ```rust GPT::new_from(writer: &mut impl std::io::Write + std::io::Seek, sector_size: u64, disk_guid: [u8; 16]) ``` ### Parameters * **writer** (`impl std::io::Write + std::io::Seek`): A mutable reference to a type that implements `Write` and `Seek` traits, where the new GPT will be initialized. * **sector_size** (`u64`): The sector size in bytes for the new GPT. * **disk_guid** (`[u8; 16]`): A 16-byte array representing the unique disk GUID. ### Request Example ```rust use std::io::Cursor; fn main() -> gptman::Result<()> { let sector_size: u64 = 512; // 50 MiB virtual disk let data = vec![0u8; 50 * 1024 * 1024]; let mut cur = Cursor::new(data); // Random-looking but deterministic disk GUID (use uuid crate in production) let disk_guid = [0xde, 0xad, 0xbe, 0xef, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb]; let mut gpt = gptman::GPT::new_from(&mut cur, sector_size, disk_guid)?; println!("First usable LBA : {}", gpt.header.first_usable_lba); println!("Last usable LBA : {}", gpt.header.last_usable_lba); println!("Partition entries: {}", gpt.header.number_of_partition_entries); // Persist the empty table to the buffer gpt.write_into(&mut cur)?; Ok(()) } ``` ### Response #### Success Response A `gptman::GPT` struct representing the newly created blank partition table. #### Response Example ```rust // Example output structure (actual values depend on sector size and disk size) // First usable LBA : 34 // Last usable LBA : 102366 // Partition entries: 128 ``` ``` -------------------------------- ### GPT Partition Placement Helpers Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Provides three strategies for finding a suitable LBA for a new partition of a given size, all respecting `gpt.align`. `find_first_place` locates the lowest available slot, `find_last_place` finds the highest, and `find_optimal_place` selects the smallest free region that fits to minimize fragmentation. ```APIDOC ## `GPT::find_first_place` / `find_last_place` / `find_optimal_place` — Partition placement helpers Three strategies for locating a suitable LBA for a new partition of a given size, all honoring `gpt.align`. `find_first_place` returns the lowest available slot, `find_last_place` the highest, and `find_optimal_place` picks the smallest free region that fits (best-fit, minimizing fragmentation). ```rust use std::fs::File; fn main() -> gptman::Result<()> { let mut f = File::open("tests/fixtures/disk1.img")?; let mut gpt = gptman::GPT::find_from(&mut f)?; gpt.align = 1; // disable alignment for this example let needed = 4; // sectors if let Some(lba) = gpt.find_first_place(needed) { println!("First available at LBA {lba}"); } if let Some(lba) = gpt.find_last_place(needed) { println!("Last available at LBA {lba}"); } if let Some(lba) = gpt.find_optimal_place(needed) { println!("Optimal placement at LBA {lba}"); } if gpt.find_first_place(999_999).is_none() { println!("Not enough space for 999999 sectors"); } Ok(()) } ``` ``` -------------------------------- ### Create New GPT with Single Full-Disk Partition Source: https://github.com/rust-disk-partition-management/gptman/blob/main/README.md Initializes a new GPT on a memory buffer with a specified sector size. It then creates a single partition entry that spans the entire usable space of the disk. ```rust let ss = 512; let data = vec![0; 100 * ss as usize]; let mut cur = std::io::Cursor::new(data); let mut gpt = gptman::GPT::new_from(&mut cur, ss as u64, [0xff; 16]) .expect("could not create partition table"); gpt[1] = gptman::GPTPartitionEntry { partition_type_guid: [0xff; 16], unique_partition_guid: [0xff; 16], starting_lba: gpt.header.first_usable_lba, ending_lba: gpt.header.last_usable_lba, attribute_bits: 0, partition_name: "A Robot Named Fight!".into(), }; ``` -------------------------------- ### Find Suitable Partition Placement LBAs Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Locates suitable LBAs for new partitions, honoring `gpt.align`. `find_first_place` finds the lowest, `find_last_place` the highest, and `find_optimal_place` the smallest fitting region to minimize fragmentation. Ensure sufficient space is available. ```rust use std::fs::File; fn main() -> gptman::Result<()> { let mut f = File::open("tests/fixtures/disk1.img")?; let mut gpt = gptman::GPT::find_from(&mut f)?; gpt.align = 1; // disable alignment for this example let needed = 4; // sectors if let Some(lba) = gpt.find_first_place(needed) { println!("First available at LBA {lba}"); } if let Some(lba) = gpt.find_last_place(needed) { println!("Last available at LBA {lba}"); } if let Some(lba) = gpt.find_optimal_place(needed) { println!("Optimal placement at LBA {lba}"); } if gpt.find_first_place(999_999).is_none() { println!("Not enough space for 999999 sectors"); } Ok(()) } ``` -------------------------------- ### Auto-detect Sector Size and Read GPT (gptman) Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Use `find_from` to automatically detect the sector size (512 or 4096 bytes) and read the GPT from a disk image or device. It handles primary/backup header redundancy and provides partition details. ```rust use std::fs::File; fn main() -> gptman::Result<()> { // Works transparently for both 512-byte and 4096-byte sector disks let mut f = File::open("tests/fixtures/disk1.img")?; let gpt = gptman::GPT::find_from(&mut f)?; println!("Disk GUID : {:02x?}", gpt.header.disk_guid); println!("Sector size: {} bytes", gpt.sector_size); println!("Alignment : {} sectors", gpt.align); for (i, p) in gpt.iter().filter(|(_, p)| p.is_used()) { println!( "Partition #{i}: name={}, size={} bytes, start_lba={}", p.partition_name, p.size()? * gpt.sector_size, p.starting_lba, ); } // Output (disk1.img): // Disk GUID : [...] // Sector size: 512 bytes // Partition #1: name=Foo, size=..., start_lba=... // Partition #2: name=Bar, size=..., start_lba=... Ok(()) } ``` -------------------------------- ### GPT::find_from Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Attempts to parse the GPT using a 512-byte sector size first, retrying with 4096 bytes if the signature is invalid. It falls back to the backup header when the primary is corrupted. This is the recommended entry point for reading an existing disk image. ```APIDOC ## GPT::find_from — Auto-detect sector size and read GPT ### Description Attempts to parse the GPT using a 512-byte sector size first; if the signature is invalid it retries with 4096 bytes. Falls back to the backup header when the primary is corrupted. This is the recommended entry point for reading an existing disk image. ### Method ```rust GPT::find_from(reader: &mut impl std::io::Read + std::io::Seek) ``` ### Parameters None explicitly documented beyond the generic `Read + Seek` trait bound for the reader. ### Request Example ```rust use std::fs::File; fn main() -> gptman::Result<()> { // Works transparently for both 512-byte and 4096-byte sector disks let mut f = File::open("tests/fixtures/disk1.img")?; let gpt = gptman::GPT::find_from(&mut f)?; println!("Disk GUID : {:02x?}", gpt.header.disk_guid); println!("Sector size: {} bytes", gpt.sector_size); println!("Alignment : {} sectors", gpt.align); for (i, p) in gpt.iter().filter(|(_, p)| p.is_used()) { println!( "Partition #{i}: name={}, size={} bytes, start_lba={}", p.partition_name, p.size()? * gpt.sector_size, p.starting_lba, ); } Ok(()) } ``` ### Response #### Success Response A `gptman::GPT` struct containing the parsed partition table information. #### Response Example ```rust // Example output structure (actual values depend on the disk image) // Disk GUID : [...] // Sector size: 512 bytes // Partition #1: name=Foo, size=..., start_lba=... // Partition #2: name=Bar, size=..., start_lba=... ``` ``` -------------------------------- ### GPT::write_into Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Validates partition consistency and writes both primary and backup GPT headers along with their partition arrays to the disk. It returns the backup GPTHeader on success. ```APIDOC ## `GPT::write_into` — Write primary and backup headers to disk Validates partition consistency (unique GUIDs, no overlaps, all within usable range) then writes both the primary header (LBA 1) and the backup header (last LBA) along with their partition arrays. Returns the backup `GPTHeader` on success. ```rust use std::io::Cursor; fn main() -> gptman::Result<()> { let ss: u64 = 512; let mut cur = Cursor::new(vec![0u8; 100 * ss as usize]); let mut gpt = gptman::GPT::new_from(&mut cur, ss, [0xff; 16])?; // Add a Linux data partition let linux_data_guid = [ 0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44, 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7, ]; gpt[1] = gptman::GPTPartitionEntry { partition_type_guid: linux_data_guid, unique_partition_guid: [0x01; 16], starting_lba: gpt.header.first_usable_lba, ending_lba: gpt.header.last_usable_lba, attribute_bits: 0, partition_name: "rootfs".into(), }; // write_into validates and writes both primary + backup headers let _backup_header = gpt.write_into(&mut cur)?; // Round-trip: read it back and confirm let gpt2 = gptman::GPT::read_from(&mut cur, ss)?; assert_eq!(gpt2[1].partition_name.as_str(), "rootfs"); println!("Written and verified successfully"); Ok(()) } ``` ``` -------------------------------- ### Run Tests in gptman Source: https://github.com/rust-disk-partition-management/gptman/blob/main/CONTRIBUTING.md Execute the test suite for the entire workspace. Use `--no-default-features` to test without default features enabled. ```sh cargo test --workspace ``` ```sh cargo test --workspace --no-default-features ``` -------------------------------- ### GPT::write_protective_mbr_into / write_bootable_protective_mbr_into Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Writes a protective MBR (pMBR) partition record. The standard variant sets the bootable flag to 0x00, while the bootable variant sets it to 0x80 for legacy BIOS systems. ```APIDOC ## `GPT::write_protective_mbr_into` / `write_bootable_protective_mbr_into` — Write protective MBR Writes a protective MBR (pMBR) partition record starting at byte offset 446. The plain variant sets the bootable flag to `0x00`; the bootable variant sets it to `0x80` for legacy BIOS systems that require a bootable MBR entry (avoid on UEFI-only systems). ### Usage Example ```rust use std::io::Cursor; fn main() -> gptman::Result<()> { let ss: u64 = 512; let mut cur = Cursor::new(vec![0u8; 100 * ss as usize]); // Standard pMBR (UEFI compatible) gptman::GPT::write_protective_mbr_into(&mut cur, ss)?; let data = cur.get_ref(); assert_eq!(data[510], 0x55); // MBR signature low byte assert_eq!(data[511], 0xaa); // MBR signature high byte assert_eq!(data[446 + 4], 0xee); // GPT protective partition type // Legacy BIOS variant (sets bootable flag 0x80) let mut cur2 = Cursor::new(vec![0u8; 100 * ss as usize]); gptman::GPT::write_bootable_protective_mbr_into(&mut cur2, ss)?; assert_eq!(cur2.get_ref()[446], 0x80); // bootable flag Ok(()) } ``` ``` -------------------------------- ### List Unallocated Disk Regions Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Returns a list of free regions on the disk, useful for diagnostics. Automatically aligns to `gpt.align`. Ensure `gpt.align` is set appropriately for desired alignment. ```rust use std::io::Cursor; fn main() -> gptman::Result<()> { let ss: u64 = 512; let mut cur = Cursor::new(vec![0u8; 100 * ss as usize]); let mut gpt = gptman::GPT::new_from(&mut cur, ss, [0xff; 16])?; gpt.align = 1; // no alignment padding for clarity // Carve out a partition in the middle gpt[1] = gptman::GPTPartitionEntry { partition_type_guid: [0xff; 16], unique_partition_guid: [0x01; 16], starting_lba: gpt.header.first_usable_lba + 5, ending_lba: gpt.header.last_usable_lba - 5, attribute_bits: 0, partition_name: "middle".into(), }; let free = gpt.find_free_sectors(); for (start, len) in &free { println!("Free: LBA {start} .. +{len} sectors ({} bytes)", len * ss); } // Free: LBA 34 .. +5 sectors (2560 bytes) // Free: LBA 61 .. +5 sectors (2560 bytes) Ok(()) } ``` -------------------------------- ### Read GPT with Explicit Sector Size (gptman) Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Use `read_from` when the sector size is known precisely, such as when processing multiple images in a batch. Incorrect sector sizes will result in an error. ```rust use std::fs::File; fn main() -> gptman::Result<()> { // 512-byte sectors (standard HDD/SSD) let mut f512 = File::open("tests/fixtures/disk1.img")?; let gpt = gptman::GPT::read_from(&mut f512, 512)?; assert_eq!(gpt.sector_size, 512); // 4096-byte sectors (Advanced Format / large drives) let mut f4k = File::open("tests/fixtures/disk2.img")?; let gpt4k = gptman::GPT::read_from(&mut f4k, 4096)?; assert_eq!(gpt4k.sector_size, 4096); // Reading with the wrong sector size returns an error let mut f_wrong = File::open("tests/fixtures/disk1.img")?; assert!(gptman::GPT::read_from(&mut f_wrong, 4096).is_err()); Ok(()) } ``` -------------------------------- ### GPT::read_from Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Reads the partition table using a caller-specified sector size. Use `find_from` when the sector size is unknown; use `read_from` when you know it precisely (e.g., when processing multiple images in batch). ```APIDOC ## GPT::read_from — Read GPT with explicit sector size ### Description Reads the partition table using a caller-specified sector size. Use `find_from` when the sector size is unknown; use `read_from` when you know it precisely (e.g., when processing multiple images in batch). ### Method ```rust GPT::read_from(reader: &mut impl std::io::Read + std::io::Seek, sector_size: u64) ``` ### Parameters * **reader** (`impl std::io::Read + std::io::Seek`): A mutable reference to a type that implements `Read` and `Seek` traits, representing the disk or image. * **sector_size** (`u64`): The explicit sector size in bytes to use for reading the GPT. ### Request Example ```rust use std::fs::File; fn main() -> gptman::Result<()> { // 512-byte sectors (standard HDD/SSD) let mut f512 = File::open("tests/fixtures/disk1.img")?; let gpt = gptman::GPT::read_from(&mut f512, 512)?; assert_eq!(gpt.sector_size, 512); // 4096-byte sectors (Advanced Format / large drives) let mut f4k = File::open("tests/fixtures/disk2.img")?; let gpt4k = gptman::GPT::read_from(&mut f4k, 4096)?; assert_eq!(gpt4k.sector_size, 4096); // Reading with the wrong sector size returns an error let mut f_wrong = File::open("tests/fixtures/disk1.img")?; assert!(gptman::GPT::read_from(&mut f_wrong, 4096).is_err()); Ok(()) } ``` ### Response #### Success Response A `gptman::GPT` struct containing the parsed partition table information. #### Response Example ```rust // Example output structure (actual values depend on the disk image and sector size) // assert_eq!(gpt.sector_size, 512); // assert_eq!(gpt4k.sector_size, 4096); ``` ``` -------------------------------- ### Remove GPT Partition by Index or Sector Source: https://context7.com/rust-disk-partition-management/gptman/llms.txt Demonstrates removing a partition by its 1-based index or by any sector LBA within its range. The partition slot is cleared, but disk data remains until `write_into` is called. An invalid partition number (e.g., 0) will result in an error. ```rust use std::fs::File; fn main() -> gptman::Result<()> { let mut f = File::open("tests/fixtures/disk1.img")?; let mut gpt = gptman::GPT::find_from(&mut f)?; let used_before: Vec = gpt.iter() .filter(|(_, p)| p.is_used()) .map(|(i, _)| i) .collect(); println!("Used before: {used_before:?}"); // Remove by partition number gpt.remove(1)?; // Remove by sector (any LBA within the partition) let sector = gpt.iter() .find(|(_, p)| p.is_used()) .map(|(_, p)| p.starting_lba); if let Some(lba) = sector { gpt.remove_at_sector(lba)?; } // Invalid partition number returns an error assert!(matches!( gpt.remove(0), Err(gptman::Error::InvalidPartitionNumber(0)) )); Ok(()) } ```