1use std::ffi::CString;
19pub struct PatchElf {
20 debug: bool,
21 inputs: Vec<String>,
22 output: Option<String>,
23 action: PatchAction,
24 page_size: Option<isize>,
25 allowed_rpath_prefixes: Vec<String>,
26}
27
28pub enum PatchAction {
29 Nop,
30 SetSoname { so_name: String },
31 PrintSoName,
32 SetOsAbi { abi: String },
33 SetInterpreter { interpreter: String },
34 ShrinkRpath,
35 SetRpath { rpath: String },
36 RemoveRpath,
37 AddRpath { rpath: String },
38 ForceRpath,
39 AddNeeded { needed: String },
40 RemoveNeeded { needed: String },
41 ReplaceNeeded { from: String, to: String },
42}
43
44extern "C" {
45 fn patchelf_run() -> bool;
46 fn patchelf_clear();
47 fn patchelf_debug();
48 fn patchelf_set_input(name: *const i8);
49 fn patchelf_set_soname(name: *const i8);
50 fn patchelf_print_soname();
51 fn patchelf_set_output(name: *const i8);
52 fn patchelf_set_page_size(size: isize);
53 fn patchelf_set_osabi(name: *const i8);
54 fn patchelf_set_interpreter(name: *const i8);
55 fn patchelf_shrink_rpath();
56 fn patchelf_set_rpath(name: *const i8);
57 fn patchelf_remove_rpath();
58 fn patchelf_add_rpath(name: *const i8);
59 fn patchelf_force_rpath();
60 fn patchelf_allowed_rpath_prefixes(name: *const i8);
61 fn patchelf_add_needed(name: *const i8);
62 fn patchelf_remove_needed(name: *const i8);
63 fn patchelf_replace_needed(from: *const i8, to: *const i8);
64}
65impl PatchElf {
66 pub fn config() -> Self {
67 Self {
68 debug: false,
69 inputs: vec![],
70 output: None,
71 action: PatchAction::Nop,
72 page_size: None,
73 allowed_rpath_prefixes: vec![],
74 }
75 }
76
77 pub fn debug(mut self) -> Self {
78 self.debug = true;
79 self
80 }
81
82 pub fn page_size(mut self, page_size: isize) -> Self {
83 self.page_size = Some(page_size);
84 self
85 }
86
87 pub fn input(mut self, name: &str) -> Self {
88 self.inputs.push(name.to_string());
89 self
90 }
91
92 pub fn output(mut self, name: &str) -> Self {
93 self.output = Some(name.to_string());
94 self
95 }
96
97 pub fn set_soname(mut self, name: &str) -> Self {
98 self.action = PatchAction::SetSoname {
99 so_name: name.to_string(),
100 };
101 self
102 }
103
104 pub fn print_soname(mut self) -> Self {
105 self.action = PatchAction::PrintSoName;
106 self
107 }
108
109 pub fn set_osabi(mut self, name: &str) -> Self {
110 self.action = PatchAction::SetOsAbi {
111 abi: name.to_string(),
112 };
113 self
114 }
115
116 pub fn set_interpreter(mut self, name: &str) -> Self {
117 self.action = PatchAction::SetInterpreter {
118 interpreter: name.to_string(),
119 };
120 self
121 }
122
123 pub fn shrink_rpath(mut self) -> Self {
124 self.action = PatchAction::ShrinkRpath;
125 self
126 }
127
128 pub fn remove_rpath(mut self) -> Self {
129 self.action = PatchAction::RemoveRpath;
130 self
131 }
132
133 pub fn force_rpath(mut self) -> Self {
134 self.action = PatchAction::ForceRpath;
135 self
136 }
137
138 pub fn set_set_rpath(mut self, name: &str) -> Self {
139 self.action = PatchAction::SetRpath {
140 rpath: name.to_string(),
141 };
142 self
143 }
144
145 pub fn set_add_rpath(mut self, name: &str) -> Self {
146 self.action = PatchAction::AddRpath {
147 rpath: name.to_string(),
148 };
149 self
150 }
151
152 pub fn allowed_rpath_prefixes(mut self, name: &str) -> Self {
153 self.allowed_rpath_prefixes.push(name.to_string());
154 self
155 }
156
157 pub fn set_add_needed(mut self, name: &str) -> Self {
158 self.action = PatchAction::AddNeeded {
159 needed: name.to_string(),
160 };
161 self
162 }
163
164 pub fn set_remove_needed(mut self, name: &str) -> Self {
165 self.action = PatchAction::RemoveNeeded {
166 needed: name.to_string(),
167 };
168 self
169 }
170
171 pub fn set_replace_needed(mut self, from: &str, to: &str) -> Self {
172 self.action = PatchAction::ReplaceNeeded {
173 from: from.to_string(),
174 to: to.to_string()
175 };
176 self
177 }
178
179 pub fn patch(&self) -> bool {
180 unsafe {
181 patchelf_clear();
182 if self.debug {
183 patchelf_debug();
184 }
185 for input in &self.inputs {
186 let c_name = CString::new(input.as_str()).unwrap();
187 patchelf_set_input(c_name.as_ptr());
188 }
189 if let Some(output) = &self.output {
190 let c_name = CString::new(output.as_str()).unwrap();
191 patchelf_set_output(c_name.as_ptr());
192 }
193 if let Some(page_size) = &self.page_size {
194 patchelf_set_page_size(*page_size);
195 }
196 for prefix in &self.allowed_rpath_prefixes {
197 let c_name = CString::new(prefix.as_str()).unwrap();
198 patchelf_allowed_rpath_prefixes(c_name.as_ptr());
199 }
200 match &self.action {
201 PatchAction::PrintSoName => {
202 patchelf_print_soname();
203 }
204 PatchAction::SetSoname { so_name } => {
205 let c_name = CString::new(so_name.as_str()).unwrap();
206 patchelf_set_soname(c_name.as_ptr());
207 }
208 PatchAction::SetOsAbi { abi } => {
209 let c_name = CString::new(abi.as_str()).unwrap();
210 patchelf_set_osabi(c_name.as_ptr());
211 }
212 PatchAction::SetInterpreter { interpreter } => {
213 let c_name = CString::new(interpreter.as_str()).unwrap();
214 patchelf_set_interpreter(c_name.as_ptr());
215 }
216 PatchAction::ShrinkRpath => {
217 patchelf_shrink_rpath();
218 }
219 PatchAction::SetRpath { rpath } => {
220 let c_name = CString::new(rpath.as_str()).unwrap();
221 patchelf_set_rpath(c_name.as_ptr());
222 }
223 PatchAction::RemoveRpath => {
224 patchelf_remove_rpath();
225 }
226 PatchAction::ForceRpath => {
227 patchelf_force_rpath();
228 }
229 PatchAction::AddRpath { rpath } => {
230 let c_name = CString::new(rpath.as_str()).unwrap();
231 patchelf_add_rpath(c_name.as_ptr());
232 }
233 PatchAction::AddNeeded { needed } => {
234 let c_name = CString::new(needed.as_str()).unwrap();
235 patchelf_add_needed(c_name.as_ptr());
236 }
237 PatchAction::RemoveNeeded { needed } => {
238 let c_name = CString::new(needed.as_str()).unwrap();
239 patchelf_remove_needed(c_name.as_ptr());
240 }
241 PatchAction::ReplaceNeeded { from, to } => {
242 let from = CString::new(from.as_str()).unwrap();
243 let to = CString::new(to.as_str()).unwrap();
244 patchelf_replace_needed(from.as_ptr(), to.as_ptr());
245 }
246 _ => {}
247 }
248 return patchelf_run();
249 }
250 }
251}