From fd14207a48cbd2220737e111f857d5abfccadbf7 Mon Sep 17 00:00:00 2001 From: Shiva Kiran Koninty Date: Tue, 25 Aug 2026 09:55:49 +0530 Subject: [PATCH 01/12] Add test `verify_cli()` for all programs --- src/drive-info/cli.rs | 12 ++++++++++++ src/iso-cp/cli.rs | 12 ++++++++++++ src/iso-ls/cli.rs | 12 ++++++++++++ src/mmc-cli/cli.rs | 12 ++++++++++++ 4 files changed, 48 insertions(+) diff --git a/src/drive-info/cli.rs b/src/drive-info/cli.rs index 7480f4d..84ed88a 100644 --- a/src/drive-info/cli.rs +++ b/src/drive-info/cli.rs @@ -39,3 +39,15 @@ pub struct DriveArg { #[arg(value_name = "DRIVE")] pub positional: Option, } + +#[cfg(test)] +mod tests { + use clap::CommandFactory; + + use super::*; + + #[test] + fn verify_cli() { + Cli::command().debug_assert(); + } +} diff --git a/src/iso-cp/cli.rs b/src/iso-cp/cli.rs index f157d02..d9dbc63 100644 --- a/src/iso-cp/cli.rs +++ b/src/iso-cp/cli.rs @@ -51,3 +51,15 @@ pub struct FileArg { #[arg(value_name = "FILE")] pub positional: Option, } + +#[cfg(test)] +mod tests { + use clap::CommandFactory; + + use super::*; + + #[test] + fn verify_cli() { + Cli::command().debug_assert(); + } +} diff --git a/src/iso-ls/cli.rs b/src/iso-ls/cli.rs index bd9d404..4f73492 100644 --- a/src/iso-ls/cli.rs +++ b/src/iso-ls/cli.rs @@ -64,3 +64,15 @@ pub struct FileArg { #[arg(value_name = "FILE")] pub positional: Option, } + +#[cfg(test)] +mod tests { + use clap::CommandFactory; + + use super::*; + + #[test] + fn verify_cli() { + Cli::command().debug_assert(); + } +} diff --git a/src/mmc-cli/cli.rs b/src/mmc-cli/cli.rs index 8f7fc85..0b6dfba 100644 --- a/src/mmc-cli/cli.rs +++ b/src/mmc-cli/cli.rs @@ -59,3 +59,15 @@ pub struct MmcActions { #[arg(short = 'S', long)] pub speed: Option, } + +#[cfg(test)] +mod tests { + use clap::CommandFactory; + + use super::*; + + #[test] + fn verify_cli() { + Cli::command().debug_assert(); + } +} From 17b176d31efa44f75ef76cedd0462f64d9efe096 Mon Sep 17 00:00:00 2001 From: Shiva Kiran Koninty Date: Tue, 25 Aug 2026 09:56:08 +0530 Subject: [PATCH 02/12] iso-ls: Remove `no_rock_ridge` option This was carried on from `iso-info` with the original plan of making it a drop in replacement. However, given that this has been renamed to `iso-ls`, it now can be an independent program, and is free to make improvements or shed options that are not so useful. Always use rock ridge extensions for files that support them. --- src/iso-ls/cli.rs | 4 ---- src/iso-ls/main.rs | 11 +++-------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/iso-ls/cli.rs b/src/iso-ls/cli.rs index 4f73492..527af09 100644 --- a/src/iso-ls/cli.rs +++ b/src/iso-ls/cli.rs @@ -31,10 +31,6 @@ pub struct Cli { #[arg(short = 'l', long, group = "listing")] pub iso9660: bool, - /// Do not use Rock Ridge extensions - #[arg(long)] - pub no_rock_ridge: bool, - /// Do not use CD-ROM XA extensions #[arg(long)] pub no_xa: bool, diff --git a/src/iso-ls/main.rs b/src/iso-ls/main.rs index 7d251da..0bc1468 100644 --- a/src/iso-ls/main.rs +++ b/src/iso-ls/main.rs @@ -66,7 +66,7 @@ fn main() -> Result<()> { print_joliet_level(&iso, &mut output).context("io error while printing joliet level")?; if cli.iso9660 { - print_iso9660_contents(&iso, &mut output, !cli.no_rock_ridge, !cli.no_xa) + print_iso9660_contents(&iso, &mut output, !cli.no_xa) .context("error printing iso9660 contents")?; } @@ -108,12 +108,7 @@ fn print_rock_ridge( } /// Outputs the file contents of the ISO 9660 image in an ls-like listing format. -fn print_iso9660_contents( - iso: &Iso, - mut out: impl io::Write, - use_rock_ridge: bool, - use_xa: bool, -) -> Result<()> { +fn print_iso9660_contents(iso: &Iso, mut out: impl io::Write, use_xa: bool) -> Result<()> { const ISO9660_DEPTH_LIMIT: usize = 512; let mut dirs = VecDeque::new(); dirs.push_back(("/".to_owned(), 0)); // (path, depth) @@ -129,7 +124,7 @@ fn print_iso9660_contents( writeln!(out, "{}:", dir_path)?; for entry in iso.read_dir(dir_path.clone())? { - let rock_ridge = use_rock_ridge.then_some(entry.rock_ridge()).flatten(); + let rock_ridge = entry.rock_ridge(); let entry_name = if rock_ridge.is_none() { entry.filename()? } else { From e320fa4cec14bc3494fb6fdbc9f69ffd1746a2a5 Mon Sep 17 00:00:00 2001 From: Shiva Kiran Koninty Date: Tue, 25 Aug 2026 10:00:08 +0530 Subject: [PATCH 03/12] iso-ls: Remove `no_xa` option --- src/iso-ls/cli.rs | 4 ---- src/iso-ls/main.rs | 7 +++---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/iso-ls/cli.rs b/src/iso-ls/cli.rs index 527af09..299b7d0 100644 --- a/src/iso-ls/cli.rs +++ b/src/iso-ls/cli.rs @@ -31,10 +31,6 @@ pub struct Cli { #[arg(short = 'l', long, group = "listing")] pub iso9660: bool, - /// Do not use CD-ROM XA extensions - #[arg(long)] - pub no_xa: bool, - /// Check if the image uses Rock Ridge extensions by considering a maximum /// of FILE_COUNT files. Provide '0' to check all files. #[arg(short = 'r', long, value_name = "FILE_COUNT")] diff --git a/src/iso-ls/main.rs b/src/iso-ls/main.rs index 0bc1468..749983b 100644 --- a/src/iso-ls/main.rs +++ b/src/iso-ls/main.rs @@ -66,8 +66,7 @@ fn main() -> Result<()> { print_joliet_level(&iso, &mut output).context("io error while printing joliet level")?; if cli.iso9660 { - print_iso9660_contents(&iso, &mut output, !cli.no_xa) - .context("error printing iso9660 contents")?; + print_iso9660_contents(&iso, &mut output).context("error printing iso9660 contents")?; } Ok(()) @@ -108,7 +107,7 @@ fn print_rock_ridge( } /// Outputs the file contents of the ISO 9660 image in an ls-like listing format. -fn print_iso9660_contents(iso: &Iso, mut out: impl io::Write, use_xa: bool) -> Result<()> { +fn print_iso9660_contents(iso: &Iso, mut out: impl io::Write) -> Result<()> { const ISO9660_DEPTH_LIMIT: usize = 512; let mut dirs = VecDeque::new(); dirs.push_back(("/".to_owned(), 0)); // (path, depth) @@ -149,7 +148,7 @@ fn print_iso9660_contents(iso: &Iso, mut out: impl io::Write, use_xa: bool) -> R write!(out, " {}", rock.group_id)?; write!(out, " [LSN {:6}]", entry.lsn())?; write!(out, " {:9}", total_size)?; - } else if use_xa && let Some(xa) = entry.xa() { + } else if let Some(xa) = entry.xa() { write!(out, " {}", xa_file_mode_str(xa.file_attr))?; write!(out, " {}", xa.user_id)?; write!(out, " {}", xa.group_id)?; From 096d786a61de892007d10fb4ffbf2288ed9020ed Mon Sep 17 00:00:00 2001 From: Shiva Kiran Koninty Date: Tue, 25 Aug 2026 10:02:23 +0530 Subject: [PATCH 04/12] iso-ls: Remove `show_rock_ridge` option This is better displayed by default in the metadata section. --- src/iso-ls/cli.rs | 5 ----- src/iso-ls/main.rs | 19 ------------------- 2 files changed, 24 deletions(-) diff --git a/src/iso-ls/cli.rs b/src/iso-ls/cli.rs index 299b7d0..67f9f27 100644 --- a/src/iso-ls/cli.rs +++ b/src/iso-ls/cli.rs @@ -31,11 +31,6 @@ pub struct Cli { #[arg(short = 'l', long, group = "listing")] pub iso9660: bool, - /// Check if the image uses Rock Ridge extensions by considering a maximum - /// of FILE_COUNT files. Provide '0' to check all files. - #[arg(short = 'r', long, value_name = "FILE_COUNT")] - pub show_rock_ridge: Option, - /// Produce only error outputs. #[arg(short, long)] pub quiet: bool, diff --git a/src/iso-ls/main.rs b/src/iso-ls/main.rs index 749983b..f9e8f82 100644 --- a/src/iso-ls/main.rs +++ b/src/iso-ls/main.rs @@ -57,12 +57,6 @@ fn main() -> Result<()> { print_iso9660_metadata(&iso, &file, &mut output) .context("io error while printing iso9660 metadata")?; - if cli.show_rock_ridge.is_some() { - let file_limit = cli.show_rock_ridge.filter(|file_limit| *file_limit != 0); - print_rock_ridge(&iso, file_limit, &mut output) - .context("io error while printing rock ridge status")?; - } - print_joliet_level(&iso, &mut output).context("io error while printing joliet level")?; if cli.iso9660 { @@ -93,19 +87,6 @@ fn print_iso9660_metadata( Ok(()) } -fn print_rock_ridge( - iso: &Iso, - file_limit: Option, - mut out: impl io::Write, -) -> Result<(), io::Error> { - let status = match iso.have_rock_ridge(file_limit) { - Ok(true) => "yes", - Ok(false) => "no", - _ => "possibly not", - }; - writeln!(out, "Rock Ridge : {}", status) -} - /// Outputs the file contents of the ISO 9660 image in an ls-like listing format. fn print_iso9660_contents(iso: &Iso, mut out: impl io::Write) -> Result<()> { const ISO9660_DEPTH_LIMIT: usize = 512; From 3662fb820fab3b64b9c2a56b4aa972aa9df8c753 Mon Sep 17 00:00:00 2001 From: Shiva Kiran Koninty Date: Tue, 25 Aug 2026 10:44:57 +0530 Subject: [PATCH 05/12] iso-ls: Accept image as a positional and not as an option --- src/iso-ls/cli.rs | 20 ++++---------------- src/iso-ls/main.rs | 5 +---- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/src/iso-ls/cli.rs b/src/iso-ls/cli.rs index 67f9f27..48c623b 100644 --- a/src/iso-ls/cli.rs +++ b/src/iso-ls/cli.rs @@ -17,15 +17,15 @@ use std::path::PathBuf; -use clap::{Args, Parser}; +use clap::Parser; /// Inspect metadata and list contents of ISO 9660 and UDF files. #[derive(Parser)] #[command(arg_required_else_help = true, long_about = libcdio_cli::HEADER, version)] pub struct Cli { - /// The file argument as an option or a positional argument - #[command(flatten)] - pub file: FileArg, + /// Path to an ISO 9660 or UDF image. + #[arg(value_name = "IMAGE")] + pub image: PathBuf, /// Show contents of ISO9660 image in long listing format #[arg(short = 'l', long, group = "listing")] @@ -40,18 +40,6 @@ pub struct Cli { pub udf: bool, } -#[derive(Args)] -#[group(required = true, multiple = false)] -pub struct FileArg { - /// Path to an ISO9660 and/or UDF image - #[arg(short = 'i', long = "input", value_name = "FILE")] - pub option: Option, - - /// Path to an ISO9660 and/or UDF image - #[arg(value_name = "FILE")] - pub positional: Option, -} - #[cfg(test)] mod tests { use clap::CommandFactory; diff --git a/src/iso-ls/main.rs b/src/iso-ls/main.rs index f9e8f82..9ec0567 100644 --- a/src/iso-ls/main.rs +++ b/src/iso-ls/main.rs @@ -45,10 +45,7 @@ fn main() -> Result<()> { } else { &mut io::stdout() }; - let file = cli.file.positional.or(cli.file.option).expect( - "the cli logic must ensure that the file argument is provided either as a positional or as an option", - ); - + let file = cli.image; if cli.udf { return print_udf_contents(file, &mut output); } From 8eb5c365e64db45503850dcdf019f9f1a25158c1 Mon Sep 17 00:00:00 2001 From: Shiva Kiran Koninty Date: Tue, 25 Aug 2026 10:56:10 +0530 Subject: [PATCH 06/12] iso-ls: Add `metadata` option for image metadata Update to print metadata only when this option is set. --- src/iso-ls/cli.rs | 4 ++++ src/iso-ls/main.rs | 19 +++++++++++-------- tests/iso-ls.rs | 15 +++++++++++---- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/iso-ls/cli.rs b/src/iso-ls/cli.rs index 48c623b..9b422b1 100644 --- a/src/iso-ls/cli.rs +++ b/src/iso-ls/cli.rs @@ -27,6 +27,10 @@ pub struct Cli { #[arg(value_name = "IMAGE")] pub image: PathBuf, + /// Print image metadata. + #[arg(short, long)] + pub metadata: bool, + /// Show contents of ISO9660 image in long listing format #[arg(short = 'l', long, group = "listing")] pub iso9660: bool, diff --git a/src/iso-ls/main.rs b/src/iso-ls/main.rs index 9ec0567..0e15f8c 100644 --- a/src/iso-ls/main.rs +++ b/src/iso-ls/main.rs @@ -46,19 +46,22 @@ fn main() -> Result<()> { &mut io::stdout() }; let file = cli.image; + + if cli.metadata { + let iso = Iso::new(file.clone())?; + print_iso9660_metadata(&iso, &file, &mut output) + .context("io error while printing iso9660 metadata")?; + print_joliet_level(&iso, &mut output).context("io error while printing joliet level")?; + + return Ok(()); + } + if cli.udf { return print_udf_contents(file, &mut output); } let iso = Iso::new(file.clone())?; - print_iso9660_metadata(&iso, &file, &mut output) - .context("io error while printing iso9660 metadata")?; - - print_joliet_level(&iso, &mut output).context("io error while printing joliet level")?; - - if cli.iso9660 { - print_iso9660_contents(&iso, &mut output).context("error printing iso9660 contents")?; - } + print_iso9660_contents(&iso, &mut output).context("error printing iso9660 contents")?; Ok(()) } diff --git a/tests/iso-ls.rs b/tests/iso-ls.rs index ed73ca9..508670e 100644 --- a/tests/iso-ls.rs +++ b/tests/iso-ls.rs @@ -17,6 +17,7 @@ No Joliet extensions #[test] fn rock_metadata() { cmd() + .arg("-m") .arg(ROCK_RIDGE_FILE) .assert() .success() @@ -36,6 +37,7 @@ Joliet Level: 3 #[test] fn joliet_metadata() { cmd() + .arg("-m") .arg(JOLIET_FILE) .assert() .success() @@ -52,7 +54,12 @@ No Joliet extensions "; #[test] fn xa_metadata() { - cmd().arg(XA_FILE).assert().success().stdout(XA_METADATA); + cmd() + .arg("-m") + .arg(XA_FILE) + .assert() + .success() + .stdout(XA_METADATA); } static ROCK_CONTENTS: &str = r"__________________________________ @@ -86,7 +93,7 @@ fn rock_contents() { .arg(ROCK_RIDGE_FILE) .assert() .success() - .stdout(ROCK_METADATA.to_owned() + ROCK_CONTENTS); + .stdout(ROCK_CONTENTS); } static JOLIET_CONTENTS: &str = r"__________________________________ @@ -118,7 +125,7 @@ fn joliet_contents() { .arg(JOLIET_FILE) .assert() .success() - .stdout(JOLIET_METADATA.to_owned() + JOLIET_CONTENTS); + .stdout(JOLIET_CONTENTS); } static XA_CONTENTS: &str = r"__________________________________ @@ -137,7 +144,7 @@ fn xa_contents() { .arg(XA_FILE) .assert() .success() - .stdout(XA_METADATA.to_owned() + XA_CONTENTS); + .stdout(XA_CONTENTS); } static UDF_FILE: &str = "tests/data/udf.iso"; From eea904bd2e3f301161ca8dbc40eaf239d79ca1f8 Mon Sep 17 00:00:00 2001 From: Shiva Kiran Koninty Date: Tue, 25 Aug 2026 11:09:12 +0530 Subject: [PATCH 07/12] iso-ls: Remove `iso9660` and `udf` options in favor of auto detection Make the program try reading the file as a UDF filesystem first, followed by a fallback to ISO 9660 if that fails. --- src/iso-ls/cli.rs | 8 -------- src/iso-ls/main.rs | 18 +++++++++++------- tests/iso-ls.rs | 4 ---- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/iso-ls/cli.rs b/src/iso-ls/cli.rs index 9b422b1..ac351fa 100644 --- a/src/iso-ls/cli.rs +++ b/src/iso-ls/cli.rs @@ -31,17 +31,9 @@ pub struct Cli { #[arg(short, long)] pub metadata: bool, - /// Show contents of ISO9660 image in long listing format - #[arg(short = 'l', long, group = "listing")] - pub iso9660: bool, - /// Produce only error outputs. #[arg(short, long)] pub quiet: bool, - - /// Show contents of UDF image in long listing format - #[arg(short = 'U', long, group = "listing")] - pub udf: bool, } #[cfg(test)] diff --git a/src/iso-ls/main.rs b/src/iso-ls/main.rs index 0e15f8c..083edc5 100644 --- a/src/iso-ls/main.rs +++ b/src/iso-ls/main.rs @@ -56,14 +56,18 @@ fn main() -> Result<()> { return Ok(()); } - if cli.udf { - return print_udf_contents(file, &mut output); - } - - let iso = Iso::new(file.clone())?; - print_iso9660_contents(&iso, &mut output).context("error printing iso9660 contents")?; + let Err(udf_err) = print_udf_contents(file.clone(), &mut output) else { + return Ok(()); + }; - Ok(()) + match Iso::new(file) { + Ok(iso) => { + print_iso9660_contents(&iso, &mut output).context("error printing iso9660 contents") + } + Err(iso_err) => bail!( + "could not open image as UDF or ISO 9660:\n udf error: {udf_err:?}\n iso error: {iso_err:?}", + ), + } } fn print_iso9660_metadata( diff --git a/tests/iso-ls.rs b/tests/iso-ls.rs index 508670e..e9318a4 100644 --- a/tests/iso-ls.rs +++ b/tests/iso-ls.rs @@ -89,7 +89,6 @@ ISO-9660 Information fn rock_contents() { cmd() .env("TZ", "UTC") - .arg("-l") .arg(ROCK_RIDGE_FILE) .assert() .success() @@ -121,7 +120,6 @@ ISO-9660 Information fn joliet_contents() { cmd() .env("TZ", "UTC") - .arg("-l") .arg(JOLIET_FILE) .assert() .success() @@ -140,7 +138,6 @@ ISO-9660 Information fn xa_contents() { cmd() .env("TZ", "UTC") - .arg("-l") .arg(XA_FILE) .assert() .success() @@ -157,7 +154,6 @@ static UDF_OUTPUT: &str = "/: fn udf() { cmd() .env("TZ", "UTC") - .arg("-U") .arg(UDF_FILE) .assert() .success() From aa768ddc18fb8fad026ce79e79eb8f396f2a47e1 Mon Sep 17 00:00:00 2001 From: Shiva Kiran Koninty Date: Tue, 25 Aug 2026 11:15:07 +0530 Subject: [PATCH 08/12] iso-ls: Remove redundant line and banner in output --- src/iso-ls/main.rs | 7 +------ tests/iso-ls.rs | 21 ++++++--------------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/src/iso-ls/main.rs b/src/iso-ls/main.rs index 083edc5..0da59cd 100644 --- a/src/iso-ls/main.rs +++ b/src/iso-ls/main.rs @@ -33,7 +33,6 @@ use crate::cli::Cli; const DATE_FMT: &[BorrowedFormatItem] = format_description!("[month repr:short] [day] [year] [hour]:[minute]:[second]"); -static LINE: &str = "__________________________________"; fn main() -> Result<()> { let cli = Cli::parse(); @@ -75,8 +74,7 @@ fn print_iso9660_metadata( path: &Path, mut out: impl io::Write, ) -> Result<(), io::Error> { - writeln!(out, "{LINE}")?; - writeln!(out, "ISO 9660 image: {}", path.display())?; + writeln!(out, "Image : {}", path.display())?; let mut write_if_some = |key, val| { let Some(val) = val else { return Ok(()) }; writeln!(out, "{key} : {val}") @@ -97,9 +95,6 @@ fn print_iso9660_contents(iso: &Iso, mut out: impl io::Write) -> Result<()> { let mut dirs = VecDeque::new(); dirs.push_back(("/".to_owned(), 0)); // (path, depth) - writeln!(out, "{}", LINE)?; - writeln!(out, "ISO-9660 Information")?; - while let Some((dir_path, depth)) = dirs.pop_front() { if depth == ISO9660_DEPTH_LIMIT { bail!("directory recursion too deep. ISO most probably damaged"); diff --git a/tests/iso-ls.rs b/tests/iso-ls.rs index e9318a4..f7830a1 100644 --- a/tests/iso-ls.rs +++ b/tests/iso-ls.rs @@ -5,8 +5,7 @@ fn cmd() -> Command { } static ROCK_RIDGE_FILE: &str = "tests/data/rock-ridge.iso"; -static ROCK_METADATA: &str = r"__________________________________ -ISO 9660 image: tests/data/rock-ridge.iso +static ROCK_METADATA: &str = r"Image : tests/data/rock-ridge.iso Application : K3B THE CD KREATOR VERSION 0.11.20 (C) 2003 SEBASTIAN TRUEG AND THE K3B TEAM Preparer : K3b - Version 0.11.20 Publisher : Rocky Bernstein @@ -25,8 +24,7 @@ fn rock_metadata() { } static JOLIET_FILE: &str = "tests/data/joliet.iso"; -static JOLIET_METADATA: &str = r"__________________________________ -ISO 9660 image: tests/data/joliet.iso +static JOLIET_METADATA: &str = r"Image : tests/data/joliet.iso Application : K3B THE CD KREATOR VERSION 0.11.12 (C) 2003 SEBASTIAN TRUEG AND THE K3B TEAM Preparer : K3b - Version 0.11.12 Publisher : Rocky Bernstein @@ -45,8 +43,7 @@ fn joliet_metadata() { } static XA_FILE: &str = "tests/data/xa.iso"; -static XA_METADATA: &str = r"__________________________________ -ISO 9660 image: tests/data/xa.iso +static XA_METADATA: &str = r"Image : tests/data/xa.iso Application : GENISOIMAGE ISO 9660/HFS FILESYSTEM CREATOR (C) 1993 E.YOUNGDALE (C) 1997-2006 J.PEARSON/J.SCHILLING (C) 2006-2007 CDRKIT TEAM System : LINUX Volume : CDROM @@ -62,9 +59,7 @@ fn xa_metadata() { .stdout(XA_METADATA); } -static ROCK_CONTENTS: &str = r"__________________________________ -ISO-9660 Information -/: +static ROCK_CONTENTS: &str = r"/: dr-xr-xr-x 4 0 0 [LSN 23] 2048 Oct 22 2004 02:21:14 . dr-xr-xr-x 2 0 0 [LSN 23] 2048 Oct 22 2004 02:21:14 .. dr-xr-xr-x 2 0 0 [LSN 24] 2048 Mar 05 2005 16:12:25 copy @@ -95,9 +90,7 @@ fn rock_contents() { .stdout(ROCK_CONTENTS); } -static JOLIET_CONTENTS: &str = r"__________________________________ -ISO-9660 Information -/: +static JOLIET_CONTENTS: &str = r"/: d [LSN 31] 2048 Oct 22 2004 22:44:59 . d [LSN 31] 2048 Oct 22 2004 22:44:59 .. d [LSN 32] 2048 Oct 22 2004 22:44:59 libcdio @@ -126,9 +119,7 @@ fn joliet_contents() { .stdout(JOLIET_CONTENTS); } -static XA_CONTENTS: &str = r"__________________________________ -ISO-9660 Information -/: +static XA_CONTENTS: &str = r"/: d---1xrxrxr 1000 3000 [fn 00] [LSN 23] 2048 Jun 08 2026 04:44:35 . d---1xrxrxr 1000 3000 [fn 00] [LSN 23] 2048 Jun 08 2026 04:44:35 .. ----1--xr-- 1000 3000 [fn 00] [LSN 25] 35149 Jun 08 2026 04:43:19 copying From 466e3861f0b5174135985ed87eefa42e27919f04 Mon Sep 17 00:00:00 2001 From: Shiva Kiran Koninty Date: Tue, 25 Aug 2026 11:18:57 +0530 Subject: [PATCH 09/12] iso-ls: Remove `quiet` option The option had been carried over from `iso-info` is not really useful. --- src/iso-ls/cli.rs | 4 ---- src/iso-ls/main.rs | 6 +----- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/iso-ls/cli.rs b/src/iso-ls/cli.rs index ac351fa..4cacd01 100644 --- a/src/iso-ls/cli.rs +++ b/src/iso-ls/cli.rs @@ -30,10 +30,6 @@ pub struct Cli { /// Print image metadata. #[arg(short, long)] pub metadata: bool, - - /// Produce only error outputs. - #[arg(short, long)] - pub quiet: bool, } #[cfg(test)] diff --git a/src/iso-ls/main.rs b/src/iso-ls/main.rs index 0da59cd..b2d8b33 100644 --- a/src/iso-ls/main.rs +++ b/src/iso-ls/main.rs @@ -39,11 +39,7 @@ fn main() -> Result<()> { tracing_subscriber::fmt() .with_env_filter(EnvFilter::from_default_env()) .init(); - let mut output: &mut dyn io::Write = if cli.quiet { - &mut io::sink() - } else { - &mut io::stdout() - }; + let mut output = &mut io::stdout(); let file = cli.image; if cli.metadata { From 16f1e15861dfaae975d7b91e4e712a952c8234e7 Mon Sep 17 00:00:00 2001 From: Shiva Kiran Koninty Date: Tue, 25 Aug 2026 11:31:16 +0530 Subject: [PATCH 10/12] iso-ls: Move `print_joliet_level()` into `print_iso9660_metadata()` --- src/iso-ls/main.rs | 21 ++++++++------------- tests/iso-ls.rs | 6 +++--- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/iso-ls/main.rs b/src/iso-ls/main.rs index b2d8b33..7015d22 100644 --- a/src/iso-ls/main.rs +++ b/src/iso-ls/main.rs @@ -44,11 +44,7 @@ fn main() -> Result<()> { if cli.metadata { let iso = Iso::new(file.clone())?; - print_iso9660_metadata(&iso, &file, &mut output) - .context("io error while printing iso9660 metadata")?; - print_joliet_level(&iso, &mut output).context("io error while printing joliet level")?; - - return Ok(()); + return print_iso9660_metadata(&iso, &file, &mut output).map_err(Into::into); } let Err(udf_err) = print_udf_contents(file.clone(), &mut output) else { @@ -82,6 +78,13 @@ fn print_iso9660_metadata( write_if_some("Volume ", iso.volume())?; write_if_some("Volume Set ", iso.volume_set())?; + let joliet_level = iso.joliet_level().map(|j| format!("Level {}", u8::from(j))); + writeln!( + out, + "Joliet : {}", + joliet_level.as_deref().unwrap_or("no") + )?; + Ok(()) } @@ -245,11 +248,3 @@ fn print_udf_contents(path: PathBuf, out: &mut dyn io::Write) -> Result<()> { Ok(()) } - -fn print_joliet_level(iso: &Iso, mut out: impl io::Write) -> Result<(), io::Error> { - let Some(joliet_level) = iso.joliet_level() else { - return writeln!(out, "No Joliet extensions"); - }; - - writeln!(out, "Joliet Level: {}", u8::from(joliet_level)) -} diff --git a/tests/iso-ls.rs b/tests/iso-ls.rs index f7830a1..baa14b4 100644 --- a/tests/iso-ls.rs +++ b/tests/iso-ls.rs @@ -11,7 +11,7 @@ Preparer : K3b - Version 0.11.20 Publisher : Rocky Bernstein System : LINUX Volume : Rock Ridge Copy test -No Joliet extensions +Joliet : no "; #[test] fn rock_metadata() { @@ -30,7 +30,7 @@ Preparer : K3b - Version 0.11.12 Publisher : Rocky Bernstein System : LINUX Volume : K3b data project -Joliet Level: 3 +Joliet : Level 3 "; #[test] fn joliet_metadata() { @@ -47,7 +47,7 @@ static XA_METADATA: &str = r"Image : tests/data/xa.iso Application : GENISOIMAGE ISO 9660/HFS FILESYSTEM CREATOR (C) 1993 E.YOUNGDALE (C) 1997-2006 J.PEARSON/J.SCHILLING (C) 2006-2007 CDRKIT TEAM System : LINUX Volume : CDROM -No Joliet extensions +Joliet : no "; #[test] fn xa_metadata() { From 26a33947e692d696a8aee2130b787a9a0e0ec4b7 Mon Sep 17 00:00:00 2001 From: Shiva Kiran Koninty Date: Tue, 25 Aug 2026 11:49:29 +0530 Subject: [PATCH 11/12] iso-ls: Show Rock ridge level in metadata output --- src/iso-ls/main.rs | 4 ++++ tests/iso-ls.rs | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/iso-ls/main.rs b/src/iso-ls/main.rs index 7015d22..0bf8695 100644 --- a/src/iso-ls/main.rs +++ b/src/iso-ls/main.rs @@ -85,6 +85,10 @@ fn print_iso9660_metadata( joliet_level.as_deref().unwrap_or("no") )?; + if let Ok(r) = iso.have_rock_ridge(None) { + writeln!(out, "Rock Ridge : {}", if r { "yes" } else { "no" })?; + }; + Ok(()) } diff --git a/tests/iso-ls.rs b/tests/iso-ls.rs index baa14b4..c02a4f9 100644 --- a/tests/iso-ls.rs +++ b/tests/iso-ls.rs @@ -12,6 +12,7 @@ Publisher : Rocky Bernstein System : LINUX Volume : Rock Ridge Copy test Joliet : no +Rock Ridge : yes "; #[test] fn rock_metadata() { @@ -31,6 +32,7 @@ Publisher : Rocky Bernstein System : LINUX Volume : K3b data project Joliet : Level 3 +Rock Ridge : no "; #[test] fn joliet_metadata() { @@ -48,6 +50,7 @@ Application : GENISOIMAGE ISO 9660/HFS FILESYSTEM CREATOR (C) 1993 E.YOUNGDALE ( System : LINUX Volume : CDROM Joliet : no +Rock Ridge : no "; #[test] fn xa_metadata() { From 194ca13e041f9d5b39a70761c2a3537cae626d63 Mon Sep 17 00:00:00 2001 From: Shiva Kiran Koninty Date: Tue, 25 Aug 2026 15:58:08 +0530 Subject: [PATCH 12/12] iso-ls: Add examples in `README.md` --- README.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/README.md b/README.md index 0dbb8ed..4b89209 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,49 @@ Utilities to work with CD/DVD media, ISO 9660 and UDF images. cargo install libcdio-cli ``` +## iso-ls +Lists files of an ISO 9660 or UDF filesystem. +```console +$ iso-ls -h +Inspect metadata and list contents of ISO 9660 and UDF files + +Usage: iso-ls [OPTIONS] + +Arguments: + Path to an ISO 9660 or UDF image + +Options: + -m, --metadata Print image metadata + -h, --help Print help (see more with '--help') + -V, --version Print version +``` + +Listing the contents of a UDF filesystem: +```console +$ iso-ls tests/data/udf1.iso +/: + dr-xr-xr-x 2000 3000 2 88 Jun 19 2026 20:42:57 . + dr-xr-xr-x 2000 3000 1 144 Jun 19 2026 20:42:57 licenses + +/licenses/: + dr-xr-xr-x 2000 3000 2 88 Jun 19 2026 20:42:57 . + -r--r--r-- 2000 3000 1 35149 Jun 19 2026 20:41:12 COPYING + -r--r--r-- 2000 3000 1 7652 Jun 19 2026 20:41:16 COPYING.LESSER +``` + +Listing the image metadata of an ISO 9660 filesystem: +```console +$ iso-ls -m tests/data/joliet.iso +Image : tests/data/joliet.iso +Application : K3B THE CD KREATOR VERSION 0.11.12 (C) 2003 SEBASTIAN TRUEG AND THE K3B TEAM +Preparer : K3b - Version 0.11.12 +Publisher : Rocky Bernstein +System : LINUX +Volume : K3b data project +Joliet : Level 3 +Rock Ridge : no +``` + ## Development ### Use the provided Git Hooks These are set to perform lint and formatting checks before every