1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use crate::elf;
use crate::is_bin;
use crate::is_ld;
use crate::is_libc;
use std::path::Path;
use std::path::PathBuf;
use colored::Color;
use colored::Colorize;
use derive_setters::Setters;
use ex::fs;
use ex::io;
use snafu::ResultExt;
use snafu::Snafu;
use structopt::StructOpt;
#[derive(Debug, Snafu)]
pub enum Error {
#[snafu(display("ELF detection error: {}", source))]
ElfDetectError { source: elf::detect::Error },
#[snafu(display("failed reading current directory entry: {}", source))]
DirEntError { source: io::Error },
#[snafu(display("failed reading current directory: {}", source))]
ReadDirError { source: io::Error },
}
pub type Result<T> = std::result::Result<T, Error>;
#[derive(StructOpt, Setters, Clone)]
#[setters(generate = "false")]
#[setters(prefix = "with_")]
pub struct Opts {
#[structopt(long)]
#[setters(generate)]
pub bin: Option<PathBuf>,
#[structopt(long)]
#[setters(generate)]
pub libc: Option<PathBuf>,
#[structopt(long)]
#[setters(generate)]
pub ld: Option<PathBuf>,
#[structopt(long)]
pub template_path: Option<PathBuf>,
#[structopt(long)]
#[structopt(default_value = "exe")]
pub template_bin_name: String,
#[structopt(long)]
#[structopt(default_value = "libc")]
pub template_libc_name: String,
#[structopt(long)]
#[structopt(default_value = "ld")]
pub template_ld_name: String,
}
impl Opts {
pub fn print(&self) {
let f = |opt_path: &Option<PathBuf>, header: &str, color| {
if let Some(path) = opt_path {
println!(
"{}: {}",
header.color(color),
path.to_string_lossy().bold().color(color)
)
}
};
f(&self.bin, "bin", Color::BrightBlue);
f(&self.libc, "libc", Color::Yellow);
f(&self.ld, "ld", Color::Green);
}
pub fn find_if_unspec(self) -> Result<Self> {
let mut dir = fs::read_dir(".").context(ReadDirError)?;
let opts = dir.try_fold(self, Opts::merge_result_entry)?;
Ok(opts)
}
fn merge_result_entry(self, dir_ent: io::Result<fs::DirEntry>) -> Result<Self> {
self.merge_entry(dir_ent.context(DirEntError)?)
.context(ElfDetectError)
}
fn merge_entry(self, dir_ent: fs::DirEntry) -> elf::detect::Result<Self> {
let f = |pred: fn(&Path) -> elf::detect::Result<bool>| {
let path = dir_ent.path();
Ok(if pred(&path)? { Some(path) } else { None })
};
Ok(self
.clone()
.with_bin(self.bin.or(f(is_bin)?))
.with_libc(self.libc.or(f(is_libc)?))
.with_ld(self.ld.or(f(is_ld)?)))
}
}