ksud: correctly copy chr device and keep xattr. close #1397
This commit is contained in:
7
userspace/ksud/Cargo.lock
generated
7
userspace/ksud/Cargo.lock
generated
@@ -537,12 +537,6 @@ dependencies = [
|
|||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fs_extra"
|
|
||||||
version = "1.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fuchsia-cprng"
|
name = "fuchsia-cprng"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@@ -806,7 +800,6 @@ dependencies = [
|
|||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"extattr",
|
"extattr",
|
||||||
"fs_extra",
|
|
||||||
"getopts",
|
"getopts",
|
||||||
"hole-punch",
|
"hole-punch",
|
||||||
"humansize",
|
"humansize",
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ sha256 = "1"
|
|||||||
tempdir = "0.3"
|
tempdir = "0.3"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
hole-punch = { git = "https://github.com/tiann/hole-punch" }
|
hole-punch = { git = "https://github.com/tiann/hole-punch" }
|
||||||
fs_extra = "1.3"
|
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies]
|
[target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies]
|
||||||
rustix = { git = "https://github.com/Kernel-SU/rustix.git", branch = "main", features = ["all-apis"] }
|
rustix = { git = "https://github.com/Kernel-SU/rustix.git", branch = "main", features = ["all-apis"] }
|
||||||
|
|||||||
@@ -392,13 +392,7 @@ fn _install_module(zip: &str) -> Result<()> {
|
|||||||
create_module_image(tmp_module_img, sparse_image_size, journal_size)?;
|
create_module_image(tmp_module_img, sparse_image_size, journal_size)?;
|
||||||
let _dontdrop =
|
let _dontdrop =
|
||||||
mount::AutoMountExt4::try_new(tmp_module_img, module_update_tmp_dir, true)?;
|
mount::AutoMountExt4::try_new(tmp_module_img, module_update_tmp_dir, true)?;
|
||||||
fs_extra::dir::copy(
|
utils::copy_module_files(defs::MODULE_DIR, module_update_tmp_dir)?;
|
||||||
defs::MODULE_DIR,
|
|
||||||
module_update_tmp_dir,
|
|
||||||
&fs_extra::dir::CopyOptions::new()
|
|
||||||
.overwrite(true)
|
|
||||||
.content_only(true),
|
|
||||||
)?;
|
|
||||||
} else {
|
} else {
|
||||||
utils::copy_sparse_file(modules_img, tmp_module_img, true).with_context(|| {
|
utils::copy_sparse_file(modules_img, tmp_module_img, true).with_context(|| {
|
||||||
format!(
|
format!(
|
||||||
|
|||||||
@@ -15,14 +15,16 @@ use std::os::unix::prelude::PermissionsExt;
|
|||||||
use hole_punch::*;
|
use hole_punch::*;
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
|
||||||
|
use jwalk::WalkDir;
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
use rustix::{
|
use rustix::{
|
||||||
process,
|
process,
|
||||||
thread::{move_into_link_name_space, unshare, LinkNameSpaceType, UnshareFlags},
|
thread::{move_into_link_name_space, unshare, LinkNameSpaceType, UnshareFlags},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn ensure_clean_dir(dir: &str) -> Result<()> {
|
pub fn ensure_clean_dir(dir: impl AsRef<Path>) -> Result<()> {
|
||||||
let path = Path::new(dir);
|
let path = dir.as_ref();
|
||||||
log::debug!("ensure_clean_dir: {}", path.display());
|
log::debug!("ensure_clean_dir: {}", path.display());
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
log::debug!("ensure_clean_dir: {} exists, remove it", path.display());
|
log::debug!("ensure_clean_dir: {} exists, remove it", path.display());
|
||||||
@@ -241,3 +243,98 @@ pub fn copy_sparse_file<P: AsRef<Path>, Q: AsRef<Path>>(
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
fn copy_xattrs(src_path: impl AsRef<Path>, dest_path: impl AsRef<Path>) -> Result<()> {
|
||||||
|
use rustix::path::Arg;
|
||||||
|
let std::result::Result::Ok(xattrs) = extattr::llistxattr(src_path.as_ref()) else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
for xattr in xattrs {
|
||||||
|
let std::result::Result::Ok(value) = extattr::lgetxattr(src_path.as_ref(), &xattr) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
log::info!(
|
||||||
|
"Set {:?} xattr {} = {}",
|
||||||
|
dest_path.as_ref(),
|
||||||
|
xattr.to_string_lossy(),
|
||||||
|
value.to_string_lossy(),
|
||||||
|
);
|
||||||
|
extattr::lsetxattr(dest_path.as_ref(), &xattr, &value, extattr::Flags::empty())
|
||||||
|
.with_context(|| format!("Failed to set xattr for {:?}", dest_path.as_ref()))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||||
|
pub fn copy_module_files(source: impl AsRef<Path>, destination: impl AsRef<Path>) -> Result<()> {
|
||||||
|
use rustix::fs::FileTypeExt;
|
||||||
|
use rustix::fs::MetadataExt;
|
||||||
|
|
||||||
|
for entry in WalkDir::new(source.as_ref()).into_iter() {
|
||||||
|
let entry = entry.context("Failed to access entry")?;
|
||||||
|
let source_path = entry.path();
|
||||||
|
let relative_path = source_path
|
||||||
|
.strip_prefix(source.as_ref())
|
||||||
|
.context("Failed to generate relative path")?;
|
||||||
|
let dest_path = destination.as_ref().join(relative_path);
|
||||||
|
|
||||||
|
if let Some(parent) = dest_path.parent() {
|
||||||
|
std::fs::create_dir_all(parent).context("Failed to create directory")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry.file_type().is_file() {
|
||||||
|
std::fs::copy(&source_path, &dest_path).with_context(|| {
|
||||||
|
format!(
|
||||||
|
"Failed to copy file from {source_path:?} to {dest_path:?}",
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
copy_xattrs(&source_path, &dest_path)?;
|
||||||
|
} else if entry.file_type().is_symlink() {
|
||||||
|
if dest_path.exists() {
|
||||||
|
std::fs::remove_file(&dest_path).context("Failed to remove file")?;
|
||||||
|
}
|
||||||
|
let target = std::fs::read_link(entry.path()).context("Failed to read symlink")?;
|
||||||
|
log::info!("Symlink: {:?} -> {:?}", dest_path, target);
|
||||||
|
std::os::unix::fs::symlink(target, &dest_path).context("Failed to create symlink")?;
|
||||||
|
copy_xattrs(&source_path, &dest_path)?;
|
||||||
|
} else if entry.file_type().is_dir() {
|
||||||
|
create_dir_all(&dest_path)?;
|
||||||
|
copy_xattrs(&source_path, &dest_path)?;
|
||||||
|
} else if entry.file_type().is_char_device() {
|
||||||
|
if dest_path.exists() {
|
||||||
|
std::fs::remove_file(&dest_path).context("Failed to remove file")?;
|
||||||
|
}
|
||||||
|
let metadata = std::fs::metadata(&source_path).context("Failed to read metadata")?;
|
||||||
|
let mode = metadata.permissions().mode();
|
||||||
|
let dev = metadata.rdev();
|
||||||
|
if dev == 0 {
|
||||||
|
log::info!(
|
||||||
|
"Found a char device with major 0: {}",
|
||||||
|
entry.path().display()
|
||||||
|
);
|
||||||
|
rustix::fs::mknodat(
|
||||||
|
rustix::fs::CWD,
|
||||||
|
&dest_path,
|
||||||
|
rustix::fs::FileType::CharacterDevice,
|
||||||
|
mode.into(),
|
||||||
|
dev,
|
||||||
|
)
|
||||||
|
.with_context(|| format!("Failed to create device file at {dest_path:?}"))?;
|
||||||
|
copy_xattrs(&source_path, &dest_path)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log::info!(
|
||||||
|
"Unknown file type: {:?}, {:?},",
|
||||||
|
entry.file_type(),
|
||||||
|
entry.path(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "linux", target_os = "android")))]
|
||||||
|
pub fn copy_module_files(_source: impl AsRef<Path>, _destination: impl AsRef<Path>) -> Result<()> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user