1 // Copyright 2024 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // To allow compiling this file on non-Linux platforms, main logic is
6 // behind the `linux` module.
7 #[cfg(target_os = "linux")]
8 mod linux {
9 use std::fs::OpenOptions;
10 use std::io::Write;
11 use std::path::PathBuf;
12
13 use argh::FromArgs;
14 use base::MappedRegion;
15
16 #[derive(FromArgs)]
17 /// Create ext2 filesystem.
18 struct Args {
19 /// path to the disk,
20 #[argh(option)]
21 output: String,
22
23 /// path to the source directory to copy files from,
24 #[argh(option)]
25 src: Option<String>,
26
27 /// number of blocks for each group
28 #[argh(option, default = "1024")]
29 blocks_per_group: u32,
30
31 /// number of inodes for each group
32 #[argh(option, default = "1024")]
33 inodes_per_group: u32,
34
35 /// size of memory region in bytes.
36 /// If it's not a multiple of 4096, it will be rounded up to the next multiple of 4096.
37 #[argh(option, default = "4194304")]
38 size: u32,
39
40 /// if sepecified, create a file systeon on RAM, but do not write to disk.
41 #[argh(switch, short = 'j')]
42 dry_run: bool,
43 }
44
main() -> anyhow::Result<()>45 pub fn main() -> anyhow::Result<()> {
46 let args: Args = argh::from_env();
47 let src_dir = args.src.as_ref().map(|s| PathBuf::new().join(s));
48 let builder = ext2::Builder {
49 blocks_per_group: args.blocks_per_group,
50 inodes_per_group: args.inodes_per_group,
51 size: args.size,
52 root_dir: src_dir,
53 };
54 let mem = builder.allocate_memory()?.build_mmap_info()?.do_mmap()?;
55 if args.dry_run {
56 println!("Done!");
57 return Ok(());
58 }
59
60 // SAFETY: `mem` has a valid pointer and its size.
61 let buf = unsafe { std::slice::from_raw_parts(mem.as_ptr(), mem.size()) };
62 let mut file = OpenOptions::new()
63 .write(true)
64 .create(true)
65 .truncate(true)
66 .open(&args.output)
67 .unwrap();
68
69 file.write_all(buf).unwrap();
70
71 println!("{} is written!", args.output);
72
73 Ok(())
74 }
75 }
76
main() -> anyhow::Result<()>77 fn main() -> anyhow::Result<()> {
78 #[cfg(target_os = "linux")]
79 linux::main()?;
80
81 #[cfg(not(target_os = "linux"))]
82 println!("Not supported on non-Linux platforms");
83
84 Ok(())
85 }
86