diff --git a/xdvdfs-cli/src/cmd_read.rs b/xdvdfs-cli/src/cmd_read.rs index 243f137..c30fe09 100644 --- a/xdvdfs-cli/src/cmd_read.rs +++ b/xdvdfs-cli/src/cmd_read.rs @@ -1,4 +1,4 @@ -use std::{fs::File, io::Write, path::Path}; +use std::{fs::File, io::Write, path::PathBuf, str::FromStr}; pub fn cmd_ls(img_path: &str, dir_path: &str) -> Result<(), String> { let mut img = File::options() @@ -58,7 +58,15 @@ pub fn cmd_tree(img_path: &str) -> Result<(), String> { Ok(()) } -pub fn cmd_unpack(img_path: &str, target_dir: &Path) -> Result<(), String> { +pub fn cmd_unpack(img_path: &str, target_dir: &Option) -> Result<(), String> { + let target_dir = match target_dir { + Some(path) => PathBuf::from_str(path).unwrap(), + None => { + let os_path = PathBuf::from_str(img_path).unwrap(); + PathBuf::from(os_path.file_name().unwrap()).with_extension("") + } + }; + let mut img = File::options() .read(true) .open(img_path) @@ -73,10 +81,25 @@ pub fn cmd_unpack(img_path: &str, target_dir: &Path) -> Result<(), String> { let dir = dir.trim_start_matches('/'); let dirname = target_dir.join(dir); let file_path = dirname.join(dirent.get_name()); + let is_dir = dirent.node.dirent.is_directory(); - println!("Extracting file {}", file_path.display()); + println!( + "Extracting {} {}", + if is_dir { "directory" } else { "file" }, + file_path.display() + ); std::fs::create_dir_all(dirname).map_err(|e| e.to_string())?; + if dirent.node.dirent.is_directory() { + std::fs::create_dir(file_path).map_err(|e| e.to_string())?; + continue; + } + + if dirent.node.dirent.filename_length == 0 { + eprintln!("WARNING: {:?} has an empty file name, skipping", file_path); + continue; + } + let mut file = File::options() .write(true) .truncate(true) diff --git a/xdvdfs-cli/src/main.rs b/xdvdfs-cli/src/main.rs index 0c476fa..3c6c66a 100644 --- a/xdvdfs-cli/src/main.rs +++ b/xdvdfs-cli/src/main.rs @@ -1,5 +1,3 @@ -use std::{path::PathBuf, str::FromStr}; - use clap::{Parser, Subcommand}; mod cmd_info; @@ -37,14 +35,6 @@ enum Cmd { #[arg(help = "Target file within image")] path: Option, }, - #[command(about = "Unpack an entire image to a directory")] - Unpack { - #[arg(help = "Path to XISO image")] - image_path: String, - - #[arg(help = "Output directory")] - path: Option, - }, #[command( about = "Print information about image metadata", long_about = "\ @@ -59,6 +49,14 @@ enum Cmd { #[arg(help = "Path to file/directory within image")] file_entry: Option, }, + #[command(about = "Unpack an entire image to a directory")] + Unpack { + #[arg(help = "Path to XISO image")] + image_path: String, + + #[arg(help = "Output directory")] + path: Option, + }, #[command(about = "Pack an image from a given directory")] Pack { #[arg(help = "Path to source directory")] @@ -69,39 +67,31 @@ enum Cmd { }, } -fn run_command(cmd: &Cmd) { +fn run_command(cmd: &Cmd) -> Result<(), String> { use Cmd::*; - let res = match cmd { + match cmd { Ls { image_path, path } => cmd_read::cmd_ls(image_path, path), Tree { image_path } => cmd_read::cmd_tree(image_path), Md5 { image_path, path } => cmd_md5::cmd_md5(image_path, path.clone().as_deref()), - Unpack { image_path, path } => { - let path = match path { - Some(path) => PathBuf::from_str(path).unwrap(), - None => { - let os_path = PathBuf::from_str(image_path).unwrap(); - PathBuf::from(os_path.file_name().unwrap()).with_extension("") - } - }; - - cmd_read::cmd_unpack(image_path, &path) - } Info { image_path, file_entry, } => cmd_info::cmd_info(image_path, file_entry.as_ref()), + Unpack { image_path, path } => cmd_read::cmd_unpack(image_path, path), Pack { source_path, image_path, } => cmd_pack::cmd_pack(source_path, image_path), - }; - - res.unwrap(); + } } fn main() { let cli = Args::parse(); if let Some(cmd) = cli.command { - run_command(&cmd); + let res = run_command(&cmd); + if let Err(err) = res { + eprintln!("Error: {}", err); + std::process::exit(1); + } } } diff --git a/xdvdfs-core/src/read.rs b/xdvdfs-core/src/read.rs index 273e2fb..3937fef 100644 --- a/xdvdfs-core/src/read.rs +++ b/xdvdfs-core/src/read.rs @@ -198,9 +198,9 @@ impl DirectoryEntryTable { let child_name = core::str::from_utf8(child.name_slice()) .map_err(|e| util::Error::UTFError(e))?; stack.push((format!("{}/{}", parent, child_name), dirent_table)); - } else { - dirents.push((parent.clone(), *child)); } + + dirents.push((parent.clone(), *child)); } }