mirror of
https://github.com/NinjaCheetah/rustii.git
synced 2025-06-06 15:31:02 -04:00
Cleaned up error handling and duplicated code in info command
This commit is contained in:
parent
d9e8465f0c
commit
74584b1ffd
@ -5,35 +5,44 @@
|
|||||||
|
|
||||||
use std::{str, fs};
|
use std::{str, fs};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use anyhow::{bail, Context, Result};
|
||||||
use rustii::{title, title::cert, title::tmd, title::ticket, title::wad, title::versions};
|
use rustii::{title, title::cert, title::tmd, title::ticket, title::wad, title::versions};
|
||||||
use crate::filetypes::{WiiFileType, identify_file_type};
|
use crate::filetypes::{WiiFileType, identify_file_type};
|
||||||
|
|
||||||
fn tid_to_ascii(tid: [u8; 8]) -> Option<String> {
|
// Avoids duplicated code, since both TMD and Ticket info print the TID in the same way.
|
||||||
let tid = String::from_utf8_lossy(&tid[4..]).trim_end_matches('\0').trim_start_matches('\0').to_owned();
|
fn print_tid(title_id: [u8; 8]) -> Result<()> {
|
||||||
if tid.len() == 4 {
|
let ascii = String::from_utf8_lossy(&title_id[4..]).trim_end_matches('\0').trim_start_matches('\0').to_owned();
|
||||||
Some(tid)
|
let ascii_tid = if ascii.len() == 4 {
|
||||||
|
Some(ascii)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
};
|
||||||
|
if ascii_tid.is_some() {
|
||||||
|
println!(" Title ID: {} ({})", hex::encode(title_id).to_uppercase(), ascii_tid.unwrap());
|
||||||
|
} else {
|
||||||
|
println!(" Title ID: {}", hex::encode(title_id).to_uppercase());
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_tmd_info(tmd: tmd::TMD, cert: Option<cert::Certificate>) {
|
// Same as above, both the TMD and Ticket info print the title version in the same way.
|
||||||
|
fn print_title_version(title_version: u16, title_id: [u8; 8], is_vwii: bool) -> Result<()> {
|
||||||
|
let converted_ver = versions::dec_to_standard(title_version, &hex::encode(title_id), Some(is_vwii));
|
||||||
|
if hex::encode(title_id).eq("0000000100000001") {
|
||||||
|
println!(" Title Version: {} (boot2v{})", title_version, title_version);
|
||||||
|
} else if hex::encode(title_id)[..8].eq("00000001") && converted_ver.is_some() {
|
||||||
|
println!(" Title Version: {} ({})", title_version, converted_ver.unwrap());
|
||||||
|
} else {
|
||||||
|
println!(" Title Version: {}", title_version);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_tmd_info(tmd: tmd::TMD, cert: Option<cert::Certificate>) -> Result<()> {
|
||||||
// Print all important keys from the TMD.
|
// Print all important keys from the TMD.
|
||||||
println!("Title Info");
|
println!("Title Info");
|
||||||
let ascii_tid = tid_to_ascii(tmd.title_id);
|
print_tid(tmd.title_id)?;
|
||||||
if ascii_tid.is_some() {
|
print_title_version(tmd.title_version, tmd.title_id, tmd.is_vwii())?;
|
||||||
println!(" Title ID: {} ({})", hex::encode(tmd.title_id).to_uppercase(), ascii_tid.unwrap());
|
|
||||||
} else {
|
|
||||||
println!(" Title ID: {}", hex::encode(tmd.title_id).to_uppercase());
|
|
||||||
}
|
|
||||||
let converted_ver = versions::dec_to_standard(tmd.title_version, &hex::encode(tmd.title_id), Some(tmd.is_vwii != 0));
|
|
||||||
if hex::encode(tmd.title_id).eq("0000000100000001") {
|
|
||||||
println!(" Title Version: {} (boot2v{})", tmd.title_version, tmd.title_version);
|
|
||||||
} else if hex::encode(tmd.title_id)[..8].eq("00000001") && converted_ver.is_some() {
|
|
||||||
println!(" Title Version: {} ({})", tmd.title_version, converted_ver.unwrap());
|
|
||||||
} else {
|
|
||||||
println!(" Title Version: {}", tmd.title_version);
|
|
||||||
}
|
|
||||||
println!(" TMD Version: {}", tmd.tmd_version);
|
println!(" TMD Version: {}", tmd.tmd_version);
|
||||||
if hex::encode(tmd.ios_tid).eq("0000000000000000") {
|
if hex::encode(tmd.ios_tid).eq("0000000000000000") {
|
||||||
println!(" Required IOS: N/A");
|
println!(" Required IOS: N/A");
|
||||||
@ -115,25 +124,14 @@ fn print_tmd_info(tmd: tmd::TMD, cert: Option<cert::Certificate>) {
|
|||||||
println!(" Content Size: {} bytes", content.content_size);
|
println!(" Content Size: {} bytes", content.content_size);
|
||||||
println!(" Content Hash: {}", hex::encode(content.content_hash));
|
println!(" Content Hash: {}", hex::encode(content.content_hash));
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_ticket_info(ticket: ticket::Ticket, cert: Option<cert::Certificate>) {
|
fn print_ticket_info(ticket: ticket::Ticket, cert: Option<cert::Certificate>) -> Result<()> {
|
||||||
// Print all important keys from the Ticket.
|
// Print all important keys from the Ticket.
|
||||||
println!("Ticket Info");
|
println!("Ticket Info");
|
||||||
let ascii_tid = tid_to_ascii(ticket.title_id);
|
print_tid(ticket.title_id)?;
|
||||||
if ascii_tid.is_some() {
|
print_title_version(ticket.title_version, ticket.title_id, ticket.common_key_index == 2)?;
|
||||||
println!(" Title ID: {} ({})", hex::encode(ticket.title_id).to_uppercase(), ascii_tid.unwrap());
|
|
||||||
} else {
|
|
||||||
println!(" Title ID: {}", hex::encode(ticket.title_id).to_uppercase());
|
|
||||||
}
|
|
||||||
let converted_ver = versions::dec_to_standard(ticket.title_version, &hex::encode(ticket.title_id), Some(ticket.common_key_index == 2));
|
|
||||||
if hex::encode(ticket.title_id).eq("0000000100000001") {
|
|
||||||
println!(" Title Version: {} (boot2v{})", ticket.title_version, ticket.title_version);
|
|
||||||
} else if hex::encode(ticket.title_id)[..8].eq("00000001") && converted_ver.is_some() {
|
|
||||||
println!(" Title Version: {} ({})", ticket.title_version, converted_ver.unwrap());
|
|
||||||
} else {
|
|
||||||
println!(" Title Version: {}", ticket.title_version);
|
|
||||||
}
|
|
||||||
println!(" Ticket Version: {}", ticket.ticket_version);
|
println!(" Ticket Version: {}", ticket.ticket_version);
|
||||||
let signature_issuer = String::from_utf8(Vec::from(ticket.signature_issuer)).unwrap_or_default();
|
let signature_issuer = String::from_utf8(Vec::from(ticket.signature_issuer)).unwrap_or_default();
|
||||||
if signature_issuer.contains("XS00000003") {
|
if signature_issuer.contains("XS00000003") {
|
||||||
@ -184,25 +182,26 @@ fn print_ticket_info(ticket: ticket::Ticket, cert: Option<cert::Certificate>) {
|
|||||||
} else {
|
} else {
|
||||||
println!(" Fakesigned: {}", ticket.is_fakesigned());
|
println!(" Fakesigned: {}", ticket.is_fakesigned());
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_wad_info(wad: wad::WAD) {
|
fn print_wad_info(wad: wad::WAD) -> Result<()> {
|
||||||
println!("WAD Info");
|
println!("WAD Info");
|
||||||
match wad.header.wad_type {
|
match wad.header.wad_type {
|
||||||
wad::WADType::ImportBoot => { println!(" WAD Type: boot2") },
|
wad::WADType::ImportBoot => { println!(" WAD Type: boot2") },
|
||||||
wad::WADType::Installable => { println!(" WAD Type: Standard Installable") },
|
wad::WADType::Installable => { println!(" WAD Type: Standard Installable") },
|
||||||
}
|
}
|
||||||
// Create a Title for size info, signing info and TMD/Ticket info.
|
// Create a Title for size info, signing info and TMD/Ticket info.
|
||||||
let title = title::Title::from_wad(&wad).unwrap();
|
let title = title::Title::from_wad(&wad).with_context(|| "The provided WAD file could not be parsed, and is likely invalid.")?;
|
||||||
let min_size_blocks = title.title_size_blocks(None).unwrap();
|
let min_size_blocks = title.title_size_blocks(None)?;
|
||||||
let max_size_blocks = title.title_size_blocks(Some(true)).unwrap();
|
let max_size_blocks = title.title_size_blocks(Some(true))?;
|
||||||
if min_size_blocks == max_size_blocks {
|
if min_size_blocks == max_size_blocks {
|
||||||
println!(" Installed Size: {} blocks", min_size_blocks);
|
println!(" Installed Size: {} blocks", min_size_blocks);
|
||||||
} else {
|
} else {
|
||||||
println!(" Installed Size: {}-{} blocks", min_size_blocks, max_size_blocks);
|
println!(" Installed Size: {}-{} blocks", min_size_blocks, max_size_blocks);
|
||||||
}
|
}
|
||||||
let min_size = title.title_size(None).unwrap() as f64 / 1048576.0;
|
let min_size = title.title_size(None)? as f64 / 1048576.0;
|
||||||
let max_size = title.title_size(Some(true)).unwrap() as f64 / 1048576.0;
|
let max_size = title.title_size(Some(true))? as f64 / 1048576.0;
|
||||||
if min_size == max_size {
|
if min_size == max_size {
|
||||||
println!(" Installed Size (MB): {:.2} MB", min_size);
|
println!(" Installed Size (MB): {:.2} MB", min_size);
|
||||||
} else {
|
} else {
|
||||||
@ -216,9 +215,9 @@ fn print_wad_info(wad: wad::WAD) {
|
|||||||
false => {
|
false => {
|
||||||
if title.is_fakesigned() {
|
if title.is_fakesigned() {
|
||||||
"Fakesigned"
|
"Fakesigned"
|
||||||
} else if cert::verify_tmd(&title.cert_chain.tmd_cert(), &title.tmd).unwrap() {
|
} else if cert::verify_tmd(&title.cert_chain.tmd_cert(), &title.tmd)? {
|
||||||
"Piratelegit (Unmodified TMD, Modified Ticket)"
|
"Piratelegit (Unmodified TMD, Modified Ticket)"
|
||||||
} else if cert::verify_ticket(&title.cert_chain.ticket_cert(), &title.ticket).unwrap() {
|
} else if cert::verify_ticket(&title.cert_chain.ticket_cert(), &title.ticket)? {
|
||||||
"Edited (Modified TMD, Unmodified Ticket)"
|
"Edited (Modified TMD, Unmodified Ticket)"
|
||||||
} else {
|
} else {
|
||||||
"Illegitimate (Modified TMD + Ticket)"
|
"Illegitimate (Modified TMD + Ticket)"
|
||||||
@ -235,31 +234,33 @@ fn print_wad_info(wad: wad::WAD) {
|
|||||||
};
|
};
|
||||||
println!(" Signing Status: {}", signing_str);
|
println!(" Signing Status: {}", signing_str);
|
||||||
println!();
|
println!();
|
||||||
print_ticket_info(title.ticket, Some(title.cert_chain.ticket_cert()));
|
print_ticket_info(title.ticket, Some(title.cert_chain.ticket_cert()))?;
|
||||||
println!();
|
println!();
|
||||||
print_tmd_info(title.tmd, Some(title.cert_chain.tmd_cert()));
|
print_tmd_info(title.tmd, Some(title.cert_chain.tmd_cert()))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn info(input: &str) {
|
pub fn info(input: &str) -> Result<()> {
|
||||||
let in_path = Path::new(input);
|
let in_path = Path::new(input);
|
||||||
if !in_path.exists() {
|
if !in_path.exists() {
|
||||||
panic!("Error: Input file does not exist.");
|
bail!("Input file \"{}\" does not exist.", in_path.display());
|
||||||
}
|
}
|
||||||
match identify_file_type(input) {
|
match identify_file_type(input) {
|
||||||
Some(WiiFileType::Tmd) => {
|
Some(WiiFileType::Tmd) => {
|
||||||
let tmd = tmd::TMD::from_bytes(fs::read(in_path).unwrap().as_slice()).unwrap();
|
let tmd = tmd::TMD::from_bytes(fs::read(in_path)?.as_slice()).with_context(|| "The provided TMD file could not be parsed, and is likely invalid.")?;
|
||||||
print_tmd_info(tmd, None);
|
print_tmd_info(tmd, None)?;
|
||||||
},
|
},
|
||||||
Some(WiiFileType::Ticket) => {
|
Some(WiiFileType::Ticket) => {
|
||||||
let ticket = ticket::Ticket::from_bytes(fs::read(in_path).unwrap().as_slice()).unwrap();
|
let ticket = ticket::Ticket::from_bytes(fs::read(in_path)?.as_slice()).with_context(|| "The provided Ticket file could not be parsed, and is likely invalid.")?;
|
||||||
print_ticket_info(ticket, None);
|
print_ticket_info(ticket, None)?;
|
||||||
},
|
},
|
||||||
Some(WiiFileType::Wad) => {
|
Some(WiiFileType::Wad) => {
|
||||||
let wad = wad::WAD::from_bytes(fs::read(in_path).unwrap().as_slice()).unwrap();
|
let wad = wad::WAD::from_bytes(fs::read(in_path)?.as_slice()).with_context(|| "The provided WAD file could not be parsed, and is likely invalid.")?;
|
||||||
print_wad_info(wad);
|
print_wad_info(wad)?;
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
println!("Error: Information cannot be displayed for this file.");
|
bail!("Information cannot be displayed for this file type.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ fn main() -> Result<()> {
|
|||||||
fakesign::fakesign(input, output)?
|
fakesign::fakesign(input, output)?
|
||||||
},
|
},
|
||||||
Some(Commands::Info { input }) => {
|
Some(Commands::Info { input }) => {
|
||||||
info::info(input)
|
info::info(input)?
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,7 @@ pub fn unpack_wad(input: &str, output: &str) -> Result<()> {
|
|||||||
let tid = hex::encode(title.tmd.title_id);
|
let tid = hex::encode(title.tmd.title_id);
|
||||||
// Create output directory if it doesn't exist.
|
// Create output directory if it doesn't exist.
|
||||||
let out_path = Path::new(output);
|
let out_path = Path::new(output);
|
||||||
if !Path::new(out_path).exists() {
|
if !out_path.exists() {
|
||||||
fs::create_dir(out_path).with_context(|| format!("The output directory \"{}\" could not be created.", out_path.display()))?;
|
fs::create_dir(out_path).with_context(|| format!("The output directory \"{}\" could not be created.", out_path.display()))?;
|
||||||
}
|
}
|
||||||
// Write out all WAD components.
|
// Write out all WAD components.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user