Skip to content

Commit

Permalink
Merge pull request #193 from Furisto/rundir
Browse files Browse the repository at this point in the history
Improve looking up the root directory
  • Loading branch information
utam0k committed Aug 8, 2021
2 parents 5bc0778 + 92e986c commit 243d5f6
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 10 deletions.
57 changes: 48 additions & 9 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand All @@ -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)]
Expand Down Expand Up @@ -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 {
Expand All @@ -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 changes: 44 additions & 1 deletion src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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>,
}
Expand Down

0 comments on commit 243d5f6

Please sign in to comment.