Use pkgar_head files for installer_tui
This commit is contained in:
+132
-73
@@ -1,11 +1,25 @@
|
||||
extern crate arg_parser;
|
||||
#[macro_use] extern crate failure;
|
||||
extern crate pkgar;
|
||||
extern crate pkgar_core;
|
||||
extern crate pkgar_keys;
|
||||
extern crate redox_installer;
|
||||
extern crate serde;
|
||||
extern crate termion;
|
||||
extern crate toml;
|
||||
|
||||
use pkgar::{PackageHead, ext::EntryExt};
|
||||
use pkgar_core::PackageSrc;
|
||||
use pkgar_keys::PublicKeyFile;
|
||||
use redox_installer::{Config, with_redoxfs};
|
||||
use std::{fs, io, process};
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
fs,
|
||||
io::{self, Read, Write},
|
||||
os::unix::fs::{MetadataExt, OpenOptionsExt, symlink},
|
||||
path::Path,
|
||||
process
|
||||
};
|
||||
use termion::input::TermRead;
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
@@ -76,24 +90,106 @@ fn format_size(size: u64) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
fn dir_files(dir: &str, files: &mut Vec<String>) -> io::Result<()> {
|
||||
for entry_res in fs::read_dir(&format!("file:/{}", dir))? {
|
||||
let entry = entry_res?;
|
||||
let path = entry.path();
|
||||
let path_str = path.into_os_string().into_string().map_err(|_| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"Failed to convert Path to &str"
|
||||
)
|
||||
})?;
|
||||
let path_trimmed = path_str.trim_start_matches("file:/");
|
||||
let metadata = entry.metadata()?;
|
||||
if metadata.is_dir() {
|
||||
dir_files(path_trimmed, files)?;
|
||||
} else {
|
||||
files.push(path_trimmed.to_string());
|
||||
fn copy_file(src: &Path, dest: &Path, buf: &mut [u8]) -> Result<(), failure::Error> {
|
||||
if let Some(parent) = dest.parent() {
|
||||
match fs::create_dir_all(&parent) {
|
||||
Ok(()) => (),
|
||||
Err(err) => {
|
||||
return Err(format_err!("failed to create directory {}: {}", parent.display(), err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let metadata = match fs::symlink_metadata(&src) {
|
||||
Ok(ok) => ok,
|
||||
Err(err) => {
|
||||
return Err(format_err!("failed to read metadata of {}: {}", src.display(), err));
|
||||
},
|
||||
};
|
||||
|
||||
if metadata.file_type().is_symlink() {
|
||||
let real_src = match fs::read_link(&src) {
|
||||
Ok(ok) => ok,
|
||||
Err(err) => {
|
||||
return Err(format_err!("failed to read link {}: {}", src.display(), err));
|
||||
}
|
||||
};
|
||||
|
||||
match symlink(&real_src, &dest) {
|
||||
Ok(()) => (),
|
||||
Err(err) => {
|
||||
return Err(format_err!("failed to copy link {} ({}) to {}: {}", src.display(), real_src.display(), dest.display(), err));
|
||||
},
|
||||
}
|
||||
} else {
|
||||
let mut src_file = match fs::File::open(&src) {
|
||||
Ok(ok) => ok,
|
||||
Err(err) => {
|
||||
return Err(format_err!("failed to open file {}: {}", src.display(), err));
|
||||
}
|
||||
};
|
||||
|
||||
let mut dest_file = match fs::OpenOptions::new().write(true).create_new(true).mode(metadata.mode()).open(&dest) {
|
||||
Ok(ok) => ok,
|
||||
Err(err) => {
|
||||
return Err(format_err!("failed to create file {}: {}", dest.display(), err));
|
||||
}
|
||||
};
|
||||
|
||||
loop {
|
||||
let count = match src_file.read(buf) {
|
||||
Ok(ok) => ok,
|
||||
Err(err) => {
|
||||
return Err(format_err!("failed to read file {}: {}", src.display(), err));
|
||||
}
|
||||
};
|
||||
|
||||
if count == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
match dest_file.write_all(&buf[..count]) {
|
||||
Ok(()) => (),
|
||||
Err(err) => {
|
||||
return Err(format_err!("failed to write file {}: {}", dest.display(), err));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn package_files(root_path: &Path, config: &mut Config, files: &mut Vec<String>) -> Result<(), pkgar::Error> {
|
||||
//TODO: Remove packages from config where all files are located (and have valid shasum?)
|
||||
config.packages.clear();
|
||||
|
||||
let pkey_path = "pkg/id_ed25519.pub.toml";
|
||||
let pkey = PublicKeyFile::open(&root_path.join(pkey_path))?.pkey;
|
||||
files.push(pkey_path.to_string());
|
||||
|
||||
for item_res in fs::read_dir(&root_path.join("pkg"))? {
|
||||
let item = item_res?;
|
||||
let pkg_path = item.path();
|
||||
if pkg_path.extension() == Some(OsStr::new("pkgar_head")) {
|
||||
let mut pkg = PackageHead::new(&pkg_path, &root_path, &pkey)?;
|
||||
for entry in pkg.read_entries()? {
|
||||
files.push(
|
||||
entry
|
||||
.check_path()?
|
||||
.to_str().unwrap()
|
||||
.to_string()
|
||||
);
|
||||
}
|
||||
files.push(
|
||||
pkg_path
|
||||
.strip_prefix(root_path).unwrap()
|
||||
.to_str().unwrap()
|
||||
.to_string()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -158,16 +254,18 @@ fn choose_password() -> Option<String> {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let root_path = Path::new("file:");
|
||||
|
||||
let disk_path = choose_disk();
|
||||
|
||||
let password_opt = choose_password();
|
||||
|
||||
let bootloader = {
|
||||
let path = "file:/bootloader";
|
||||
let mut bootloader = match fs::read(path) {
|
||||
let path = root_path.join("bootloader");
|
||||
let mut bootloader = match fs::read(&path) {
|
||||
Ok(ok) => ok,
|
||||
Err(err) => {
|
||||
eprintln!("installer_tui: {}: failed to read: {}", path, err);
|
||||
eprintln!("installer_tui: {}: failed to read: {}", path.display(), err);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
@@ -182,26 +280,20 @@ fn main() {
|
||||
|
||||
let res = with_redoxfs(&disk_path, password_opt.as_ref().map(|x| x.as_bytes()), &bootloader, |mount_path| -> Result<(), failure::Error> {
|
||||
let mut config: Config = {
|
||||
let path = "file:/filesystem.toml";
|
||||
match fs::read_to_string(path) {
|
||||
let path = root_path.join("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))
|
||||
);
|
||||
return Err(format_err!("{}: failed to decode: {}", path.display(), err));
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
eprintln!("installer_tui: {}: failed to read: {}", path, err);
|
||||
return Err(failure::Error::from_boxed_compat(
|
||||
Box::new(err))
|
||||
);
|
||||
return Err(format_err!("{}: failed to read: {}", path.display(), err));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -213,55 +305,22 @@ fn main() {
|
||||
"kernel".to_string()
|
||||
];
|
||||
|
||||
// Copy files from known directories
|
||||
//TODO: Use package data
|
||||
for dir in [
|
||||
"bin",
|
||||
"etc",
|
||||
"include",
|
||||
"lib",
|
||||
"pkg",
|
||||
"share",
|
||||
"ssl",
|
||||
"ui"
|
||||
].iter() {
|
||||
if let Err(err) = dir_files(dir, &mut files) {
|
||||
eprintln!("installer_tui: failed to read files from {}: {}", dir, err);
|
||||
return Err(failure::Error::from_boxed_compat(
|
||||
Box::new(err))
|
||||
);
|
||||
}
|
||||
// Copy files from locally installed packages
|
||||
if let Err(err) = package_files(&root_path, &mut config, &mut files) {
|
||||
return Err(format_err!("failed to read package files: {}", err));
|
||||
}
|
||||
|
||||
// Packages are copied by previous code
|
||||
config.packages.clear();
|
||||
// Sort and remove duplicates
|
||||
files.sort();
|
||||
files.dedup();
|
||||
|
||||
let mut buf = vec![0; 4 * 1024 * 1024];
|
||||
for (i, name) in files.iter().enumerate() {
|
||||
eprintln!("copy {} [{}/{}]", name, i, files.len());
|
||||
|
||||
let src = format!("file:/{}", name);
|
||||
let src = root_path.join(name);
|
||||
let dest = mount_path.join(name);
|
||||
if let Some(parent) = dest.parent() {
|
||||
match fs::create_dir_all(&parent) {
|
||||
Ok(()) => (),
|
||||
Err(err) => {
|
||||
eprintln!("installer_tui: failed to create directory {}: {}", parent.display(), err);
|
||||
return Err(failure::Error::from_boxed_compat(
|
||||
Box::new(err))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match fs::copy(&src, &dest) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
eprintln!("installer_tui: failed to copy file {} to {}: {}", src, dest.display(), err);
|
||||
return Err(failure::Error::from_boxed_compat(
|
||||
Box::new(err))
|
||||
);
|
||||
}
|
||||
}
|
||||
copy_file(&src, &dest, &mut buf)?;
|
||||
}
|
||||
|
||||
eprintln!("finished copying {} files", files.len());
|
||||
@@ -285,7 +344,7 @@ fn main() {
|
||||
process::exit(0);
|
||||
},
|
||||
Err(err) => {
|
||||
eprintln!("installer_tui: failed to install: {:?}", err);
|
||||
eprintln!("installer_tui: failed to install: {}", err);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user