Skip to content
Snippets Groups Projects
Verified Commit 5762840f authored by Jeremy Soller's avatar Jeremy Soller
Browse files

Installer TUI (WIP)

parent 39d68618
No related branches found
No related tags found
No related merge requests found
......@@ -592,7 +592,7 @@ dependencies = [
"liner 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_pkgutils 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"redoxfs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"redoxfs 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -637,7 +637,7 @@ dependencies = [
[[package]]
name = "redoxfs"
version = "0.3.6"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuse 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -1054,7 +1054,7 @@ dependencies = [
"checksum redox_pkgutils 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca2450ab3f90ceba523d9df39d4958bc2f437381c2cbdc0fb17ad53994a6bb86"
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum redoxfs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "801d7b3f9ba3f5a68fb1738545ea074cf2f6361e7f4cbf4133a5ecf6086f6ded"
"checksum redoxfs 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3c44da1976bfd3119b225c8ab5906cfb25da5f009b3cff06a4065b9af7ec42d0"
"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a"
"checksum rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf"
......
......@@ -10,6 +10,10 @@ repository = "https://gitlab.redox-os.org/redox-os/installer"
name = "redox_installer"
path = "src/bin/installer.rs"
[[bin]]
name = "redox_installer_tui"
path = "src/bin/installer_tui.rs"
[lib]
name = "redox_installer"
path = "src/lib.rs"
......@@ -21,7 +25,7 @@ libc = "0.2.54"
failure = "0.1.5"
rand = "0.6.5"
redox_pkgutils = "0.1.2"
redoxfs = "0.3.3"
redoxfs = "0.3.7"
rust-argon2 = "0.5"
serde = "1.0.91"
serde_derive = "1.0.91"
......
#![deny(warnings)]
extern crate arg_parser;
extern crate redox_installer;
extern crate serde;
......
extern crate arg_parser;
extern crate redox_installer;
extern crate redoxfs;
extern crate serde;
extern crate toml;
use redoxfs::{DiskFile, FileSystem};
use std::{fs, io, process, sync, thread, time};
use std::ops::DerefMut;
use std::path::Path;
use std::process::Command;
#[cfg(not(target_os = "redox"))]
fn disk_paths(_paths: &mut Vec<(String, u64)>) {}
#[cfg(target_os = "redox")]
fn disk_paths(paths: &mut Vec<(String, u64)>) {
let mut schemes = vec![];
match fs::read_dir(":") {
Ok(entries) => for entry_res in entries {
if let Ok(entry) = entry_res {
if let Ok(path) = entry.path().into_os_string().into_string() {
let scheme = path.trim_start_matches(':').trim_matches('/');
if scheme.starts_with("disk") {
schemes.push(format!("{}:", scheme));
}
}
}
},
Err(err) => {
eprintln!("installer_tui: failed to list schemes: {}", err);
}
}
for scheme in schemes {
match fs::read_dir(&scheme) {
Ok(entries) => for entry_res in entries {
if let Ok(entry) = entry_res {
if let Ok(path) = entry.path().into_os_string().into_string() {
if let Ok(metadata) = entry.metadata() {
let size = metadata.len();
if size > 0 {
paths.push((path, size));
}
}
}
}
},
Err(err) => {
eprintln!("installer_tui: failed to list '{}': {}", scheme, err);
}
}
}
}
const KB: u64 = 1024;
const MB: u64 = 1024 * KB;
const GB: u64 = 1024 * MB;
const TB: u64 = 1024 * GB;
fn format_size(size: u64) -> String {
if size % TB == 0 {
format!("{} TB", size / TB)
} else if size % GB == 0 {
format!("{} GB", size / GB)
} else if size % MB == 0 {
format!("{} MB", size / MB)
} else if size % KB == 0 {
format!("{} KB", size / KB)
} else {
format!("{} B", size)
}
}
fn with_redoxfs<P, T, F>(disk_path: &P, bootloader: &[u8], callback: F)
-> T where
P: AsRef<Path>,
T: Send + Sync + 'static,
F: FnMut(&Path) -> T + Send + Sync + 'static
{
let mount_path = "file/installer_tui";
let res = {
let disk = DiskFile::open(disk_path).unwrap();
if cfg!(not(target_os = "redox")) {
if ! Path::new(mount_path).exists() {
fs::create_dir(mount_path).unwrap();
}
}
let ctime = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap();
let fs = FileSystem::create_reserved(disk, bootloader, ctime.as_secs(), ctime.subsec_nanos()).unwrap();
let callback_mutex = sync::Arc::new(sync::Mutex::new(callback));
let join_handle = redoxfs::mount(fs, mount_path, move |real_path| {
let callback_mutex = callback_mutex.clone();
let real_path = real_path.to_owned();
thread::spawn(move || {
let res = {
let mut callback_guard = callback_mutex.lock().unwrap();
let callback = callback_guard.deref_mut();
callback(&real_path)
};
if cfg!(target_os = "redox") {
fs::remove_file(format!(":{}", mount_path)).unwrap();
} else {
let status_res = if cfg!(target_os = "linux") {
Command::new("fusermount")
.arg("-u")
.arg(mount_path)
.status()
} else {
Command::new("umount")
.arg(mount_path)
.status()
};
let status = status_res.unwrap();
if ! status.success() {
panic!("umount failed");
}
}
res
})
}).unwrap();
join_handle.join().unwrap()
};
fs::remove_file(disk_path).unwrap();
if cfg!(not(target_os = "redox")) {
fs::remove_dir(mount_path).unwrap();
}
res
}
fn main() {
let disk_path = {
let mut paths = Vec::new();
disk_paths(&mut paths);
loop {
for (i, (path, size)) in paths.iter().enumerate() {
eprintln!("\x1B[1m{}\x1B[0m: {}: {}", i + 1, path, format_size(*size));
}
if paths.is_empty() {
eprintln!("installer_tui: no drives found");
process::exit(1);
} else {
eprint!("Select a drive from 1 to {}: ", paths.len());
let mut line = String::new();
match io::stdin().read_line(&mut line) {
Ok(0) => {
eprintln!("installer_tui: failed to read line: end of input");
process::exit(1);
},
Ok(_) => (),
Err(err) => {
eprintln!("installer_tui: failed to read line: {}", err);
process::exit(1);
}
}
match line.trim().parse::<usize>() {
Ok(i) => {
if i >= 1 && i <= paths.len() {
break paths[i - 1].0.clone();
} else {
eprintln!("{} not from 1 to {}", i, paths.len());
}
},
Err(err) => {
eprintln!("invalid input: {}", err);
}
}
}
}
};
let bootloader = {
let path = "file:/bootloader";
match fs::read(path) {
Ok(ok) => ok,
Err(err) => {
eprintln!("installer_tui: {}: failed to read: {}", path, err);
process::exit(1);
}
}
};
let res = with_redoxfs(&disk_path, &bootloader, |mount_path| -> Result<(), failure::Error> {
let config = {
let path = "file:/filesystem.toml";
match fs::read_to_string(path) {
Ok(config_data) => {
match toml::from_str(&config_data) {
Ok(config) => {
config
},
Err(err) => {
eprintln!("installer_tui: {}: failed to decode: {}", path, err);
return Err(failure::Error::from_boxed_compat(
Box::new(err))
);
}
}
},
Err(err) => {
eprintln!("installer_tui: {}: failed to read: {}", path, err);
return Err(failure::Error::from_boxed_compat(
Box::new(err))
);
}
}
};
for name in &["bootloader", "filesystem.toml", "kernel"] {
eprintln!("copy {}", name);
let src = format!("file:/{}", name);
let dest = mount_path.join(name);
match fs::copy(&src, &dest) {
Ok(_) => (),
Err(err) => {
eprintln!("installer_tui: {}: failed to copy to {}: {}", src, dest.display(), err);
return Err(failure::Error::from_boxed_compat(
Box::new(err))
);
}
}
};
let cookbook: Option<&'static str> = None;
redox_installer::install(config, mount_path, cookbook)
});
if let Err(err) = res {
eprintln!("installer_tui: failed to install: {}", err);
process::exit(1);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment