diff --git a/config/default.toml b/config/default.toml index 470349cef87e9a341a44575864e5889229f536db..ce7f54d13fad5687af9fd1a6be3bdde6a17e7cd4 100644 --- a/config/default.toml +++ b/config/default.toml @@ -59,8 +59,7 @@ uutils = {} # User settings [users.root] -# Password is set to "password" -password = "$argon2i$m=4096,t=10,p=1$Tnc4UVV0N00$ML9LIOujd3nmAfkAwEcSTMPqakWUF0OUiLWrIy0nGLk" +password = "password" uid = 0 gid = 0 name = "root" diff --git a/config/minimal.toml b/config/minimal.toml index dba20f5d48c8bf979d933811d86d63c9b7de079f..54e41b317e7104d7fa561bd2862568f8f4d0e4fc 100644 --- a/config/minimal.toml +++ b/config/minimal.toml @@ -17,8 +17,7 @@ userutils = {} # User settings [users.root] -# Password is set to "password" -password = "$argon2i$m=4096,t=10,p=1$Tnc4UVV0N00$ML9LIOujd3nmAfkAwEcSTMPqakWUF0OUiLWrIy0nGLk" +password = "password" uid = 0 gid = 0 name = "root" diff --git a/src/lib.rs b/src/lib.rs index 6a2c50df78be4fbc6067ecb3c953023adf4b9ca7..a34ae1de48c7464da5427057dcbd6d0181fd16a2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,7 @@ type Result<T> = std::result::Result<T, Error>; const REMOTE: &'static str = "https://static.redox-os.org/pkg"; const TARGET: &'static str = "x86_64-unknown-redox"; +const SYSROOT: &'static str = "SYSROOT"; /// Converts a password to a serialized argon2rs hash, understandable /// by redox_users. If the password is blank, the hash is blank. @@ -120,12 +121,42 @@ fn install_packages<S: AsRef<str>>(config: &Config, dest: &str, cookbook: Option } } -pub fn install<P: AsRef<Path>, S: AsRef<str>>(config: Config, output: P, cookbook: Option<S>) -> Result<()> { - let output = output.as_ref(); - println!("Install {:#?} to {}", config, output.display()); - +pub fn install<P: AsRef<Path>, S: AsRef<str>>(config: Config, output_dir: P, cookbook: Option<S>) -> Result<()> { + + /// Creates a directory relative to the output directory + fn create_dir_relative<P: AsRef<Path>>(path: P) -> Result<()> { + let root = env::var(SYSROOT)?; + let target_dir = Path::new(&root) + .join(path.as_ref()); + println!("Create directory {}", target_dir.display()); + fs::create_dir_all(&target_dir)?; + Ok(()) + } + + /// Creates a file relative to the output directory + fn create_file_relative<P: AsRef<Path>>(path: P, data: &[u8], is_symlink: bool) -> Result<()> { + let root = env::var(SYSROOT)?; + let target_file = Path::new(&root) + .join(path.as_ref()); + + if let Some(parent) = target_file.parent() { + println!("Create file parent {}", parent.display()); + fs::create_dir_all(parent)?; + } + + if is_symlink { + println!("Create symlink {}", target_file.display()); + symlink(&OsStr::from_bytes(data), &target_file)?; + } else { + println!("Create file {}", target_file.display()); + let mut file = fs::File::create(&target_file)?; + file.write_all(data)?; + } + Ok(()) + } + let mut context = liner::Context::new(); - + macro_rules! prompt { ($dst:expr, $def:expr, $($arg:tt)*) => (if config.general.prompt { match unwrap_or_prompt($dst, &mut context, &format!($($arg)*)) { @@ -141,48 +172,27 @@ pub fn install<P: AsRef<Path>, S: AsRef<str>>(config: Config, output: P, cookboo }) } - // TODO: Mount disk if output is a file - let sysroot = output.to_owned(); - - macro_rules! dir { - ($path:expr) => {{ - let mut path = sysroot.clone(); - path.push($path); - println!("Create directory {}", path.display()); - fs::create_dir_all(&path)?; - }}; - } + // Using an env var here to communicate the root dir to the functions + // instead of passing it as a param + env::set_var(SYSROOT, output_dir.as_ref().as_os_str()); - macro_rules! file { - ($path:expr, $data:expr, $symlink:expr) => {{ - let mut path = sysroot.clone(); - path.push($path); - if let Some(parent) = path.parent() { - println!("Create file parent {}", parent.display()); - fs::create_dir_all(parent)?; - } - if $symlink { - println!("Create symlink {}", path.display()); - symlink(&OsStr::from_bytes($data), &path)?; - } else { - println!("Create file {}", path.display()); - let mut file = fs::File::create(&path)?; - file.write_all($data)?; - } - }}; - } + let output_dir = output_dir.as_ref(); + println!("Install {:#?} to {}", config, output_dir.display()); - dir!(""); + // TODO: Mount disk if output is a file + let output_dir = output_dir.to_owned(); + + create_dir_relative("")?; - install_packages(&config, sysroot.to_str().unwrap(), cookbook); + install_packages(&config, output_dir.to_str().unwrap(), cookbook); for file in config.files { - file!(file.path.trim_matches('/'), file.data.as_bytes(), file.symlink); + create_file_relative(file.path.trim_matches('/'), file.data.as_bytes(), file.symlink)?; } let mut passwd = String::new(); let mut next_uid = 1000; - + for (username, user) in config.users { // plaintext let password = if let Some(password) = user.password { @@ -203,7 +213,7 @@ pub fn install<P: AsRef<Path>, S: AsRef<str>>(config: Config, output: P, cookboo let gid = user.gid.unwrap_or(uid); - let name = prompt!(user.name, username.clone(), "{}: name [{}]: ", username, username)?; + let name = prompt!(user.name, username.clone(), "{}: name (GECOS) [{}]: ", username, username)?; let home = prompt!(user.home, format!("/home/{}", username), "{}: home [/home/{}]: ", username, username)?; let shell = prompt!(user.shell, "/bin/ion".to_string(), "{}: shell [/bin/ion]: ", username)?; @@ -215,15 +225,15 @@ pub fn install<P: AsRef<Path>, S: AsRef<str>>(config: Config, output: P, cookboo println!("\tHome: {}", home); println!("\tShell: {}", shell); - dir!(home.trim_matches('/')); - + create_dir_relative(home.trim_matches('/'))?; + let password = hash_password(&password)?; - + passwd.push_str(&format!("{};{};{};{};{};file:{};file:{}\n", username, password, uid, gid, name, home, shell)); } - - if ! passwd.is_empty() { - file!("etc/passwd", passwd.as_bytes(), false); + + if !passwd.is_empty() { + create_file_relative("etc/passwd", passwd.as_bytes(), false)?; } Ok(())