Add no_mount option and tidy up flags
This commit is contained in:
+17
-8
@@ -19,7 +19,8 @@ fn main() {
|
||||
.add_flag(&["filesystem-size"])
|
||||
.add_flag(&["r", "repo-binary"])
|
||||
.add_flag(&["l", "list-packages"])
|
||||
.add_flag(&["live"]);
|
||||
.add_flag(&["live"])
|
||||
.add_flag(&["no-mount"]);
|
||||
parser.parse(env::args());
|
||||
|
||||
// Use pre-built binaries for packages as the default.
|
||||
@@ -127,14 +128,22 @@ fn main() {
|
||||
None
|
||||
};
|
||||
|
||||
if cookbook.is_some() {
|
||||
config.general.cookbook = cookbook;
|
||||
}
|
||||
if parser.found("live") {
|
||||
config.general.live_disk = Some(true);
|
||||
}
|
||||
if parser.found("no-mount") {
|
||||
config.general.no_mount = Some(true);
|
||||
}
|
||||
let write_bootloader = parser.get_opt("write-bootloader");
|
||||
if write_bootloader.is_some() {
|
||||
config.general.write_bootloader = write_bootloader;
|
||||
}
|
||||
|
||||
if let Some(path) = parser.args.first() {
|
||||
if let Err(err) = redox_installer::install(
|
||||
config,
|
||||
path,
|
||||
cookbook.as_deref(),
|
||||
parser.found("live"),
|
||||
parser.get_opt("write-bootloader").as_deref(),
|
||||
) {
|
||||
if let Err(err) = redox_installer::install(config, path) {
|
||||
eprintln!("installer: failed to install: {}", err);
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
+31
-3
@@ -1,19 +1,47 @@
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
pub struct GeneralConfig {
|
||||
/// Specify a path where cookbook exists, all packages will be installed locally
|
||||
pub cookbook: Option<String>,
|
||||
/// Allow prompts for missing information such as user password, true by default
|
||||
pub prompt: Option<bool>,
|
||||
// Allow config to specify cookbook recipe or binary package as default
|
||||
/// Allow config to specify cookbook recipe or binary package as default
|
||||
/// note: Not read by installer anymore, exists only for legacy reasons
|
||||
pub repo_binary: Option<bool>,
|
||||
pub filesystem_size: Option<u32>, //MiB
|
||||
pub efi_partition_size: Option<u32>, //MiB
|
||||
/// Total filesystem size in MB
|
||||
pub filesystem_size: Option<u32>,
|
||||
/// EFI partition size in MB, default to 2MB
|
||||
pub efi_partition_size: Option<u32>,
|
||||
/// Skip disk partitioning, assume whole disk is a partition
|
||||
pub skip_partitions: Option<bool>,
|
||||
/// Set a plain text password to encrypt the disk, or empty string to prompt
|
||||
pub encrypt_disk: Option<String>,
|
||||
/// Use live disk for bootloader config, default is false
|
||||
pub live_disk: Option<bool>,
|
||||
/// If set, write bootloader disk into this path
|
||||
pub write_bootloader: Option<String>,
|
||||
/// Use AR to write files instead of FUSE-based mount
|
||||
/// (bypasses FUSE, but slower and requires namespaced context such as "podman unshare")
|
||||
pub no_mount: Option<bool>,
|
||||
}
|
||||
|
||||
impl GeneralConfig {
|
||||
/// Merge two config, "other" is more dominant
|
||||
pub(super) fn merge(&mut self, other: GeneralConfig) {
|
||||
if let Some(cookbook) = other.cookbook {
|
||||
self.cookbook = Some(cookbook);
|
||||
}
|
||||
self.prompt = other.prompt.or(self.prompt);
|
||||
self.repo_binary = other.repo_binary.or(self.repo_binary);
|
||||
self.filesystem_size = other.filesystem_size.or(self.filesystem_size);
|
||||
self.efi_partition_size = other.efi_partition_size.or(self.efi_partition_size);
|
||||
self.skip_partitions = other.skip_partitions.or(self.skip_partitions);
|
||||
if let Some(encrypt_disk) = other.encrypt_disk {
|
||||
self.encrypt_disk = Some(encrypt_disk);
|
||||
}
|
||||
self.live_disk = other.live_disk.or(self.live_disk);
|
||||
if let Some(write_bootloader) = other.write_bootloader {
|
||||
self.write_bootloader = Some(write_bootloader);
|
||||
}
|
||||
self.no_mount = other.no_mount.or(self.no_mount);
|
||||
}
|
||||
}
|
||||
|
||||
+85
-22
@@ -3,7 +3,7 @@ use anyhow::{anyhow, Context};
|
||||
use anyhow::{bail, Result};
|
||||
use pkg::Library;
|
||||
use rand::{rngs::OsRng, TryRngCore};
|
||||
use redoxfs::{unmount_path, Disk, DiskIo, FileSystem};
|
||||
use redoxfs::{unmount_path, Disk, DiskIo, FileSystem, BLOCK_SIZE};
|
||||
use termion::input::TermRead;
|
||||
|
||||
use crate::config::file::FileConfig;
|
||||
@@ -412,6 +412,67 @@ where
|
||||
res
|
||||
}
|
||||
|
||||
pub fn with_redoxfs_ar<D, T, F>(mut fs: FileSystem<D>, callback: F) -> Result<T>
|
||||
where
|
||||
D: Disk + Send + 'static,
|
||||
F: FnOnce(&Path) -> Result<T>,
|
||||
{
|
||||
let mount_path = if cfg!(target_os = "redox") {
|
||||
format!("file.redox_installer_{}", process::id())
|
||||
} else {
|
||||
format!("/tmp/redox_installer_{}", process::id())
|
||||
};
|
||||
|
||||
let res = callback(Path::new(&mount_path));
|
||||
|
||||
if res.is_ok() {
|
||||
let _end_block = fs
|
||||
.tx(|tx| {
|
||||
// Archive_at root node
|
||||
redoxfs::archive_at(tx, Path::new(&mount_path), redoxfs::TreePtr::root())
|
||||
.map_err(|err| syscall::Error::new(err.raw_os_error().unwrap()))?;
|
||||
|
||||
// Squash alloc log
|
||||
tx.sync(true)?;
|
||||
|
||||
let end_block = tx.header.size() / BLOCK_SIZE;
|
||||
/* TODO: Cut off any free blocks at the end of the filesystem
|
||||
let mut end_changed = true;
|
||||
while end_changed {
|
||||
end_changed = false;
|
||||
|
||||
let allocator = fs.allocator();
|
||||
let levels = allocator.levels();
|
||||
for level in 0..levels.len() {
|
||||
let level_size = 1 << level;
|
||||
for &block in levels[level].iter() {
|
||||
if block < end_block && block + level_size >= end_block {
|
||||
end_block = block;
|
||||
end_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Update header
|
||||
tx.header.size = (end_block * BLOCK_SIZE).into();
|
||||
tx.header_changed = true;
|
||||
tx.sync(false)?;
|
||||
|
||||
Ok(end_block)
|
||||
})
|
||||
.map_err(syscall_error)?;
|
||||
|
||||
// let size = (fs.block + end_block) * BLOCK_SIZE;
|
||||
// fs.disk.file.set_len(size)?;
|
||||
}
|
||||
|
||||
fs::remove_dir_all(&mount_path)?;
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
pub fn fetch_bootloaders(
|
||||
config: &Config,
|
||||
cookbook: Option<&str>,
|
||||
@@ -744,42 +805,44 @@ pub fn try_fast_install<D: redoxfs::Disk, F: FnMut(u64, u64)>(
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn install_inner(
|
||||
config: Config,
|
||||
output: &Path,
|
||||
cookbook: Option<&str>,
|
||||
live: bool,
|
||||
write_bootloader: Option<&str>,
|
||||
) -> Result<()> {
|
||||
fn install_inner(config: Config, output: &Path) -> Result<()> {
|
||||
println!("Install {config:#?} to {}", output.display());
|
||||
|
||||
let cookbook = config.general.cookbook.clone();
|
||||
let cookbook = cookbook.as_ref().map(|p| p.as_str());
|
||||
if output.is_dir() {
|
||||
install_dir(config, output, cookbook)
|
||||
} else {
|
||||
let live = config.general.live_disk.unwrap_or(false);
|
||||
let password_opt = config.general.encrypt_disk.clone();
|
||||
let password_opt = password_opt.as_ref().map(|p| p.as_bytes());
|
||||
let (bootloader_bios, bootloader_efi) = fetch_bootloaders(&config, cookbook, live)?;
|
||||
if let Some(write_bootloader) = write_bootloader {
|
||||
if let Some(write_bootloader) = &config.general.write_bootloader {
|
||||
std::fs::write(write_bootloader, &bootloader_efi)?;
|
||||
}
|
||||
let disk_option = DiskOption {
|
||||
bootloader_bios: &bootloader_bios,
|
||||
bootloader_efi: &bootloader_efi,
|
||||
password_opt: None,
|
||||
password_opt: password_opt,
|
||||
efi_partition_size: config.general.efi_partition_size,
|
||||
skip_partitions: config.general.skip_partitions.unwrap_or(false),
|
||||
};
|
||||
with_whole_disk(output, &disk_option, move |fs| {
|
||||
with_redoxfs_mount(fs, move |mount_path| {
|
||||
install_dir(config, mount_path, cookbook)
|
||||
})
|
||||
if config.general.no_mount.unwrap_or(false) {
|
||||
with_redoxfs_ar(fs, move |mount_path| {
|
||||
install_dir(config, mount_path, cookbook)
|
||||
})
|
||||
} else {
|
||||
with_redoxfs_mount(fs, move |mount_path| {
|
||||
install_dir(config, mount_path, cookbook)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
pub fn install(
|
||||
config: Config,
|
||||
output: impl AsRef<Path>,
|
||||
cookbook: Option<&str>,
|
||||
live: bool,
|
||||
write_bootloader: Option<&str>,
|
||||
) -> Result<()> {
|
||||
install_inner(config, output.as_ref(), cookbook, live, write_bootloader)
|
||||
|
||||
/// Install RedoxFS into a new disk file, or a sysroot directory.
|
||||
/// This function assumes all interactive prompts resolved by the caller,
|
||||
/// so "prompt" option is ignored from this function onward.
|
||||
pub fn install(config: Config, output: impl AsRef<Path>) -> Result<()> {
|
||||
install_inner(config, output.as_ref())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user