1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use std::fs::File;
use std::io::{Read, Seek, Cursor, SeekFrom, Error, ErrorKind};
use std::fmt;
use header::{Header, parse_uuid};
extern crate uuid;
extern crate byteorder;
extern crate crc;
extern crate serde;
extern crate serde_json;
use self::byteorder::{LittleEndian, ReadBytesExt};
use self::crc::crc32;
#[derive(Debug)]
pub struct Partition {
part_type_guid: PartitionType,
part_guid: uuid::Uuid,
first_LBA: u32,
last_LBA: u32,
flags: u32,
name: String,
}
#[derive(Debug, Serialize, Deserialize)]
struct PartitionType {
os: String,
guid: String,
desc: String,
}
impl fmt::Display for Partition {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Partition:\t\t{}\nPartition GUID:\t\t{}\nPartition Type:\t\t{}\t{}\nSpan:\t\t\t{} - {}\nFlags:\t\t\t{}", self.name, self.part_guid, self.part_type_guid.guid, self.part_type_guid.desc, self.first_LBA, self.last_LBA, self.flags)
}
}
fn read_part_name(rdr: &mut Cursor<&[u8]>) -> String {
let mut namebytes: Vec<u16> = Vec::new();
for _ in 0..36 {
let b = rdr.read_u16::<LittleEndian>().unwrap();
if b != 0 {
namebytes.push(b);
}
}
return String::from_utf16_lossy(&namebytes);
}
fn parse_parttype_guid(str: uuid::Uuid) -> Result<PartitionType, Error> {
let uuid = str.hyphenated().to_string().to_uppercase();
let mut file = File::open("types.json")?;
let mut json: String = String::new();
let _ = file.read_to_string(&mut json);
let mut guids: Vec<PartitionType> =
serde_json::from_str(&json).map_err(|e: serde_json::Error|
Error::new(ErrorKind::Other, e.to_string()))?;
for guid in guids {
if guid.guid == uuid {
return Ok(PartitionType {
guid: guid.guid,
os: guid.os,
desc: guid.desc
})
}
}
Err(Error::new(ErrorKind::Other, "Partition GUID not found."))
}
pub fn read_partitions(path: &String, header: &Header) -> Result<Vec<Partition>, Error> {
let mut file = File::open(path)?;
let _ = file.seek(SeekFrom::Start(512 * header.part_start));
let mut parts: Vec<Partition> = Vec::new();
for _ in 0..header.num_parts {
let mut bytes: [u8; 56] = [0; 56];
let mut nameraw: [u8; 72] = [0; 72];
let _ = file.read_exact(&mut bytes);
let _ = file.read_exact(&mut nameraw);
let partname = read_part_name(&mut Cursor::new(&nameraw[..]));
let mut reader = Cursor::new(&bytes[..]);
let p: Partition = Partition {
part_type_guid: parse_parttype_guid(parse_uuid(&mut reader)?)?,
part_guid: parse_uuid(&mut reader)?,
first_LBA: reader.read_u32::<LittleEndian>()?,
last_LBA: reader.read_u32::<LittleEndian>()?,
flags: reader.read_u32::<LittleEndian>()?,
name: partname.to_string(),
};
if p.part_guid.simple().to_string() != "00000000000000000000000000000000" {
parts.push(p);
}
}
let _ = file.seek(SeekFrom::Start(512 * header.part_start));
let mut table: [u8; 16384] = [0; 16384];
let _ = file.read_exact(&mut table);
if crc32::checksum_ieee(&table) != header.crc32_parts {
return Err(Error::new(ErrorKind::Other, "Invalid partition table CRC."))
}
Ok(parts)
}