file_system/mbr/
utilities.rs

1//! Utility functions for Master Boot Record (MBR) operations.
2
3//!
4//! This module provides high-level utility functions for working with MBR partition tables,
5//! including creating partition devices, scanning for partitions, validation, and disk formatting.
6//! These utilities simplify common MBR operations and provide comprehensive error handling.
7
8use alloc::vec::Vec;
9
10use super::Mbr;
11use crate::{Device, Error, PartitionDevice, PartitionEntry, Result};
12
13/// Create a partition device from an MBR partition entry.
14///
15/// This function takes a base device and a partition entry from an MBR, and creates
16/// a [`PartitionDevice`] that represents just that partition. The resulting
17/// partition device can be used for all standard device operations, but will only
18/// access the sectors allocated to that specific partition.
19///
20/// # Arguments
21///
22/// * `Base_device` - The underlying storage device containing the partition
23/// * `Partition` - MBR partition entry describing the partition layout
24///
25/// # Returns
26///
27/// * `Ok(Partition_device_type)` - Successfully created partition device
28/// * `Err(Error::InvalidParameter)` - Partition entry is invalid
29///
30/// # Examples
31///
32/// ```rust
33/// extern crate alloc;
34/// use file_system::*;
35///
36/// let device = create_device!(Memory_device_type::<512>::new(4 * 1024 * 1024));
37/// // First create and write an MBR to the device
38/// let mut mbr = MBR_type::New_with_signature(0x12345678);
39/// mbr.Add_partition(Partition_type_type::Fat32_lba, 2048, 1024, true).unwrap();
40/// mbr.Write_to_device(&device).unwrap();
41///
42/// // Now read it back and create partition device
43/// let mbr = MBR_type::Read_from_device(&device).unwrap();
44/// if let Some(partition) = mbr.get_valid_partitions().first() {
45///     let partition_device = Create_partition_device(device, partition).unwrap();
46///     // Now you can use partition_device for I/O operations
47/// }
48/// ```
49pub fn create_partition_device(
50    base_device: Device,
51    partition: &PartitionEntry,
52) -> Result<PartitionDevice> {
53    if !partition.is_valid() {
54        return Err(Error::InvalidParameter);
55    }
56
57    Ok(PartitionDevice::new_from_lba(
58        base_device,
59        partition.get_start_lba(),
60        partition.get_size_sectors(),
61    ))
62}
63
64/// Scan a device for MBR and return partition information.
65///
66/// This function reads the MBR from a device and extracts information about all
67/// valid partitions. It returns a vector of tuples containing the partition index
68/// and the partition entry for each valid partition found.
69///
70/// # Arguments
71///
72/// * `Device` - The storage device to scan for MBR partitions
73///
74/// # Returns
75///
76/// * `Ok(Vec<(usize, Partition_entry_type)>)` - List of valid partitions with their indices
77/// * `Err(Error)` - Error reading MBR or device access failure
78///
79/// # Examples
80///
81/// ```rust
82/// extern crate alloc;
83/// use file_system::*;
84///
85/// let device = create_device!(Memory_device_type::<512>::new(4 * 1024 * 1024));
86///
87/// match Scan_mbr_partitions(&device) {
88///     Ok(partitions) => {
89///         println!("Found {} valid partitions", partitions.len());
90///         for (index, partition) in partitions {
91///             println!("Partition {}: {:?}", index, partition.get_partition_type());
92///         }
93///     }
94///     Err(e) => println!("Failed to scan partitions: {}", e),
95/// }
96/// ```
97pub fn scan_mbr_partitions(device: &Device) -> Result<Vec<(usize, PartitionEntry)>> {
98    let mbr = Mbr::read_from_device(device)?;
99
100    let mut partitions = Vec::new();
101    for (i, partition) in mbr.partitions.iter().enumerate() {
102        if partition.is_valid() {
103            partitions.push((i, *partition));
104        }
105    }
106
107    Ok(partitions)
108}
109
110/// Validate MBR structure and partitions for consistency and correctness.
111///
112/// This function performs comprehensive validation of an MBR structure, checking:
113/// - MBR signature validity (0x55AA boot signature)
114/// - Partition overlap detection
115/// - Bootable partition count (at most one partition should be bootable)
116///
117/// # Arguments
118///
119/// * `Mbr` - The MBR structure to validate
120///
121/// # Returns
122///
123/// * `Ok(())` - MBR is valid and consistent
124/// * `Err(Error::Corrupted)` - MBR is invalid or corrupted
125///
126/// # Examples
127///
128/// ```rust
129/// extern crate alloc;
130/// use file_system::*;
131///
132/// let device = create_device!(Memory_device_type::<512>::new(4 * 1024 * 1024));
133/// // First create and write a valid MBR
134/// let mut mbr = MBR_type::New_with_signature(0x12345678);
135/// mbr.Add_partition(Partition_type_type::Fat32_lba, 2048, 1024, true).unwrap();
136/// mbr.Write_to_device(&device).unwrap();
137///
138/// // Read it back and validate
139/// let mbr = MBR_type::Read_from_device(&device).unwrap();
140/// match mbr.Validate() {
141///     Ok(()) => println!("MBR is valid"),
142///     Err(Error::Corrupted) => println!("MBR is corrupted"),
143///     Err(e) => println!("Validation error: {}", e),
144/// }
145/// ```
146pub fn validate_mbr(mbr: &crate::Mbr) -> Result<()> {
147    mbr.validate()
148}
149
150/// Create partition devices for all valid partitions in an MBR.
151///
152/// This function iterates through all partition entries in an MBR and creates
153/// [`PartitionDevice`] instances for each valid partition. This is useful
154/// when you need to access all partitions on a disk programmatically.
155///
156/// # Arguments
157///
158/// * `Base_device` - The underlying storage device containing all partitions
159/// * `Mbr` - The MBR structure containing partition information
160///
161/// # Returns
162///
163/// * `Ok(Vec<PartitionDevice>)` - Vector of partition devices for all valid partitions
164/// * `Err(Error)` - Error if any partition device creation fails
165///
166/// # Examples
167///
168/// ```rust
169/// extern crate alloc;
170/// use file_system::*;
171///
172/// let device = create_device!(Memory_device_type::<512>::new(4 * 1024 * 1024));
173/// // Create an MBR with multiple partitions
174/// let mut mbr = MBR_type::New_with_signature(0x12345678);
175/// mbr.Add_partition(Partition_type_type::Fat32_lba, 2048, 1024, true).unwrap();
176/// mbr.Add_partition(Partition_type_type::Linux, 4096, 2048, false).unwrap();
177/// mbr.Write_to_device(&device).unwrap();
178///
179/// // Read it back and create all partition devices
180/// let mbr = MBR_type::Read_from_device(&device).unwrap();
181/// let partition_devices = mbr.Create_all_partition_devices(device).unwrap();
182/// println!("Created {} partition devices", partition_devices.len());
183///
184/// for (i, partition) in partition_devices.iter().enumerate() {
185///     println!("Partition {}: {} sectors", i, partition.get_sector_count());
186/// }
187/// ```
188pub fn create_all_partition_devices(
189    base_device: Device,
190    mbr: &super::Mbr,
191) -> Result<Vec<PartitionDevice>> {
192    mbr.create_all_partition_devices(base_device)
193}
194
195/// Find partitions of a specific type within an MBR.
196///
197/// This function searches through all partitions in an MBR and returns references
198/// to those that match the specified partition type. This is useful for locating
199/// specific types of partitions (e.g., FAT32, Linux, etc.) without creating
200/// partition devices.
201///
202/// # Arguments
203///
204/// * `Mbr` - The MBR structure to search through
205/// * `Partition_type` - The specific partition type to find
206///
207/// # Returns
208///
209/// A vector of tuples containing the partition index and reference to the partition entry
210/// for each matching partition.
211///
212/// # Examples
213///
214/// ```rust
215/// extern crate alloc;
216/// use file_system::*;
217///
218/// let device = create_device!(Memory_device_type::<512>::new(4 * 1024 * 1024));
219/// // Create an MBR with FAT32 partition
220/// let mut mbr = MBR_type::New_with_signature(0x12345678);
221/// mbr.Add_partition(Partition_type_type::Fat32_lba, 2048, 1024, true).unwrap();
222/// mbr.Write_to_device(&device).unwrap();
223///
224/// // Read it back and find FAT32 partitions
225/// let mbr = MBR_type::Read_from_device(&device).unwrap();
226/// let fat32_partitions = mbr.Find_partitions_by_type(Partition_type_type::Fat32_lba);
227/// println!("Found {} FAT32 partitions", fat32_partitions.len());
228/// ```
229pub fn find_partitions_by_type(
230    mbr: &super::Mbr,
231    partition_type: crate::PartitionKind,
232) -> Vec<(usize, &PartitionEntry)> {
233    mbr.find_partitions_by_type(partition_type)
234}
235
236/// Check if a device contains a valid MBR.
237///
238/// This function attempts to read an MBR from the device and validates its signature.
239/// It's a quick way to determine if a device has been properly partitioned with MBR.
240///
241/// # Arguments
242///
243/// * `Device` - The storage device to check
244///
245/// # Returns
246///
247/// * `true` - Device contains a valid MBR with proper signature
248/// * `false` - Device doesn't contain a valid MBR or cannot be read
249///
250/// # Examples
251///
252/// ```rust
253/// extern crate alloc;
254/// use file_system::*;
255///
256/// let device = create_device!(Memory_device_type::<512>::new(4 * 1024 * 1024));
257///
258/// if Has_valid_mbr(&device) {
259///     println!("Device has a valid MBR");
260/// } else {
261///     println!("Device needs to be partitioned");
262/// }
263/// ```
264pub fn has_valid_mbr(device: &Device) -> bool {
265    match Mbr::read_from_device(device) {
266        Ok(mbr) => mbr.is_valid(),
267        Err(_) => false,
268    }
269}
270
271/// Check if a device uses GPT (GUID Partition Table) instead of MBR.
272///
273/// This function checks if the device contains a GPT protective partition in its MBR,
274/// which indicates that the device uses GPT partitioning instead of traditional MBR.
275/// GPT is the modern replacement for MBR and supports larger disks and more partitions.
276///
277/// # Arguments
278///
279/// * `Device` - The storage device to check
280///
281/// # Returns
282///
283/// * `true` - Device uses GPT partitioning (has protective MBR)
284/// * `false` - Device uses traditional MBR or cannot be read
285///
286/// # Examples
287///
288/// ```rust
289/// extern crate alloc;
290/// use file_system::*;
291///
292/// let device = create_device!(Memory_device_type::<512>::new(4 * 1024 * 1024));
293///
294/// if is_gpt_disk(&device) {
295///     println!("Device uses GPT partitioning");
296/// } else {
297///     println!("Device uses MBR partitioning");
298/// }
299/// ```
300pub fn is_gpt_disk(device: &Device) -> bool {
301    match Mbr::read_from_device(device) {
302        Ok(mbr) => mbr.has_gpt_protective_partition(),
303        Err(_) => false,
304    }
305}
306
307/// Create a basic MBR with a single partition covering most of the disk.
308///
309/// This function creates a simple MBR structure with one partition that uses
310/// most of the available disk space. It leaves 2048 sectors at the beginning
311/// for proper alignment, which is standard practice for modern storage devices.
312///
313/// # Arguments
314///
315/// * `Disk_signature` - Unique 32-bit signature for the disk
316/// * `Partition_type` - Type of partition to create (e.g., FAT32, Linux, etc.)
317/// * `Total_sectors` - Total number of sectors available on the disk
318///
319/// # Returns
320///
321/// * `Ok(MBR_type)` - Successfully created MBR with single partition
322/// * `Err(Error::InvalidParameter)` - Disk is too small for a partition
323///
324/// # Examples
325///
326/// ```rust
327/// use file_system::*;
328///
329/// // Create MBR for a 4MB device (8192 sectors)
330/// let mbr = MBR_type::Create_basic(0x12345678, Partition_type_type::Fat32_lba, 8192).unwrap();
331///
332/// // The MBR will have one FAT32 partition starting at sector 2048
333/// let partitions = mbr.get_valid_partitions();
334/// assert_eq!(partitions.len(), 1);
335/// assert_eq!(partitions[0].get_start_lba(), 2048);
336/// ```
337pub fn create_basic_mbr(
338    disk_signature: u32,
339    partition_type: crate::PartitionKind,
340    total_sectors: u32,
341) -> Result<super::Mbr> {
342    Mbr::create_basic(disk_signature, partition_type, total_sectors)
343}
344
345/// Clone an MBR from one device to another.
346///
347/// This function reads the MBR from a source device, validates it for consistency,
348/// and writes it to a target device. This is useful for creating exact copies of
349/// partition layouts or backing up partition tables.
350///
351/// # Arguments
352///
353/// * `Source_device` - Device to read the MBR from
354/// * `Target_device` - Device to write the MBR to
355///
356/// # Returns
357///
358/// * `Ok(())` - MBR successfully cloned
359/// * `Err(Error)` - Error reading, validating, or writing MBR
360///
361/// # Examples
362///
363/// ```rust
364/// extern crate alloc;
365/// use file_system::*;
366///
367/// let source = create_device!(Memory_device_type::<512>::new(4 * 1024 * 1024));
368/// let target = create_device!(Memory_device_type::<512>::new(4 * 1024 * 1024));
369///
370/// // Create a valid MBR on source device first
371/// let mut mbr = MBR_type::New_with_signature(0x12345678);
372/// mbr.Add_partition(Partition_type_type::Fat32_lba, 2048, 1024, true).unwrap();
373/// mbr.Write_to_device(&source).unwrap();
374///
375/// // Now clone the MBR to target
376/// Clone_mbr(&source, &target).unwrap();
377///
378/// // Both devices now have valid MBRs
379/// assert_eq!(Has_valid_mbr(&source), Has_valid_mbr(&target));
380/// ```
381pub fn clone_mbr(source_device: &Device, target_device: &Device) -> Result<()> {
382    let mbr = Mbr::read_from_device(source_device)?;
383    mbr.validate()?;
384    mbr.write_to_device(target_device)?;
385    Ok(())
386}
387
388/// Create a backup of an MBR as a byte array.
389///
390/// This function reads the MBR from a device and returns it as a 512-byte array.
391/// This backup can be stored and later restored using [`restore_mbr`]. This is
392/// essential for disaster recovery and partition table management.
393///
394/// # Arguments
395///
396/// * `Device` - The storage device to backup the MBR from
397///
398/// # Returns
399///
400/// * `Ok([u8; 512])` - 512-byte array containing the complete MBR
401/// * `Err(Error)` - Error reading MBR from device
402///
403/// # Examples
404///
405/// ```rust
406/// extern crate alloc;
407/// use file_system::*;
408///
409/// let device = create_device!(Memory_device_type::<512>::new(4 * 1024 * 1024));
410/// // Create a valid MBR first
411/// let mut mbr = MBR_type::New_with_signature(0x12345678);
412/// mbr.Add_partition(Partition_type_type::Fat32_lba, 2048, 1024, true).unwrap();
413/// mbr.Write_to_device(&device).unwrap();
414///
415/// // Create backup
416/// let backup = Backup_mbr(&device).unwrap();
417///
418/// // Store backup somewhere safe...
419/// // Later, restore it if needed
420/// Restore_mbr(&device, &backup).unwrap();
421/// ```
422pub fn backup_mbr(device: &Device) -> Result<[u8; 512]> {
423    let mbr = Mbr::read_from_device(device)?;
424    Ok(mbr.to_bytes())
425}
426
427/// Restore an MBR from a backup byte array.
428///
429/// This function takes a previously created MBR backup and writes it to a device.
430/// The backup is validated before writing to ensure data integrity. This is the
431/// counterpart to [`backup_mbr`] for disaster recovery scenarios.
432///
433/// # Arguments
434///
435/// * `Device` - The storage device to restore the MBR to
436/// * `Backup` - 512-byte array containing the MBR backup
437///
438/// # Returns
439///
440/// * `Ok(())` - MBR successfully restored
441/// * `Err(Error)` - Error validating backup or writing to device
442///
443/// # Examples
444///
445/// ```rust
446/// extern crate alloc;
447/// use file_system::*;
448///
449/// let device = create_device!(Memory_device_type::<512>::new(4 * 1024 * 1024));
450/// // Create a valid MBR first
451/// let mut mbr = MBR_type::New_with_signature(0x12345678);
452/// mbr.Add_partition(Partition_type_type::Fat32_lba, 2048, 1024, true).unwrap();
453/// mbr.Write_to_device(&device).unwrap();
454///
455/// // Create a backup
456/// let backup = backup_mbr(&device).unwrap();
457///
458/// // Simulate corruption or need to restore
459/// Restore_mbr(&device, &backup).unwrap();
460///
461/// assert!(Has_valid_mbr(&device));
462/// ```
463pub fn restore_mbr(device: &Device, backup: &[u8; 512]) -> Result<()> {
464    let mbr = Mbr::from_bytes(backup)?;
465    mbr.validate()?;
466    mbr.write_to_device(device)?;
467    Ok(())
468}
469
470/// Format disk to MBR if it doesn't contain valid MBR and return first partition device
471///
472/// This function checks if the device contains a valid MBR. If not, it creates a new MBR
473/// with a single partition using the full disk size. It then returns a partition device
474/// for the first partition.
475///
476/// # Arguments
477/// * `Device` - The device to format and get partition from
478/// * `Partition_type` - The type of partition to create if formatting is needed
479/// * `Disk_signature` - The disk signature to use when creating new MBR (optional, uses random if None)
480///
481/// # Returns
482/// * `Result<Partition_device_type>` - The first partition device
483pub fn format_disk_and_get_first_partition(
484    device: &Device,
485    partition_type: crate::PartitionKind,
486    disk_signature: Option<u32>,
487) -> Result<PartitionDevice> {
488    // Check if device already has valid MBR
489    let mbr = if has_valid_mbr(device) {
490        // Read existing MBR
491        Mbr::read_from_device(device)?
492    } else {
493        // Get device size in sectors
494        let device_size = device.get_size()?;
495        let block_size = device.get_block_size()?;
496        let total_sectors = (device_size.as_u64() / block_size as u64) as u32;
497
498        if total_sectors < 2048 {
499            return Err(Error::InvalidParameter);
500        }
501
502        // Create new MBR with signature
503        let signature = disk_signature.unwrap_or({
504            // Generate a simple signature based on current time or use a default
505            // In a real implementation, you might want to use a proper random number generator
506            0x12345678
507        });
508
509        let new_mbr = Mbr::create_basic(signature, partition_type, total_sectors)?;
510
511        // Write the new MBR to device
512        new_mbr.write_to_device(device)?;
513
514        new_mbr
515    };
516
517    // Get the first valid partition
518    let valid_partitions = mbr.get_valid_partitions();
519    if valid_partitions.is_empty() {
520        return Err(Error::NotFound);
521    }
522
523    // Create partition device for the first partition
524    create_partition_device(device.clone(), valid_partitions[0])
525}
526
527#[cfg(test)]
528mod tests {
529    use super::*;
530    use crate::{Device, DeviceTrait, Error, MemoryDevice, PartitionKind, PartitionStatistics};
531    use alloc::vec;
532
533    /// Create a test device with MBR data
534    fn create_test_device_with_mbr() -> Device {
535        let mut data = vec![0u8; 4096 * 1024]; // Make it large enough (4MB = 8192 sectors)
536
537        // Create a simple MBR at the beginning
538        let mbr = create_test_mbr();
539        let mbr_bytes = mbr.to_bytes();
540        data[0..512].copy_from_slice(&mbr_bytes);
541
542        let memory_device = MemoryDevice::<512>::from_vec(data);
543        crate::create_device!(memory_device)
544    }
545
546    /// Create a test device without valid MBR
547    fn create_test_device_no_mbr() -> Device {
548        let memory_device = MemoryDevice::<512>::new(4096 * 1024); // Make it large enough (4MB = 8192 sectors)
549        crate::create_device!(memory_device)
550    }
551
552    /// Create a test MBR for testing
553    fn create_test_mbr() -> Mbr {
554        let mut mbr = Mbr::new_with_signature(0x12345678);
555
556        // Add a few test partitions
557        let _ = mbr.add_partition(PartitionKind::Fat32Lba, 2048, 1024, true);
558        let _ = mbr.add_partition(PartitionKind::Linux, 4096, 2048, false);
559        let _ = mbr.add_partition(PartitionKind::HiddenFat16, 8192, 512, false);
560
561        mbr
562    }
563
564    #[test]
565    fn test_create_partition_device() {
566        let base_device = create_test_device_with_mbr();
567        let mbr = Mbr::read_from_device(&base_device).unwrap();
568        let partition = &mbr.partitions[0];
569
570        let device_result = create_partition_device(base_device, partition);
571        assert!(device_result.is_ok());
572
573        let device = device_result.unwrap();
574        assert_eq!(device.get_start_lba(), partition.get_start_lba());
575        assert_eq!(device.get_sector_count(), partition.get_size_sectors());
576        assert!(device.is_valid());
577    }
578
579    #[test]
580    fn test_create_partition_device_invalid() {
581        let base_device = create_test_device_with_mbr();
582        let invalid_partition = PartitionEntry::new();
583
584        let device_result = create_partition_device(base_device, &invalid_partition);
585        assert!(device_result.is_err());
586        assert_eq!(device_result.unwrap_err(), Error::InvalidParameter);
587    }
588
589    #[test]
590    fn test_scan_mbr_partitions() {
591        let device = create_test_device_with_mbr();
592
593        let scan_result = scan_mbr_partitions(&device);
594        assert!(scan_result.is_ok());
595
596        let partitions = scan_result.unwrap();
597        assert_eq!(partitions.len(), 3); // Should find 3 valid partitions
598
599        // Check that indices are correct
600        assert_eq!(partitions[0].0, 0);
601        assert_eq!(partitions[1].0, 1);
602        assert_eq!(partitions[2].0, 2);
603
604        // Check partition types
605        assert_eq!(
606            partitions[0].1.get_partition_type(),
607            PartitionKind::Fat32Lba
608        );
609        assert_eq!(partitions[1].1.get_partition_type(), PartitionKind::Linux);
610        assert_eq!(
611            partitions[2].1.get_partition_type(),
612            PartitionKind::HiddenFat16
613        );
614    }
615
616    #[test]
617    fn test_scan_mbr_partitions_no_mbr() {
618        let device = create_test_device_no_mbr();
619
620        let scan_result = scan_mbr_partitions(&device);
621        assert!(scan_result.is_err());
622    }
623
624    #[test]
625    fn test_validate_mbr_valid() {
626        let mbr = create_test_mbr();
627        let validation_result = validate_mbr(&mbr);
628        assert!(validation_result.is_ok());
629    }
630
631    #[test]
632    fn test_validate_mbr_invalid_signature() {
633        let mut mbr = super::Mbr::new();
634        // Manually set invalid signature - should be invalid
635        mbr.boot_signature = [0x00, 0x00];
636
637        let validation_result = validate_mbr(&mbr);
638        assert!(validation_result.is_err());
639        assert_eq!(validation_result.unwrap_err(), Error::Corrupted);
640    }
641
642    #[test]
643    fn test_validate_mbr_multiple_bootable() {
644        let mut mbr = Mbr::new_with_signature(0x12345678);
645
646        // Manually create multiple bootable partitions (bypassing Add_partition validation)
647        mbr.partitions[0] =
648            PartitionEntry::new_with_params(true, PartitionKind::Fat32Lba, 2048, 1024);
649        mbr.partitions[1] = PartitionEntry::new_with_params(true, PartitionKind::Linux, 4096, 2048);
650
651        let validation_result = validate_mbr(&mbr);
652        assert!(validation_result.is_err());
653        assert_eq!(validation_result.unwrap_err(), Error::Corrupted);
654    }
655
656    #[test]
657    fn test_validate_mbr_overlapping_partitions() {
658        let mut mbr = Mbr::new_with_signature(0x12345678);
659
660        // Manually create overlapping partitions (bypassing Add_partition validation)
661        mbr.partitions[0] =
662            PartitionEntry::new_with_params(false, PartitionKind::Fat32Lba, 2048, 2048);
663        mbr.partitions[1] =
664            PartitionEntry::new_with_params(false, PartitionKind::Linux, 3000, 2048);
665
666        let validation_result = validate_mbr(&mbr);
667        assert!(validation_result.is_err());
668        assert_eq!(validation_result.unwrap_err(), Error::Corrupted);
669    }
670
671    #[test]
672    fn test_create_all_partition_devices() {
673        let base_device = create_test_device_with_mbr();
674        let mbr = create_test_mbr();
675
676        let devices_result = create_all_partition_devices(base_device, &mbr);
677        assert!(devices_result.is_ok());
678
679        let devices = devices_result.unwrap();
680        assert_eq!(devices.len(), 3); // Should create 3 devices
681
682        // Check that all devices are valid
683        for device in &devices {
684            assert!(device.is_valid());
685        }
686
687        // Check first device properties
688        assert_eq!(devices[0].get_start_lba(), 2048);
689        assert_eq!(devices[0].get_sector_count(), 1024);
690    }
691
692    #[test]
693    fn test_find_partitions_by_type() {
694        let mbr = create_test_mbr();
695
696        // Find FAT32 partitions
697        let fat_partitions = find_partitions_by_type(&mbr, PartitionKind::Fat32Lba);
698        assert_eq!(fat_partitions.len(), 1);
699        assert_eq!(fat_partitions[0].0, 0); // Index 0
700
701        // Find Linux partitions
702        let linux_partitions = find_partitions_by_type(&mbr, PartitionKind::Linux);
703        assert_eq!(linux_partitions.len(), 1);
704        assert_eq!(linux_partitions[0].0, 1); // Index 1
705
706        // Find non-existent type
707        let ntfs_partitions = find_partitions_by_type(&mbr, PartitionKind::NtfsExfat);
708        assert_eq!(ntfs_partitions.len(), 0);
709    }
710
711    #[test]
712    fn test_partition_statistics() {
713        let mbr = create_test_mbr();
714        let stats = PartitionStatistics::from_mbr(&mbr);
715
716        assert_eq!(stats.total_partitions, 3);
717        assert_eq!(stats.bootable_partitions, 1);
718        assert_eq!(stats.fat_partitions, 2); // Fat32_lba + Hidden_fat16
719        assert_eq!(stats.linux_partitions, 1);
720        assert_eq!(stats.hidden_partitions, 1); // Hidden_fat16
721        assert_eq!(stats.extended_partitions, 0);
722        assert_eq!(stats.unknown_partitions, 0);
723        assert_eq!(stats.total_used_sectors, 1024 + 2048 + 512); // Sum of all partition sizes
724        assert_eq!(stats.largest_partition_sectors, 2048);
725        assert_eq!(stats.smallest_partition_sectors, 512);
726    }
727
728    #[test]
729    fn test_partition_statistics_empty_mbr() {
730        let mbr = Mbr::new_with_signature(0x12345678);
731        let stats = PartitionStatistics::from_mbr(&mbr);
732
733        assert_eq!(stats.total_partitions, 0);
734        assert_eq!(stats.bootable_partitions, 0);
735        assert_eq!(stats.fat_partitions, 0);
736        assert_eq!(stats.linux_partitions, 0);
737        assert_eq!(stats.hidden_partitions, 0);
738        assert_eq!(stats.extended_partitions, 0);
739        assert_eq!(stats.unknown_partitions, 0);
740        assert_eq!(stats.total_used_sectors, 0);
741        assert_eq!(stats.largest_partition_sectors, 0);
742        assert_eq!(stats.smallest_partition_sectors, 0);
743    }
744
745    #[test]
746    fn test_has_valid_mbr() {
747        let valid_device = create_test_device_with_mbr();
748        assert!(has_valid_mbr(&valid_device));
749
750        let invalid_device = create_test_device_no_mbr();
751        assert!(!has_valid_mbr(&invalid_device));
752    }
753
754    #[test]
755    fn test_is_gpt_disk() {
756        // Create MBR with GPT protective partition
757        let mut mbr = Mbr::new_with_signature(0x12345678);
758        let _ = mbr.add_partition(PartitionKind::GptProtective, 1, 0xFFFFFFFF, false);
759
760        let mut data = vec![0u8; 4096 * 1024];
761        let mbr_bytes = mbr.to_bytes();
762        data[0..512].copy_from_slice(&mbr_bytes);
763        let memory_device = MemoryDevice::<512>::from_vec(data);
764        let gpt_device = crate::create_device!(memory_device);
765
766        assert!(is_gpt_disk(&gpt_device));
767
768        // Regular MBR should not be detected as GPT
769        let regular_device = create_test_device_with_mbr();
770        assert!(!is_gpt_disk(&regular_device));
771    }
772
773    #[test]
774    fn test_create_basic_mbr() {
775        let mbr_result = create_basic_mbr(0xABCDEF00, PartitionKind::Fat32Lba, 100000);
776        assert!(mbr_result.is_ok());
777
778        let mbr = mbr_result.unwrap();
779        assert!(mbr.is_valid());
780        assert_eq!(mbr.get_disk_signature(), 0xABCDEF00);
781
782        let valid_partitions = mbr.get_valid_partitions();
783        assert_eq!(valid_partitions.len(), 1);
784
785        let partition = &valid_partitions[0];
786        assert_eq!(partition.get_partition_type(), PartitionKind::Fat32Lba);
787        assert_eq!(partition.get_start_lba(), 2048);
788        assert_eq!(partition.get_size_sectors(), 100000 - 2048);
789        assert!(partition.is_bootable());
790    }
791
792    #[test]
793    fn test_create_basic_mbr_too_small() {
794        let mbr_result = create_basic_mbr(0x12345678, PartitionKind::Fat32Lba, 1000);
795        assert!(mbr_result.is_err());
796        assert_eq!(mbr_result.unwrap_err(), Error::InvalidParameter);
797    }
798
799    #[test]
800    fn test_clone_mbr() {
801        let source_device = create_test_device_with_mbr();
802        let target_data = vec![0u8; 4096 * 1024];
803        let memory_device = MemoryDevice::<512>::from_vec(target_data);
804        let target_device = crate::create_device!(memory_device);
805
806        let clone_result = clone_mbr(&source_device, &target_device);
807        assert!(clone_result.is_ok());
808
809        // Verify that target device now has the same MBR
810        let source_mbr = Mbr::read_from_device(&source_device).unwrap();
811        let target_mbr = Mbr::read_from_device(&target_device).unwrap();
812
813        assert_eq!(source_mbr.to_bytes(), target_mbr.to_bytes());
814    }
815
816    #[test]
817    fn test_backup_and_restore_mbr() {
818        let device = create_test_device_with_mbr();
819
820        // Backup MBR
821        let backup_result = backup_mbr(&device);
822        assert!(backup_result.is_ok());
823        let backup = backup_result.unwrap();
824
825        // Create a new device with zeros
826        let target_data = vec![0u8; 4096 * 1024];
827        let memory_device = MemoryDevice::<512>::from_vec(target_data);
828        let target_device = crate::create_device!(memory_device);
829
830        // Restore MBR
831        let restore_result = restore_mbr(&target_device, &backup);
832        assert!(restore_result.is_ok());
833
834        // Verify restoration
835        let original_mbr = Mbr::read_from_device(&device).unwrap();
836        let restored_mbr = Mbr::read_from_device(&target_device).unwrap();
837
838        assert_eq!(original_mbr.to_bytes(), restored_mbr.to_bytes());
839    }
840
841    #[test]
842    fn test_backup_mbr_invalid_device() {
843        let invalid_device = create_test_device_no_mbr();
844
845        let backup_result = backup_mbr(&invalid_device);
846        assert!(backup_result.is_err());
847    }
848
849    #[test]
850    fn test_restore_mbr_invalid_backup() {
851        let device = create_test_device_no_mbr();
852        let invalid_backup = [0u8; 512]; // No valid signature
853
854        let restore_result = restore_mbr(&device, &invalid_backup);
855        assert!(restore_result.is_err());
856    }
857
858    #[test]
859    fn test_utilities_with_complex_mbr() {
860        // Create a more complex MBR for comprehensive testing
861        let mut mbr = Mbr::new_with_signature(0xDEADBEEF);
862
863        let _ = mbr.add_partition(PartitionKind::Fat16, 63, 1000, true);
864        let _ = mbr.add_partition(PartitionKind::ExtendedLba, 2048, 10000, false);
865        let _ = mbr.add_partition(PartitionKind::LinuxSwap, 15000, 2000, false);
866        let _ = mbr.add_partition(PartitionKind::Unknown(0x42), 20000, 5000, false);
867
868        // Test statistics
869        let stats = PartitionStatistics::from_mbr(&mbr);
870        assert_eq!(stats.total_partitions, 4);
871        assert_eq!(stats.bootable_partitions, 1);
872        assert_eq!(stats.fat_partitions, 1);
873        assert_eq!(stats.linux_partitions, 1); // Linux_swap counts as Linux
874        assert_eq!(stats.extended_partitions, 1);
875        assert_eq!(stats.unknown_partitions, 1);
876
877        // Test finding by type
878        let extended = find_partitions_by_type(&mbr, PartitionKind::ExtendedLba);
879        assert_eq!(extended.len(), 1);
880        assert_eq!(extended[0].0, 1);
881
882        let unknown = find_partitions_by_type(&mbr, PartitionKind::Unknown(0x42));
883        assert_eq!(unknown.len(), 1);
884        assert_eq!(unknown[0].0, 3);
885    }
886
887    #[test]
888    fn test_edge_cases() {
889        // Test with MBR containing only empty partitions
890        let empty_mbr = Mbr::new_with_signature(0x12345678);
891
892        let stats = PartitionStatistics::from_mbr(&empty_mbr);
893        assert_eq!(stats.total_partitions, 0);
894
895        let partitions = find_partitions_by_type(&empty_mbr, PartitionKind::Fat32);
896        assert_eq!(partitions.len(), 0);
897
898        // Test scan on empty device
899        let mut empty_data = vec![0u8; 4096 * 1024];
900        let empty_mbr_bytes = empty_mbr.to_bytes();
901        empty_data[0..512].copy_from_slice(&empty_mbr_bytes);
902        let memory_device = MemoryDevice::<512>::from_vec(empty_data);
903        let empty_device = crate::create_device!(memory_device);
904
905        let scan_result = scan_mbr_partitions(&empty_device);
906        assert!(scan_result.is_ok());
907        assert_eq!(scan_result.unwrap().len(), 0);
908    }
909
910    // Tests for the new Format_disk_and_get_first_partition function
911
912    #[test]
913    fn test_format_disk_and_get_first_partition_existing_mbr() {
914        let device = create_test_device_with_mbr();
915
916        let partition_device_result =
917            format_disk_and_get_first_partition(&device, PartitionKind::Fat32Lba, Some(0xABCDEF00));
918        assert!(partition_device_result.is_ok());
919
920        let partition_device = partition_device_result.unwrap();
921        assert!(partition_device.is_valid());
922        assert_eq!(partition_device.get_start_lba(), 2048); // First partition starts at 2048
923        assert_eq!(partition_device.get_sector_count(), 1024); // First partition size
924    }
925
926    #[test]
927    fn test_format_disk_and_get_first_partition_no_mbr() {
928        let device = create_test_device_no_mbr();
929
930        let partition_device_result =
931            format_disk_and_get_first_partition(&device, PartitionKind::Fat32Lba, Some(0x12345678));
932        assert!(partition_device_result.is_ok());
933
934        let partition_device = partition_device_result.unwrap();
935        assert!(partition_device.is_valid());
936        assert_eq!(partition_device.get_start_lba(), 2048); // Should start at 2048 for alignment
937
938        // Check that MBR was created on device
939        assert!(has_valid_mbr(&device));
940
941        // Verify the MBR has one partition with correct type
942        let mbr = Mbr::read_from_device(&device).unwrap();
943        let valid_partitions = mbr.get_valid_partitions();
944        assert_eq!(valid_partitions.len(), 1);
945        assert_eq!(
946            valid_partitions[0].get_partition_type(),
947            PartitionKind::Fat32Lba
948        );
949        assert!(valid_partitions[0].is_bootable());
950    }
951
952    #[test]
953    fn test_format_disk_and_get_first_partition_default_signature() {
954        let device = create_test_device_no_mbr();
955
956        let partition_device_result = format_disk_and_get_first_partition(
957            &device,
958            PartitionKind::Linux,
959            None, // Use default signature
960        );
961        assert!(partition_device_result.is_ok());
962
963        let partition_device = partition_device_result.unwrap();
964        assert!(partition_device.is_valid());
965
966        // Check that MBR was created with default signature
967        let mbr = Mbr::read_from_device(&device).unwrap();
968        assert_eq!(mbr.get_disk_signature(), 0x12345678); // Default signature
969    }
970
971    #[test]
972    fn test_format_disk_and_get_first_partition_device_too_small() {
973        // Create a very small device (less than 2048 sectors)
974        let small_data = vec![0u8; 1024]; // 2 sectors of 512 bytes each
975        let memory_device = MemoryDevice::<512>::from_vec(small_data);
976        let small_device = crate::create_device!(memory_device);
977
978        let partition_device_result = format_disk_and_get_first_partition(
979            &small_device,
980            PartitionKind::Fat32Lba,
981            Some(0x12345678),
982        );
983        assert!(partition_device_result.is_err());
984        assert_eq!(
985            partition_device_result.unwrap_err(),
986            Error::InvalidParameter
987        );
988    }
989
990    #[test]
991    fn test_format_disk_and_get_first_partition_empty_mbr() {
992        // Create device with valid MBR but no partitions
993        let mut data = vec![0u8; 4096 * 1024];
994        let empty_mbr = Mbr::new_with_signature(0xDEADBEEF);
995        let mbr_bytes = empty_mbr.to_bytes();
996        data[0..512].copy_from_slice(&mbr_bytes);
997
998        let memory_device = MemoryDevice::<512>::from_vec(data);
999        let device = crate::create_device!(memory_device);
1000
1001        let partition_device_result =
1002            format_disk_and_get_first_partition(&device, PartitionKind::Fat32Lba, Some(0x12345678));
1003        assert!(partition_device_result.is_err());
1004        assert_eq!(partition_device_result.unwrap_err(), Error::NotFound);
1005    }
1006
1007    #[test]
1008    fn test_format_disk_and_get_first_partition_different_types() {
1009        // Test with different partition types
1010        let partition_types = [
1011            PartitionKind::Fat32Lba,
1012            PartitionKind::Linux,
1013            PartitionKind::NtfsExfat,
1014            PartitionKind::ExtendedLba,
1015        ];
1016
1017        for partition_type in &partition_types {
1018            let device = create_test_device_no_mbr();
1019
1020            let partition_device_result =
1021                format_disk_and_get_first_partition(&device, *partition_type, Some(0xABCDEF00));
1022            assert!(partition_device_result.is_ok());
1023
1024            let partition_device = partition_device_result.unwrap();
1025            assert!(partition_device.is_valid());
1026
1027            // Verify the partition type in MBR
1028            let mbr = Mbr::read_from_device(&device).unwrap();
1029            let valid_partitions = mbr.get_valid_partitions();
1030            assert_eq!(valid_partitions.len(), 1);
1031            assert_eq!(valid_partitions[0].get_partition_type(), *partition_type);
1032        }
1033    }
1034
1035    #[test]
1036    fn test_format_disk_and_write_read_data() {
1037        let device = create_test_device_no_mbr();
1038
1039        // Format disk and get first partition
1040        let partition_device_result =
1041            format_disk_and_get_first_partition(&device, PartitionKind::Fat32Lba, Some(0x12345678));
1042        assert!(partition_device_result.is_ok());
1043        let partition_device = partition_device_result.unwrap();
1044
1045        // Test data to write
1046        let test_data = b"Hello, Partition World! This is a test of writing and reading data from a partition device.";
1047        let mut write_buffer = vec![0u8; 512]; // One sector
1048        write_buffer[0..test_data.len()].copy_from_slice(test_data);
1049
1050        // Write data to the beginning of the partition
1051        let write_result = partition_device.write(&write_buffer);
1052        assert!(write_result.is_ok());
1053        let bytes_written = write_result.unwrap();
1054        assert_eq!(bytes_written.as_u64(), 512);
1055
1056        // Reset position to beginning of partition
1057        let set_position_result = partition_device.set_position(&crate::Position::Start(0));
1058        assert!(set_position_result.is_ok());
1059
1060        // Read data back from the partition
1061        let mut read_buffer = vec![0u8; 512];
1062        let read_result = partition_device.read(&mut read_buffer);
1063        assert!(read_result.is_ok());
1064        let bytes_read = read_result.unwrap();
1065        assert_eq!(bytes_read.as_u64(), 512);
1066
1067        // Verify the data matches what we wrote
1068        assert_eq!(&read_buffer[0..test_data.len()], test_data);
1069
1070        // Test writing at different positions
1071        let second_test_data = b"Second write test at offset";
1072        let second_position = 1024; // Write at sector 2
1073
1074        // Set position to second sector
1075        let set_position_result =
1076            partition_device.set_position(&crate::Position::Start(second_position));
1077        assert!(set_position_result.is_ok());
1078
1079        // Write second test data
1080        let mut second_write_buffer = vec![0u8; 512];
1081        second_write_buffer[0..second_test_data.len()].copy_from_slice(second_test_data);
1082        let write_result = partition_device.write(&second_write_buffer);
1083        assert!(write_result.is_ok());
1084
1085        // Read back from second position
1086        let set_position_result =
1087            partition_device.set_position(&crate::Position::Start(second_position));
1088        assert!(set_position_result.is_ok());
1089        let mut second_read_buffer = vec![0u8; 512];
1090        let read_result = partition_device.read(&mut second_read_buffer);
1091        assert!(read_result.is_ok());
1092
1093        // Verify second write
1094        assert_eq!(
1095            &second_read_buffer[0..second_test_data.len()],
1096            second_test_data
1097        );
1098
1099        // Verify first write is still intact
1100        let set_position_result = partition_device.set_position(&crate::Position::Start(0));
1101        assert!(set_position_result.is_ok());
1102        let mut first_read_buffer = vec![0u8; 512];
1103        let read_result = partition_device.read(&mut first_read_buffer);
1104        assert!(read_result.is_ok());
1105        assert_eq!(&first_read_buffer[0..test_data.len()], test_data);
1106    }
1107
1108    #[test]
1109    fn test_partition_data_isolation() {
1110        // Test that data written to one partition doesn't affect another
1111        let device = create_test_device_no_mbr();
1112
1113        // Create an MBR with multiple partitions manually
1114        let device_size = device.get_size().unwrap();
1115        let block_size = device.get_block_size().unwrap();
1116        let _ = (device_size.as_u64() / block_size as u64) as u32;
1117
1118        let mut mbr = Mbr::new_with_signature(0x12345678);
1119
1120        // Add two partitions
1121        let first_partition_size = 2048; // 1MB worth of sectors
1122        let second_partition_start = 2048 + first_partition_size;
1123        let second_partition_size = 2048;
1124
1125        let _ = mbr.add_partition(PartitionKind::Fat32Lba, 2048, first_partition_size, true);
1126        let _ = mbr.add_partition(
1127            PartitionKind::Linux,
1128            second_partition_start,
1129            second_partition_size,
1130            false,
1131        );
1132
1133        // Write MBR to device
1134        let write_result = mbr.write_to_device(&device);
1135        assert!(write_result.is_ok());
1136
1137        // Create partition devices
1138        let valid_partitions = mbr.get_valid_partitions();
1139        assert_eq!(valid_partitions.len(), 2);
1140
1141        let first_partition_device =
1142            create_partition_device(device.clone(), valid_partitions[0]).unwrap();
1143        let second_partition_device =
1144            create_partition_device(device.clone(), valid_partitions[1]).unwrap();
1145
1146        // Write different data to each partition
1147        let first_data = b"Data for first partition - FAT32";
1148        let second_data = b"Data for second partition - Linux";
1149
1150        let mut first_buffer = vec![0u8; 512];
1151        first_buffer[0..first_data.len()].copy_from_slice(first_data);
1152        let write_result = first_partition_device.write(&first_buffer);
1153        assert!(write_result.is_ok());
1154
1155        let mut second_buffer = vec![0u8; 512];
1156        second_buffer[0..second_data.len()].copy_from_slice(second_data);
1157        let write_result = second_partition_device.write(&second_buffer);
1158        assert!(write_result.is_ok());
1159
1160        // Reset positions and read back
1161        let _ = first_partition_device.set_position(&crate::Position::Start(0));
1162        let _ = second_partition_device.set_position(&crate::Position::Start(0));
1163
1164        let mut first_read_buffer = vec![0u8; 512];
1165        let mut second_read_buffer = vec![0u8; 512];
1166
1167        let read_result = first_partition_device.read(&mut first_read_buffer);
1168        assert!(read_result.is_ok());
1169        let read_result = second_partition_device.read(&mut second_read_buffer);
1170        assert!(read_result.is_ok());
1171
1172        // Verify each partition has its own data
1173        assert_eq!(&first_read_buffer[0..first_data.len()], first_data);
1174        assert_eq!(&second_read_buffer[0..second_data.len()], second_data);
1175
1176        // Verify the data is different (partitions are isolated)
1177        assert_ne!(&first_read_buffer[0..32], &second_read_buffer[0..32]);
1178    }
1179
1180    #[test]
1181    fn test_partition_bounds_checking() {
1182        let device = create_test_device_no_mbr();
1183
1184        let partition_device_result =
1185            format_disk_and_get_first_partition(&device, PartitionKind::Fat32Lba, Some(0x12345678));
1186        assert!(partition_device_result.is_ok());
1187        let partition_device = partition_device_result.unwrap();
1188
1189        // Try to write beyond partition bounds
1190        let partition_size_bytes = partition_device.get_sector_count() as u64 * 512;
1191        let beyond_bounds_position = partition_size_bytes;
1192
1193        let _ = partition_device
1194            .set_position(&crate::Position::Start(beyond_bounds_position))
1195            .unwrap();
1196        // This should either fail or be clamped to valid range
1197        // The exact behavior depends on the partition device implementation
1198
1199        // Write a small amount of data at the very end of the partition (should work)
1200        let end_position = partition_size_bytes - 512;
1201        let set_position_result =
1202            partition_device.set_position(&crate::Position::Start(end_position));
1203        assert!(set_position_result.is_ok());
1204
1205        let test_data = b"End of partition data";
1206        let mut write_buffer = vec![0u8; 512];
1207        write_buffer[0..test_data.len()].copy_from_slice(test_data);
1208
1209        let write_result = partition_device.write(&write_buffer);
1210        assert!(write_result.is_ok());
1211
1212        // Read it back to verify
1213        let set_position_result =
1214            partition_device.set_position(&crate::Position::Start(end_position));
1215        assert!(set_position_result.is_ok());
1216        let mut read_buffer = vec![0u8; 512];
1217        let read_result = partition_device.read(&mut read_buffer);
1218        assert!(read_result.is_ok());
1219        assert_eq!(&read_buffer[0..test_data.len()], test_data);
1220    }
1221}