Commit 5762840f authored by Jeremy Soller's avatar Jeremy Soller

Installer TUI (WIP)

parent 39d68618
......@@ -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);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment