Commit e58815f8 authored by SamwiseFilmore's avatar SamwiseFilmore

Rudimentary support for permissions

I sorta OOP'ed this, combining the logic of what needs to happen for
each config object with those objects. More things are coming, this is a
very WIP commit.
parent ce6e96bd
...@@ -438,6 +438,7 @@ dependencies = [ ...@@ -438,6 +438,7 @@ dependencies = [
"arg_parser 0.1.0 (git+https://github.com/redox-os/arg-parser.git)", "arg_parser 0.1.0 (git+https://github.com/redox-os/arg-parser.git)",
"argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "liner 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"pkgutils 0.1.1 (git+https://github.com/redox-os/pkgutils.git)", "pkgutils 0.1.1 (git+https://github.com/redox-os/pkgutils.git)",
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
......
...@@ -14,6 +14,7 @@ path = "src/lib.rs" ...@@ -14,6 +14,7 @@ path = "src/lib.rs"
arg_parser = { git = "https://github.com/redox-os/arg-parser.git" } arg_parser = { git = "https://github.com/redox-os/arg-parser.git" }
argon2rs = { version = "0.2", default-features = false } argon2rs = { version = "0.2", default-features = false }
liner = "0.1" liner = "0.1"
libc = "0.2"
failure = "0.1" failure = "0.1"
pkgutils = { git = "https://github.com/redox-os/pkgutils.git" } pkgutils = { git = "https://github.com/redox-os/pkgutils.git" }
rand = "0.3" rand = "0.3"
......
use Result;
use libc::chown;
use std::io::{Error, Write};
use std::ffi::{CString, OsStr};
use std::fs::{self, File};
use std::os::unix::ffi::OsStrExt;
use std::os::unix::fs::{PermissionsExt, symlink};
use std::path::Path;
//type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Default, Deserialize)] #[derive(Debug, Default, Deserialize)]
pub struct FileConfig { pub struct FileConfig {
pub path: String, pub path: String,
pub data: String, pub data: String,
#[serde(default)] #[serde(default)]
pub symlink: bool pub symlink: bool,
pub mode: Option<u32>,
pub uid: Option<u32>,
pub gid: Option<u32>
}
// TODO: Rewrite
impl FileConfig {
pub(crate) fn create<P: AsRef<Path>>(self, prefix: P) -> Result<()> {
let path = self.path.trim_left_matches('/');
let target_file = prefix.as_ref()
.join(path);
println!("target file: {:?}", target_file);
if let Some(parent) = target_file.parent() {
println!("Create file parent {}", parent.display());
fs::create_dir_all(parent)?;
}
if self.symlink {
println!("Create symlink {}", target_file.display());
symlink(&OsStr::new(&self.data), &target_file)?;
Ok(())
} else {
println!("Create file {}", target_file.display());
let mut file = File::create(&target_file)?;
file.write_all(self.data.as_bytes())?;
self.apply_perms(target_file)
}
}
fn apply_perms<P: AsRef<Path>>(&self, target: P) -> Result<()> {
let path = target.as_ref();
let mode = self.mode.unwrap_or(0o0755);
let uid = self.uid.unwrap_or(0);
let gid = self.gid.unwrap_or(0);
// chmod
fs::set_permissions(path, fs::Permissions::from_mode(mode))?;
// chown
let c_path = CString::new(path.as_os_str().as_bytes()).unwrap();
let ret = unsafe {
chown(c_path.as_ptr(), uid, gid)
};
// credit to uutils
if ret == 0 {
Ok(())
} else {
Err(Error::last_os_error().into())
}
}
} }
use std::collections::BTreeMap; use std::collections::BTreeMap;
mod general; mod general;
mod file; pub(crate) mod file;
mod package; mod package;
mod user; mod user;
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
extern crate argon2rs; extern crate argon2rs;
extern crate libc;
extern crate liner; extern crate liner;
extern crate failure; extern crate failure;
extern crate pkgutils; extern crate pkgutils;
...@@ -12,6 +13,7 @@ extern crate termion; ...@@ -12,6 +13,7 @@ extern crate termion;
mod config; mod config;
pub use config::Config; pub use config::Config;
use config::file::FileConfig;
use argon2rs::verifier::Encoded; use argon2rs::verifier::Encoded;
use argon2rs::{Argon2, Variant}; use argon2rs::{Argon2, Variant};
...@@ -21,15 +23,12 @@ use termion::input::TermRead; ...@@ -21,15 +23,12 @@ use termion::input::TermRead;
use pkgutils::{Repo, Package}; use pkgutils::{Repo, Package};
use std::{env, fs}; use std::{env, fs};
use std::ffi::OsStr;
use std::io::{self, stderr, Write}; use std::io::{self, stderr, Write};
use std::os::unix::ffi::OsStrExt;
use std::os::unix::fs::symlink;
use std::path::Path; use std::path::Path;
use std::process::{self, Command}; use std::process::{self, Command};
use std::str::FromStr; use std::str::FromStr;
type Result<T> = std::result::Result<T, Error>; pub(crate) type Result<T> = std::result::Result<T, Error>;
const REMOTE: &'static str = "https://static.redox-os.org/pkg"; const REMOTE: &'static str = "https://static.redox-os.org/pkg";
const TARGET: &'static str = "x86_64-unknown-redox"; const TARGET: &'static str = "x86_64-unknown-redox";
...@@ -133,28 +132,6 @@ pub fn install<P: AsRef<Path>, S: AsRef<str>>(config: Config, output_dir: P, coo ...@@ -133,28 +132,6 @@ pub fn install<P: AsRef<Path>, S: AsRef<str>>(config: Config, output_dir: P, coo
Ok(()) 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(); let mut context = liner::Context::new();
macro_rules! prompt { macro_rules! prompt {
...@@ -172,22 +149,21 @@ pub fn install<P: AsRef<Path>, S: AsRef<str>>(config: Config, output_dir: P, coo ...@@ -172,22 +149,21 @@ pub fn install<P: AsRef<Path>, S: AsRef<str>>(config: Config, output_dir: P, coo
}) })
} }
let output_dir = output_dir.as_ref();
// Using an env var here to communicate the root dir to the functions // Using an env var here to communicate the root dir to the functions
// instead of passing it as a param // instead of passing it as a param
env::set_var(SYSROOT, output_dir.as_ref().as_os_str()); env::set_var(SYSROOT, output_dir.as_os_str());
let output_dir = output_dir.as_ref();
println!("Install {:#?} to {}", config, output_dir.display()); println!("Install {:#?} to {}", config, output_dir.display());
// TODO: Mount disk if output is a file // TODO: Mount disk if output is a file
let output_dir = output_dir.to_owned(); let output_dir = output_dir.to_owned();
create_dir_relative("")?;
install_packages(&config, output_dir.to_str().unwrap(), cookbook); install_packages(&config, output_dir.to_str().unwrap(), cookbook);
for file in config.files { for file in config.files {
create_file_relative(file.path.trim_matches('/'), file.data.as_bytes(), file.symlink)?; file.create(&output_dir)?;
} }
let mut passwd = String::new(); let mut passwd = String::new();
...@@ -233,7 +209,14 @@ pub fn install<P: AsRef<Path>, S: AsRef<str>>(config: Config, output_dir: P, coo ...@@ -233,7 +209,14 @@ pub fn install<P: AsRef<Path>, S: AsRef<str>>(config: Config, output_dir: P, coo
} }
if !passwd.is_empty() { if !passwd.is_empty() {
create_file_relative("etc/passwd", passwd.as_bytes(), false)?; FileConfig {
path: "/etc/passwd".to_string(),
data: passwd,
symlink: false,
mode: Some(0o755),
uid: Some(0),
gid: Some(0)
}.create(output_dir)?;
} }
Ok(()) Ok(())
......
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