1
0
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:
Furisto 2021-08-08 01:08:14 +02:00
parent 5bc077861e
commit 92e986cf82
2 changed files with 92 additions and 10 deletions

View File

@ -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");
}

View File

@ -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>,
}