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
124
125
126
127
128
129
use std::env;
use std::fs::OpenOptions;
use std::io;
use std::io::prelude::*;
use std::fs;
use std::path::{Path, PathBuf};
use storage_device::storage_device::{StorageDevice, StorageBlockDevice};
use libfat::FatFileSystemResult;
use libfat::filesystem::FatFileSystem;
use libfat::FatFsType;
use libfat::directory::File as FatFile;
mod gpt;
use gpt::{PartitionIterator, PartitionManager};
const BLOCK_SIZE: usize = 512;
const BLOCK_SIZE_U64: u64 = BLOCK_SIZE as u64;
fn write_file_to_filesystem<S>(
fs: &FatFileSystem<S>,
mut file: FatFile,
path: &str,
) -> FatFileSystemResult<()> where S: StorageDevice {
let mut f = OpenOptions::new()
.read(true)
.write(false)
.open(path)
.unwrap();
let mut base_buffer = Vec::new();
f.read_to_end(&mut base_buffer).unwrap();
file.write(fs, 0, &base_buffer, true)?;
Ok(())
}
fn write_tempate_to_filesystem<S>(filesystem: &FatFileSystem<S>, dir: &Path, filesystem_path: &mut PathBuf) -> io::Result<()> where S: StorageDevice {
if dir.is_dir() {
for entry in fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
let mut filesystem_entry_path = filesystem_path.clone();
filesystem_entry_path.push(entry.file_name());
let filesystem_entry_path_str = filesystem_entry_path.to_str().unwrap();
if path.is_dir() {
filesystem.create_directory(filesystem_entry_path_str).expect("Cannot create directory in the filesystem");
write_tempate_to_filesystem(filesystem, &path, &mut filesystem_entry_path)?;
} else {
filesystem.create_file(filesystem_entry_path_str).expect("Cannot create file in the filesystem");
let file = filesystem.open_file(filesystem_entry_path_str).expect("Cannot open file in the filesystem");
write_file_to_filesystem(filesystem, file, path.to_str().unwrap()).expect("Cannot write file to filesystem");
}
}
}
Ok(())
}
fn main() {
env_logger::init();
if env::args().len() < 4 {
println!("usage: <disk_name> <disk_size> <template_path>");
std::process::exit(1);
}
let file_name = env::args().nth(1).expect("File name is expected");
let file_size = env::args().nth(2).expect("Disk size is expected");
let template_path = env::args().nth(3).expect("Template path is expected");
let file_size = u64::from_str_radix(file_size.as_str(), 10).expect("Cannot parse file size");
let file = OpenOptions::new().create(true).read(true).write(true).open(file_name.clone()).expect("Cannot create file");
file.set_len(file_size).expect("Cannot set file size");
let mut system_device = StorageBlockDevice::new(file);
let mut part_manager = PartitionManager::new(&mut system_device);
part_manager
.initialize()
.expect("Disk initialization failed");
let mut partition_iterator = PartitionIterator::new(&mut system_device).expect("Invalid GPT");
let partition_option = partition_iterator.next().unwrap();
let partition = partition_option.expect("Invalid partition while iterating");
let partition_start = partition.first_lba * BLOCK_SIZE_U64;
let partition_len = (partition.last_lba * BLOCK_SIZE_U64) - partition_start;
libfat::format_partition(
system_device,
FatFsType::Fat32,
partition_start,
partition_len,
)
.expect("Format issue in libfat");
let file = OpenOptions::new().read(true).write(true).open(file_name).expect("Cannot open output disk image");
let system_device = StorageBlockDevice::new(file);
let filesystem = libfat::get_raw_partition_with_start(system_device, partition_start, partition_len).expect("Open issue in libfat");
let mut filesystem_path = PathBuf::new();
filesystem_path.push("/");
write_tempate_to_filesystem(&filesystem, Path::new(&template_path), &mut filesystem_path).expect("Failed to write template to filesystem");
}