mirror of
https://github.com/containers/youki
synced 2024-09-27 22:49:57 +02:00
Improve looking up the root directory
This commit is contained in:
parent
5bc077861e
commit
92e986cf82
57
src/main.rs
57
src/main.rs
@ -5,9 +5,12 @@
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::bail;
|
||||
use anyhow::Result;
|
||||
use clap::Clap;
|
||||
|
||||
use nix::sys::stat::Mode;
|
||||
use nix::unistd::getuid;
|
||||
use youki::commands::create;
|
||||
use youki::commands::delete;
|
||||
use youki::commands::events;
|
||||
@ -23,6 +26,7 @@ use youki::commands::spec_json;
|
||||
use youki::commands::start;
|
||||
use youki::commands::state;
|
||||
use youki::rootless::should_use_rootless;
|
||||
use youki::utils::{self, create_dir_all_with_mode};
|
||||
|
||||
// High-level commandline option definition
|
||||
// This takes global options as well as individual commands as specified in [OCI runtime-spec](https://github.com/opencontainers/runtime-spec/blob/master/runtime.md)
|
||||
@ -31,8 +35,8 @@ use youki::rootless::should_use_rootless;
|
||||
#[clap(version = "0.0.0", author = "youki team")]
|
||||
struct Opts {
|
||||
/// root directory to store container state
|
||||
#[clap(short, long, default_value = "/run/youki")]
|
||||
root: PathBuf,
|
||||
#[clap(short, long)]
|
||||
root: Option<PathBuf>,
|
||||
#[clap(short, long)]
|
||||
log: Option<PathBuf>,
|
||||
#[clap(long)]
|
||||
@ -88,13 +92,7 @@ fn main() -> Result<()> {
|
||||
eprintln!("log init failed: {:?}", e);
|
||||
}
|
||||
|
||||
let root_path = if should_use_rootless() && opts.root.eq(&PathBuf::from("/run/youki")) {
|
||||
PathBuf::from("/tmp/rootless")
|
||||
} else {
|
||||
PathBuf::from(&opts.root)
|
||||
};
|
||||
fs::create_dir_all(&root_path)?;
|
||||
|
||||
let root_path = determine_root_path(opts.root)?;
|
||||
let systemd_cgroup = opts.systemd_cgroup;
|
||||
|
||||
match opts.subcmd {
|
||||
@ -114,3 +112,44 @@ fn main() -> Result<()> {
|
||||
SubCommand::Ps(ps) => ps.exec(root_path),
|
||||
}
|
||||
}
|
||||
|
||||
fn determine_root_path(root_path: Option<PathBuf>) -> Result<PathBuf> {
|
||||
if let Some(path) = root_path {
|
||||
return Ok(path);
|
||||
}
|
||||
|
||||
if !should_use_rootless() {
|
||||
let default = PathBuf::from("/run/youki");
|
||||
utils::create_dir_all(&default)?;
|
||||
return Ok(default);
|
||||
}
|
||||
|
||||
// see https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
if let Ok(path) = std::env::var("XDG_RUNTIME_DIR") {
|
||||
return Ok(PathBuf::from(path));
|
||||
}
|
||||
|
||||
// XDG_RUNTIME_DIR is not set, try the usual location
|
||||
let uid = getuid().as_raw();
|
||||
let runtime_dir = PathBuf::from(format!("/run/user/{}", uid));
|
||||
if create_dir_all_with_mode(&runtime_dir, uid, Mode::S_IRWXU).is_ok() {
|
||||
return Ok(runtime_dir);
|
||||
}
|
||||
|
||||
if let Ok(path) = std::env::var("HOME") {
|
||||
let home = PathBuf::from(path);
|
||||
if let Ok(resolved) = fs::canonicalize(home) {
|
||||
let run_dir = resolved.join(".youki/run");
|
||||
if create_dir_all_with_mode(&run_dir, uid, Mode::S_IRWXU).is_ok() {
|
||||
return Ok(run_dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let tmp_dir = PathBuf::from(format!("/tmp/youki/{}", uid));
|
||||
if create_dir_all_with_mode(&tmp_dir, uid, Mode::S_IRWXU).is_ok() {
|
||||
return Ok(tmp_dir);
|
||||
}
|
||||
|
||||
bail!("could not find a storage location with suitable permissions for the current user");
|
||||
}
|
||||
|
45
src/utils.rs
45
src/utils.rs
@ -2,13 +2,16 @@
|
||||
|
||||
use std::env;
|
||||
use std::ffi::CString;
|
||||
use std::fs::{self, File};
|
||||
use std::fs::{self, DirBuilder, File};
|
||||
use std::ops::Deref;
|
||||
use std::os::linux::fs::MetadataExt;
|
||||
use std::os::unix::fs::DirBuilderExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Context;
|
||||
use anyhow::{bail, Result};
|
||||
use nix::sys::stat::Mode;
|
||||
use nix::unistd;
|
||||
|
||||
pub trait PathBufExt {
|
||||
@ -106,6 +109,46 @@ pub fn open<P: AsRef<Path>>(path: P) -> Result<File> {
|
||||
File::open(path).with_context(|| format!("failed to open {:?}", path))
|
||||
}
|
||||
|
||||
/// Creates the specified directory and all parent directories with the specified mode. Ensures
|
||||
/// that the directory has been created with the correct mode and that the owner of the directory
|
||||
/// is the owner that has been specified
|
||||
/// # Example
|
||||
/// ``` no_run
|
||||
/// use youki::utils::create_dir_all_with_mode;
|
||||
/// use nix::sys::stat::Mode;
|
||||
/// use std::path::Path;
|
||||
///
|
||||
/// let path = Path::new("/tmp/youki");
|
||||
/// create_dir_all_with_mode(&path, 1000, Mode::S_IRWXU).unwrap();
|
||||
/// assert!(path.exists())
|
||||
/// ```
|
||||
pub fn create_dir_all_with_mode<P: AsRef<Path>>(path: P, owner: u32, mode: Mode) -> Result<()> {
|
||||
let path = path.as_ref();
|
||||
if !path.exists() {
|
||||
DirBuilder::new()
|
||||
.recursive(true)
|
||||
.mode(mode.bits())
|
||||
.create(path)
|
||||
.with_context(|| format!("failed to create directory {}", path.display()))?;
|
||||
}
|
||||
|
||||
let metadata = path
|
||||
.metadata()
|
||||
.with_context(|| format!("failed to get metadata for {}", path.display()))?;
|
||||
|
||||
if metadata.is_dir()
|
||||
&& metadata.st_uid() == owner
|
||||
&& metadata.st_mode() & mode.bits() == mode.bits()
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
bail!(
|
||||
"metadata for {} does not possess the expected attributes",
|
||||
path.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TempDir {
|
||||
path: Option<PathBuf>,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user