Skip to content
This repository was archived by the owner on May 10, 2023. It is now read-only.

Commit 6b12a25

Browse files
authored
Merge pull request #16 from yellowcake-org/develop
Inspect & extract files from .dat
2 parents 853a444 + 6e9933b commit 6b12a25

File tree

10 files changed

+697
-0
lines changed

10 files changed

+697
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ Cargo.lock
88

99
# These are backup files generated by rustfmt
1010
**/*.rs.bk
11+
.DS_Store
12+
.idea

Cargo.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
edition = "2018"
3+
name = "libycresources"
4+
version = "0.1.0"
5+
6+
[[example]]
7+
name = "undat"
8+
9+
[dev-dependencies]
10+
clap = "3.0.0-beta.2"

examples/undat/extract.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
use libycresources::dat;
2+
3+
use std::io::{Read, Seek};
4+
use std::path::PathBuf;
5+
6+
#[derive(Debug)]
7+
pub(crate) enum Error {
8+
Path,
9+
Buffer,
10+
Decompress,
11+
Read(std::io::Error),
12+
Write(std::io::Error),
13+
}
14+
15+
pub(crate) fn tree<R>(reader: &mut R, tree: &dat::Directory, output: &String) -> Result<(), Error>
16+
where
17+
R: Read + Seek,
18+
{
19+
let mut path = PathBuf::new();
20+
21+
for (depth, _, directory) in tree.iter() {
22+
if depth > path.components().count() {
23+
path.push(String::from(&directory.name));
24+
} else {
25+
for _ in 0..path.components().count() - depth {
26+
path.pop();
27+
}
28+
29+
if !path.ends_with(String::from(&directory.name)) {
30+
path.push(String::from(&directory.name));
31+
}
32+
}
33+
34+
for file in &directory.files {
35+
let root = std::path::Path::new(&output);
36+
let full = root.join(&path).join(&file.name);
37+
let path = full.as_path();
38+
39+
println!("{:}", path.display());
40+
41+
let directory = match path.parent() {
42+
None => return Err(Error::Path),
43+
Some(directory) => directory,
44+
};
45+
46+
if let Err(error) = std::fs::create_dir_all(&directory) {
47+
return Err(Error::Write(error));
48+
}
49+
50+
let mut created = match std::fs::File::create(&path) {
51+
Err(error) => return Err(Error::Write(error)),
52+
Ok(created) => created,
53+
};
54+
55+
let mut writer = std::io::BufWriter::with_capacity(1 * 1024 * 1024, &mut created);
56+
57+
if let Err(error) = dat::extract::file(reader, &file, &mut writer) {
58+
return match error {
59+
dat::extract::Error::Source => Err(Error::Buffer),
60+
dat::extract::Error::Decompress => Err(Error::Decompress),
61+
dat::extract::Error::Read(error) => Err(Error::Read(error)),
62+
dat::extract::Error::Write(error) => Err(Error::Write(error)),
63+
};
64+
}
65+
}
66+
}
67+
68+
Ok(())
69+
}

examples/undat/main.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
pub(crate) mod extract;
2+
pub(crate) mod tree;
3+
4+
use libycresources::dat;
5+
6+
use clap::Clap;
7+
use std::fs::File;
8+
9+
#[derive(Clap)]
10+
#[clap(name = "undat", version)]
11+
struct Options {
12+
/// Path to the input arhive file
13+
#[clap(short, long)]
14+
input: String,
15+
#[clap(subcommand)]
16+
action: Action,
17+
}
18+
19+
#[derive(Clap)]
20+
enum Action {
21+
/// Prints arhive contents
22+
Tree,
23+
/// Extracts all archive contents to specified directory
24+
Extract(Extract),
25+
}
26+
27+
#[derive(Clap)]
28+
struct Extract {
29+
output: String,
30+
}
31+
32+
fn main() {
33+
let options = Options::parse();
34+
35+
let file = match File::open(&options.input) {
36+
Err(error) => {
37+
eprintln!("Couldn't open input file: {:?}", error);
38+
return;
39+
}
40+
Ok(value) => value,
41+
};
42+
43+
let mut reader = std::io::BufReader::with_capacity(1 * 1024 * 1024, file);
44+
45+
if let Some(tree) = match dat::parse::tree(&mut reader) {
46+
Err(error) => {
47+
eprintln!("Error occured: {:?}", error);
48+
return;
49+
}
50+
Ok(value) => value,
51+
} {
52+
match options.action {
53+
Action::Tree => {
54+
tree::print(&tree);
55+
}
56+
Action::Extract(arguments) => {
57+
let result = extract::tree(&mut reader, &tree, &arguments.output);
58+
59+
if let Err(error) = result {
60+
eprintln!("Error occured: {:?}", error);
61+
}
62+
}
63+
}
64+
} else {
65+
println!("Input file has zero directories.");
66+
}
67+
}

examples/undat/tree.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use libycresources::dat;
2+
3+
pub(crate) fn print(tree: &dat::Directory) {
4+
let mut flag_path = Vec::new();
5+
6+
for (depth, is_last, directory) in tree.iter() {
7+
if depth > flag_path.iter().count() {
8+
flag_path.push((is_last, &directory.name));
9+
} else {
10+
for _ in 0..flag_path.iter().count() - depth {
11+
flag_path.pop();
12+
}
13+
14+
if flag_path.last() != Some(&(is_last, &directory.name)) {
15+
flag_path.push((is_last, &directory.name));
16+
}
17+
}
18+
19+
for (index, tuple) in flag_path.iter().enumerate() {
20+
if index > 0 {
21+
if tuple.0 {
22+
if index == depth {
23+
print!("└");
24+
} else {
25+
print!(" ");
26+
}
27+
} else {
28+
if index == depth {
29+
print!("├");
30+
} else {
31+
print!("│");
32+
}
33+
}
34+
if index == depth {
35+
print!("───");
36+
} else {
37+
print!(" ");
38+
}
39+
}
40+
}
41+
42+
println!("{:}", directory.name);
43+
44+
for (index, file) in directory.files.iter().enumerate() {
45+
let is_last_file = index == directory.files.iter().count() - 1
46+
&& directory.children.iter().count() == 0;
47+
48+
for (index, tuple) in flag_path.iter().enumerate() {
49+
if index > 0 {
50+
if tuple.0 {
51+
print!(" ");
52+
} else {
53+
print!("│");
54+
}
55+
print!(" ");
56+
}
57+
}
58+
59+
if is_last_file {
60+
print!("└");
61+
} else {
62+
print!("├");
63+
}
64+
print!("───");
65+
println!("{:}", file.name);
66+
}
67+
}
68+
}

src/dat.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
pub mod extract;
2+
pub mod parse;
3+
4+
pub struct File {
5+
pub name: String,
6+
pub size: usize,
7+
pub(crate) range: std::ops::Range<usize>,
8+
}
9+
10+
pub struct Directory {
11+
pub name: String,
12+
pub files: Vec<File>,
13+
pub children: Vec<Directory>,
14+
}

0 commit comments

Comments
 (0)