Quellcode durchsuchen

feat: 添加一些rootfs命令 (#87)

添加了:
- rootfs create: 添加 `--skip-if-exists`参数,允许当磁盘镜像存在时跳过创建
- rootfs show-mountpoint: 添加该命令,用于获取磁盘挂载点
- rootfs show-loopdevice: 添加该命令,用于获取磁盘镜像被挂载到的磁盘镜像的路径
- rootfs check-disk-image-exists: 用于检查磁盘镜像是否存在

Signed-off-by: longjin <longjin@DragonOS.org>
LoGin vor 4 Monaten
Ursprung
Commit
ce26d6757b

+ 29 - 5
dadk/src/actions/rootfs/disk_img.rs

@@ -168,11 +168,8 @@ pub fn umount(ctx: &DADKExecContext) -> Result<()> {
 
     if let Ok(mut loop_device) = loop_device {
         let loop_dev_path = loop_device.dev_path().cloned();
-        if let Err(e) = loop_device.detach().map_err(|e| anyhow!("{}", e)) {
-            if ctx.rootfs().partition.image_should_be_partitioned() {
-                return Err(e);
-            }
-        }
+        loop_device.detach().ok();
+
         log::info!("Loop device detached: {:?}", loop_dev_path);
     }
 
@@ -247,6 +244,33 @@ fn create_raw_img(disk_image_path: &PathBuf, image_size: usize) -> Result<()> {
     Ok(())
 }
 
+pub fn check_disk_image_exists(ctx: &DADKExecContext) -> Result<()> {
+    let disk_image_path = ctx.disk_image_path();
+    if disk_image_path.exists() {
+        println!("1");
+    } else {
+        println!("0");
+    }
+    Ok(())
+}
+
+pub fn show_mount_point(ctx: &DADKExecContext) -> Result<()> {
+    let disk_mount_path = ctx.disk_mount_path();
+    println!("{}", disk_mount_path.display());
+    Ok(())
+}
+
+pub fn show_loop_device(ctx: &DADKExecContext) -> Result<()> {
+    let disk_image_path = ctx.disk_image_path();
+    let mut loop_device = LoopDeviceBuilder::new().img_path(disk_image_path).build()?;
+    if let Err(e) = loop_device.attach_by_exists() {
+        log::error!("Failed to attach loop device: {}", e);
+    } else {
+        println!("{}", loop_device.dev_path().unwrap());
+    }
+    Ok(())
+}
+
 struct DiskPartitioner;
 
 impl DiskPartitioner {

+ 30 - 2
dadk/src/actions/rootfs/loopdev.rs

@@ -11,6 +11,8 @@ const LOOP_DEVICE_LOSETUP_A_REGEX: &str = r"^/dev/loop(\d+)";
 pub struct LoopDevice {
     img_path: Option<PathBuf>,
     loop_device_path: Option<String>,
+    /// 尝试在drop时自动detach
+    try_detach_when_drop: bool,
 }
 impl LoopDevice {
     pub fn attached(&self) -> bool {
@@ -111,6 +113,12 @@ impl LoopDevice {
             return Ok(());
         }
         let loop_device = self.loop_device_path.take().unwrap();
+        let p = PathBuf::from(&loop_device);
+        log::trace!(
+            "Detach loop device: {}, exists: {}",
+            p.display(),
+            p.exists()
+        );
         let output = Command::new("losetup")
             .arg("-d")
             .arg(loop_device)
@@ -127,12 +135,23 @@ impl LoopDevice {
             ))
         }
     }
+
+    pub fn try_detach_when_drop(&self) -> bool {
+        self.try_detach_when_drop
+    }
+
+    #[allow(dead_code)]
+    pub fn set_try_detach_when_drop(&mut self, try_detach_when_drop: bool) {
+        self.try_detach_when_drop = try_detach_when_drop;
+    }
 }
 
 impl Drop for LoopDevice {
     fn drop(&mut self) {
-        if let Err(e) = self.detach() {
-            log::warn!("Failed to detach loop device: {}", e);
+        if self.try_detach_when_drop() {
+            if let Err(e) = self.detach() {
+                log::warn!("Failed to detach loop device: {}", e);
+            }
         }
     }
 }
@@ -140,6 +159,7 @@ impl Drop for LoopDevice {
 pub struct LoopDeviceBuilder {
     img_path: Option<PathBuf>,
     loop_device_path: Option<String>,
+    try_detach_when_drop: bool,
 }
 
 impl LoopDeviceBuilder {
@@ -147,6 +167,7 @@ impl LoopDeviceBuilder {
         LoopDeviceBuilder {
             img_path: None,
             loop_device_path: None,
+            try_detach_when_drop: true,
         }
     }
 
@@ -155,10 +176,17 @@ impl LoopDeviceBuilder {
         self
     }
 
+    #[allow(dead_code)]
+    pub fn try_detach_when_drop(mut self, try_detach_when_drop: bool) -> Self {
+        self.try_detach_when_drop = try_detach_when_drop;
+        self
+    }
+
     pub fn build(self) -> Result<LoopDevice> {
         let loop_dev = LoopDevice {
             img_path: self.img_path,
             loop_device_path: self.loop_device_path,
+            try_detach_when_drop: self.try_detach_when_drop,
         };
 
         Ok(loop_dev)

+ 4 - 1
dadk/src/actions/rootfs/mod.rs

@@ -7,10 +7,13 @@ mod sysroot;
 
 pub(super) fn run(ctx: &DADKExecContext, rootfs_cmd: &RootFSCommand) -> Result<()> {
     match rootfs_cmd {
-        RootFSCommand::Create => disk_img::create(ctx, false),
+        RootFSCommand::Create(param) => disk_img::create(ctx, param.skip_if_exists),
         RootFSCommand::Delete => disk_img::delete(ctx, false),
         RootFSCommand::DeleteSysroot => sysroot::delete(ctx),
         RootFSCommand::Mount => disk_img::mount(ctx),
         RootFSCommand::Umount => disk_img::umount(ctx),
+        RootFSCommand::CheckDiskImageExists => disk_img::check_disk_image_exists(ctx),
+        RootFSCommand::ShowMountPoint => disk_img::show_mount_point(ctx),
+        RootFSCommand::ShowLoopDevice => disk_img::show_loop_device(ctx),
     }
 }

+ 17 - 3
dadk/src/console/rootfs.rs

@@ -1,10 +1,10 @@
-use clap::{Parser, ValueEnum};
+use clap::Parser;
 
 // 定义一个枚举类型 RootFSCommand,表示根文件系统操作命令
-#[derive(Debug, Parser, Clone, PartialEq, Eq, ValueEnum)]
+#[derive(Debug, Parser, Clone, PartialEq, Eq)]
 pub enum RootFSCommand {
     /// 创建根文件系统(磁盘镜像)
-    Create,
+    Create(CreateCommandParam),
     /// 删除根文件系统(磁盘镜像)
     Delete,
     /// 删除系统根目录(sysroot文件夹)
@@ -13,4 +13,18 @@ pub enum RootFSCommand {
     Mount,
     /// 卸载根文件系统(磁盘镜像)
     Umount,
+    /// 输出磁盘镜像的挂载点
+    #[clap(name = "show-mountpoint")]
+    ShowMountPoint,
+    /// 输出磁盘镜像挂载到的loop设备
+    ShowLoopDevice,
+    /// 检查磁盘镜像文件是否存在
+    CheckDiskImageExists,
+}
+
+#[derive(Debug, Parser, Clone, PartialEq, Eq)]
+pub struct CreateCommandParam {
+    /// 当磁盘镜像文件存在时,跳过创建
+    #[clap(long = "skip-if-exists", default_value = "false")]
+    pub skip_if_exists: bool,
 }

+ 24 - 1
dadk/src/console/tests.rs

@@ -1,3 +1,4 @@
+use rootfs::CreateCommandParam;
 use user::UserCleanLevel;
 
 use super::*;
@@ -25,7 +26,29 @@ fn test_command_line_args_with_manifest() {
 #[test]
 fn test_command_line_args_rootfs_subcommand() {
     let args = CommandLineArgs::parse_from(&["dadk", "rootfs", "create"]);
-    assert!(matches!(args.action, Action::Rootfs(RootFSCommand::Create)));
+    assert!(matches!(
+        args.action,
+        Action::Rootfs(RootFSCommand::Create(CreateCommandParam {
+            skip_if_exists: false
+        }))
+    ));
+
+    let args = CommandLineArgs::parse_from(&["dadk", "rootfs", "create", "--skip-if-exists"]);
+    assert!(matches!(
+        args.action,
+        Action::Rootfs(RootFSCommand::Create(CreateCommandParam {
+            skip_if_exists: true
+        }))
+    ));
+}
+
+#[test]
+fn test_show_mountpoint() {
+    let args = CommandLineArgs::parse_from(&["dadk", "rootfs", "show-mountpoint"]);
+    assert!(matches!(
+        args.action,
+        Action::Rootfs(RootFSCommand::ShowMountPoint)
+    ));
 }
 
 #[test]