sysmaster/backport-feature-libbasic-add-remove_dir_until.patch
huyubiao 8936fa02c5 sync patches from upstream,change the path of the unit,modify permissions for some directories and files
(cherry picked from commit ce9ff469b57f60130621bc293783bd3ac1fc92f2)
2023-08-05 18:15:53 +08:00

107 lines
3.4 KiB
Diff

From d9fdd267027d6bf3b8265c18279a7f50c2b62081 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Wed, 21 Jun 2023 21:27:38 +0800
Subject: [PATCH] feature(libbasic): add remove_dir_until
remove_dir_until is used to recursively remove parent directories
which contains nothing until specific directory.
---
libs/basic/src/fs_util.rs | 64 +++++++++++++++++++++++++++++++++++++--
1 file changed, 62 insertions(+), 2 deletions(-)
diff --git a/libs/basic/src/fs_util.rs b/libs/basic/src/fs_util.rs
index 63c43ca..5f34e9a 100644
--- a/libs/basic/src/fs_util.rs
+++ b/libs/basic/src/fs_util.rs
@@ -20,7 +20,7 @@ use nix::{
unistd::{Gid, Uid},
};
use pathdiff::diff_paths;
-use std::{os::unix::prelude::PermissionsExt, path::Path};
+use std::{fs::remove_dir, io::ErrorKind, os::unix::prelude::PermissionsExt, path::Path};
/// open the parent directory of path
pub fn open_parent(path: &Path, flags: OFlag, mode: Mode) -> Result<i32> {
@@ -164,12 +164,55 @@ pub fn futimens_opath(fd: i32, ts: Option<[timespec; 2]>) -> Result<()> {
}
}
+/// recursively remove parent directories until specific directory
+pub fn remove_dir_until(path: &str, stop: &str) -> Result<()> {
+ let path = Path::new(path);
+
+ let mut dir = if path.is_dir() {
+ Path::new(path)
+ } else {
+ match path.parent() {
+ Some(p) => p,
+ None => {
+ return Ok(());
+ }
+ }
+ };
+
+ loop {
+ if let Err(e) = remove_dir(dir) {
+ match e.kind() {
+ ErrorKind::NotFound => break,
+ _ => {
+ return Err(Error::Io { source: e });
+ }
+ }
+ }
+
+ match dir.parent() {
+ Some(p) => {
+ if p.ends_with(stop) {
+ break;
+ }
+ dir = p;
+ }
+ None => break,
+ };
+ }
+
+ Ok(())
+}
+
#[cfg(test)]
mod tests {
use super::*;
use crate::fs_util::symlink;
use nix::unistd::{self};
- use std::{fs::File, os::unix::prelude::MetadataExt, time::SystemTime};
+ use std::{
+ fs::{create_dir_all, File},
+ os::unix::prelude::MetadataExt,
+ time::SystemTime,
+ };
#[test]
fn test_symlink() {
@@ -267,4 +310,21 @@ mod tests {
std::fs::remove_file("/tmp/test_futimens_opath").unwrap();
}
+
+ #[test]
+ fn test_remove_dir_until() {
+ create_dir_all("/tmp/test_remove_dir_until_1/test1").unwrap();
+ assert!(Path::new("/tmp/test_remove_dir_until_1/test1").exists());
+ remove_dir_until("/tmp/test_remove_dir_until_1/test1", "/tmp").unwrap();
+ assert!(!Path::new("/tmp/test_remove_dir_until_1/test1").exists());
+ assert!(!Path::new("/tmp/test_remove_dir_until_1").exists());
+
+ create_dir_all("/tmp/test_remove_dir_until_2/test2").unwrap();
+ File::create("/tmp/test_remove_dir_until_2/test_file").unwrap();
+ assert!(Path::new("/tmp/test_remove_dir_until_2/test2").exists());
+ assert!(Path::new("/tmp/test_remove_dir_until_2/test_file").exists());
+ assert!(remove_dir_until("/tmp/test_remove_dir_until_2/test2", "/tmp").is_err());
+ assert!(!Path::new("/tmp/test_remove_dir_until_2/test2").exists());
+ assert!(Path::new("/tmp/test_remove_dir_until_2/test_file").exists());
+ }
}
--
2.33.0