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.
This commit is contained in:
Generated
+1
@@ -438,6 +438,7 @@ dependencies = [
|
||||
"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)",
|
||||
"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)",
|
||||
"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)",
|
||||
|
||||
@@ -14,6 +14,7 @@ path = "src/lib.rs"
|
||||
arg_parser = { git = "https://github.com/redox-os/arg-parser.git" }
|
||||
argon2rs = { version = "0.2", default-features = false }
|
||||
liner = "0.1"
|
||||
libc = "0.2"
|
||||
failure = "0.1"
|
||||
pkgutils = { git = "https://github.com/redox-os/pkgutils.git" }
|
||||
rand = "0.3"
|
||||
|
||||
+68
-1
@@ -1,7 +1,74 @@
|
||||
|
||||
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)]
|
||||
pub struct FileConfig {
|
||||
pub path: String,
|
||||
pub data: String,
|
||||
#[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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
mod general;
|
||||
mod file;
|
||||
pub(crate) mod file;
|
||||
mod package;
|
||||
mod user;
|
||||
|
||||
|
||||
+15
-32
@@ -3,6 +3,7 @@
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
extern crate argon2rs;
|
||||
extern crate libc;
|
||||
extern crate liner;
|
||||
extern crate failure;
|
||||
extern crate pkgutils;
|
||||
@@ -12,6 +13,7 @@ extern crate termion;
|
||||
mod config;
|
||||
|
||||
pub use config::Config;
|
||||
use config::file::FileConfig;
|
||||
|
||||
use argon2rs::verifier::Encoded;
|
||||
use argon2rs::{Argon2, Variant};
|
||||
@@ -21,15 +23,12 @@ use termion::input::TermRead;
|
||||
use pkgutils::{Repo, Package};
|
||||
|
||||
use std::{env, fs};
|
||||
use std::ffi::OsStr;
|
||||
use std::io::{self, stderr, Write};
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::os::unix::fs::symlink;
|
||||
use std::path::Path;
|
||||
use std::process::{self, Command};
|
||||
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 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
|
||||
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 {
|
||||
@@ -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
|
||||
// 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());
|
||||
|
||||
// TODO: Mount disk if output is a file
|
||||
let output_dir = output_dir.to_owned();
|
||||
|
||||
create_dir_relative("")?;
|
||||
|
||||
install_packages(&config, output_dir.to_str().unwrap(), cookbook);
|
||||
|
||||
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();
|
||||
@@ -233,7 +209,14 @@ pub fn install<P: AsRef<Path>, S: AsRef<str>>(config: Config, output_dir: P, coo
|
||||
}
|
||||
|
||||
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(())
|
||||
|
||||
Reference in New Issue
Block a user