From afe1a6ac5ae6f5e1d15c6a3b4c829594706f2c01 Mon Sep 17 00:00:00 2001 From: Yohei Ueda Date: Fri, 17 Jun 2022 23:37:13 +0900 Subject: [PATCH] agent: support copying of directories and symlinks This patch allows copying of directories and symlinks when static file copying is used between host and guest. This change is necessary to support recursive file copying between shim and agent. Signed-off-by: Yohei Ueda (cherry picked from commit de232b8030eba9908557ac6546b97e8044685bfc) --- src/agent/src/rpc.rs | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/agent/src/rpc.rs b/src/agent/src/rpc.rs index 30d14d559d..b162d23bfe 100644 --- a/src/agent/src/rpc.rs +++ b/src/agent/src/rpc.rs @@ -8,8 +8,9 @@ use rustjail::{pipestream::PipeStream, process::StreamType}; use tokio::io::{AsyncReadExt, AsyncWriteExt, ReadHalf}; use tokio::sync::Mutex; -use std::ffi::CString; +use std::ffi::{CString, OsStr}; use std::io; +use std::os::unix::ffi::OsStrExt; use std::path::Path; use std::sync::Arc; use ttrpc::{ @@ -1856,6 +1857,38 @@ fn do_copy_file(req: &CopyFileRequest) -> Result<()> { } } + let sflag = stat::SFlag::from_bits_truncate(req.file_mode); + + if sflag.contains(stat::SFlag::S_IFDIR) { + fs::create_dir(&path).or_else(|e| { + if e.kind() != std::io::ErrorKind::AlreadyExists { + return Err(e); + } + Ok(()) + })?; + + std::fs::set_permissions(&path, std::fs::Permissions::from_mode(req.file_mode))?; + + unistd::chown( + &path, + Some(Uid::from_raw(req.uid as u32)), + Some(Gid::from_raw(req.gid as u32)), + )?; + + return Ok(()); + } + + if sflag.contains(stat::SFlag::S_IFLNK) { + let src = PathBuf::from(OsStr::from_bytes(&req.data)); + unistd::symlinkat(&src, None, &path)?; + let path_str = CString::new(path.as_os_str().as_bytes())?; + + let ret = unsafe { libc::lchown(path_str.as_ptr(), req.uid as u32, req.gid as u32) }; + Errno::result(ret).map(drop)?; + + return Ok(()); + } + let mut tmpfile = path.clone(); tmpfile.set_extension("tmp");