1#[derive(Debug)]
2pub struct AptProgram {
3 pub name: String,
4 pub repos: Vec<String>,
5 pub version: String,
6 pub core_type: String,
7 pub traits: Vec<String>
8}
9
10#[derive(Debug)]
11pub struct YumProgram {
12 pub name: String,
13 pub core_type: String,
14 pub version: String,
15 pub release: String,
16 pub repository: String,
17 pub from_repo: String,
18 pub size: String,
19 pub source: String,
20 pub summary: String,
21 pub url: String,
22 pub license: String,
23 pub description: String
24}
25
26#[derive(Debug)]
27pub struct PacmanProgram {
28 pub name: String,
29 pub version: String,
30 pub description: String,
31 pub url: String,
32 pub core_type: String,
33 pub licenses: Vec<String>,
34 pub groups: Vec<String>,
35 pub provides: Vec<String>,
36 pub depends_on: Vec<String>,
37 pub optional_dependencies: Vec<String>,
38 pub required_by: Vec<String>,
39 pub optional_for: Vec<String>,
40 pub conflicts_with: Vec<String>,
41 pub replaces: Vec<String>,
42 pub size: i32,
43 pub packager: String,
44 pub build_date: String,
45 pub install_date: String,
46 pub install_reason: String,
47 pub install_script: String,
48 pub validated_by: String
49}
50
51#[derive(Debug, Clone)]
52pub struct ApkProgram {
53 pub name: String,
54 pub long_name: String,
55 pub version: String,
56 pub description: String,
57 pub website: String,
58 pub size: Option<i32>,
59 pub update: String,
60 pub sub_versions: Vec<ApkProgramSubVersion>
61}
62
63#[derive(Debug, Clone)]
64pub struct ApkProgramSubVersion {
65 pub name: String,
66 pub description: String,
67 pub website: String,
68 pub size: i32
69}
70
71
72pub fn find_package_managers<'a>() -> Vec<&'a str> {
73 let mut package_manager = vec![];
74
75 let check_if_apt_exist = std::process::Command::new("apt").output();
76
77 match check_if_apt_exist {
78 Ok(_) => package_manager.push("apt"),
79 Err(_) => ()
80 }
81
82 let check_if_yum_exist = std::process::Command::new("yum").output();
83
84 match check_if_yum_exist {
85 Ok(_) => package_manager.push("yum"),
86 Err(_) => ()
87 }
88
89 let check_if_dnf_exist = std::process::Command::new("dnf").output();
90
91 match check_if_dnf_exist {
92 Ok(_) => package_manager.push("dnf"),
93 Err(_) => ()
94 }
95
96 let check_if_rpm_exist = std::process::Command::new("rpm").output();
97
98 match check_if_rpm_exist {
99 Ok(_) => package_manager.push("rpm"),
100 Err(_) => ()
101 }
102
103 let check_if_pacman_exist = std::process::Command::new("pacman").output();
104
105 match check_if_pacman_exist {
106 Ok(_) => package_manager.push("pacman"),
107 Err(_) => ()
108 }
109
110 let check_if_emerge_exist = std::process::Command::new("emerge").arg("--info").output();
111
112 match check_if_emerge_exist {
113 Ok(_) => package_manager.push("emerge"),
114 Err(_) => ()
115 }
116
117 let check_if_busybox_exist = std::process::Command::new("busybox").output();
118
119 match check_if_busybox_exist {
120 Ok(_) => package_manager.push("busybox"),
121 Err(_) => ()
122 }
123
124 let check_if_apk_exist = std::process::Command::new("apk").output();
125
126 match check_if_apk_exist {
127 Ok(_) => package_manager.push("apk"),
128 Err(_) => ()
129 }
130
131 return package_manager
132}
133
134pub fn get_apt_program(program_name: &str) -> std::result::Result<AptProgram, std::io::Error> { let apt_command = std::process::Command::new("apt")
136 .args(&["list", "--installed"])
137 .stdout(std::process::Stdio::piped())
138 .spawn()
139 .expect("apt command failed to start");
140
141 let grep_command = std::process::Command::new("grep")
142 .arg(program_name)
143 .stdin(apt_command.stdout.expect("Failed to open apt stdout"))
144 .output();
145
146 match grep_command {
147 Ok(program) => {
148 let program_output = std::str::from_utf8(&program.stdout).unwrap();
149
150 println!("our program output: {}", program_output);
151
152 let mut name = String::new();
153 let mut repos: Vec<String> = vec![];
154 let mut version = String::new();
155 let mut core_type = String::new();
156 let mut traits: Vec<String> = vec![];
157
158 for line in program_output.lines() {
159 if !line.starts_with(program_name) {
160 continue;
161 }
162
163 let split_the_line: Vec<&str> = line.split("now").collect();
164
165 let name_and_repo_infos: Vec<&str> = split_the_line[0].split("/").collect();
166
167 name = name_and_repo_infos[0].to_string();
168
169 let repos_string: Vec<&str> = name_and_repo_infos[1].split(",").collect();
170
171 for repo in repos_string {
172 if repo == "" {
173 continue;
174 }
175
176 repos.push(repo.to_string())
177 }
178
179 let other_infos: Vec<&str> = split_the_line[1].trim().split(" ").collect();
180
181 version = other_infos[0].to_string();
182
183 match other_infos[1] {
184 "amd64" => core_type = "64-bit".to_string(),
185 "i386" => core_type = "32-bit".to_string(),
186 "all" => core_type = "all".to_string(),
187 &_ => eprintln!("Core type couldn't spotted")
188 }
189
190 let replace_and_split_last_traits_info = other_infos[2].replace("[", "").replace("]", "");
191 let replace_and_split_last_traits_info: Vec<&str> = replace_and_split_last_traits_info.split(",").collect();
192
193 for individual_trait in replace_and_split_last_traits_info {
194 traits.push(individual_trait.to_string())
195 }
196 }
197
198 return Ok(AptProgram {
199 name, repos: repos.clone(), version, core_type: core_type.clone(), traits: traits.clone()
200 })
201 },
202 Err(error) => {
203 return Err(std::io::Error::new(std::io::ErrorKind::NotFound, error))
204 }
205 }
206}
207
208pub fn list_all_apt_programs() -> std::result::Result<Vec<AptProgram>, std::io::Error> {
209 let mut all_programs: Vec<AptProgram> = vec![];
210 let mut error_string = String::new();
211
212 let get_programs_command = std::process::Command::new("apt")
213 .arg("list")
214 .arg("--installed")
215 .output();
216
217 match get_programs_command {
218 Ok(programs) => {
219 let our_command = std::str::from_utf8(&programs.stdout).unwrap();
220
221 for line in our_command.lines() {
222 if line.starts_with("Listing") {
223 continue;
224 }
225
226 let mut name = String::new();
227 let mut repos: Vec<String> = vec![];
228 let mut version = String::new();
229 let mut core_type = String::new();
230 let mut traits: Vec<String> = vec![];
231
232 let split_the_line: Vec<&str> = line.split("now").collect();
233
234 let name_and_repo_infos: Vec<&str> = split_the_line[0].split("/").collect();
235
236 name = name_and_repo_infos[0].to_string();
237
238 let repos_string: Vec<&str> = name_and_repo_infos[1].split(",").collect();
239
240 for repo in repos_string {
241 if repo == "" {
242 continue;
243 }
244
245 repos.push(repo.to_string())
246 }
247
248 let other_infos: Vec<&str> = split_the_line[1].trim().split(" ").collect();
249
250 version = other_infos[0].to_string();
251
252 match other_infos[1] {
253 "amd64" => core_type = "64-bit".to_string(),
254 "i386" => core_type = "32-bit".to_string(),
255 "all" => core_type = "all".to_string(),
256 &_ => eprintln!("Core type couldn't spotted")
257 }
258
259 let replace_and_split_last_traits_info = other_infos[2].replace("[", "").replace("]", "");
260 let replace_and_split_last_traits_info: Vec<&str> = replace_and_split_last_traits_info.split(",").collect();
261
262 for individual_trait in replace_and_split_last_traits_info {
263 traits.push(individual_trait.to_string())
264 }
265
266 let new_apt_program = AptProgram {
267 name, repos: repos.clone(), version, core_type: core_type.clone(), traits: traits.clone()
268 };
269
270 all_programs.push(new_apt_program)
271 }
272 },
273 Err(error) => {
274 error_string = format!("{}", error);
275 }
276 }
277
278 return match error_string.as_str() {
279 "" => Ok(all_programs),
280 &_ => Err(std::io::Error::new(std::io::ErrorKind::NotFound, error_string))
281 }
282}
283
284pub fn check_if_exist_in_apt(program_name: &str) -> bool {
285 let mut result = false;
286
287 let get_programs_command = std::process::Command::new("apt")
288 .arg("list")
289 .arg("--installed")
290 .output();
291
292 match get_programs_command {
293 Ok(programs) => {
294 let our_command = std::str::from_utf8(&programs.stdout).unwrap();
295
296 for line in our_command.lines() {
297 let split_the_line: Vec<&str> = line.split("/").collect();
298
299 if program_name == split_the_line[0] {
300 result = true;
301 break;
302 }
303 }
304 },
305 Err(error) => {
306 eprintln!("that error occured: {}", error)
307 }
308 }
309
310 return result
311}
312
313pub struct AptSourceRepo {
314 pub url: String,
315 pub options: Option<Vec<String>>,
316 pub distro: String,
317 pub parts: Vec<String>,
318 pub comments: Vec<String>
319}
320
321pub fn add_source_repo_to_apt(opts: AptSourceRepo) -> std::result::Result<(), std::io::Error> {
322 let create_repo_record_string = match opts.options {
323 Some(options) => {
324 match options.len() {
325 0 => {
326 let mut parts_str = "".to_string();
327
328 for part in &opts.parts {
329 parts_str = format!("{} {}", parts_str, part)
330 }
331
332 format!("deb {} {} {}", opts.url, opts.distro, parts_str)
333 },
334 _ => {
335 let mut options_str = "[".to_string();
336
337 let length_of_options = &options.len();
338
339 for (index, opt) in options.into_iter().enumerate() {
340 if index + 1 == *length_of_options {
341 options_str = format!("{}]", options_str)
342 } else {
343 options_str = format!("{}, {}", options_str, opt);
344 }
345 }
346
347 let mut parts_str = "".to_string();
348
349 for part in &opts.parts {
350 parts_str = format!("{} {}", parts_str, part)
351 }
352
353 format!("deb {} {} {} {}", options_str, opts.url, opts.distro, parts_str)
354 }
355 }
356 },
357 None => {
358 let mut parts_str = "".to_string();
359
360 for part in &opts.parts {
361 parts_str = format!("{} {}", parts_str, part)
362 }
363
364 format!("deb {} {} {}", opts.url, opts.distro, parts_str)
365 }
366 };
367
368 use std::fs::OpenOptions;
369 use std::io::{Read, Write};
370
371 match OpenOptions::new().read(true).append(true).open("/etc/apt/sources.list") {
372 Ok(mut sources_file) => {
373 let buffer = &mut String::new();
374
375 match sources_file.read_to_string(buffer) {
376 Ok(_) => {
377 match buffer.contains(&create_repo_record_string) {
378 true => Err(std::io::Error::new(std::io::ErrorKind::AlreadyExists, "That source repo already exist with exact same configurations")),
379 false => {
380 match buffer.contains(&opts.url) {
381 true => Err(std::io::Error::new(std::io::ErrorKind::AlreadyExists, "That source repo already exist but with different configurations")),
382 false => {
383
384 for comment in &opts.comments {
385 let comment_string = format!("\n{}", comment);
386
387 if let Err(error) = sources_file.write(comment_string.as_bytes()) {
388 println!("error occured when we try to write comments on sources.list!");
389
390 return Err(std::io::Error::new(error.kind(), error));
391 }
392 }
393
394 match sources_file.write(format!("\n{}", create_repo_record_string).as_bytes()) {
395 Ok(_) => Ok(()),
396 Err(error) => Err(std::io::Error::new(error.kind(), error))
397 }
398 }
399 }
400 }
401 }
402 },
403 Err(error) => {
404 println!("Error when we try to read the sources.list file!");
405
406 Err(std::io::Error::new(error.kind(), error))
407 }
408 }
409 },
410 Err(error) => {
411 println!("error occured when we try to open sources.list file!");
412
413 Err(std::io::Error::new(error.kind(), error))
414 }
415 }
416}
417
418pub fn get_yum_program(program: &str) -> std::result::Result<YumProgram, std::io::Error> {
419 let check_if_yum_exist = std::process::Command::new("yum").output();
420
421 let get_yum_lists;
422
423 match check_if_yum_exist {
424 Ok(_) => get_yum_lists = std::process::Command::new("yum").arg("info").arg(program).output(),
425 Err(_) => get_yum_lists = std::process::Command::new("dnf").arg("info").arg(program).output()
426 }
427
428 match get_yum_lists {
429 Ok(answer) => {
430 let parse_answer = std::str::from_utf8(&answer.stdout).unwrap();
431 let mut name = String::new();
432 let mut core_type = String::new();
433 let mut version = String::new();
434 let mut release = String::new();
435 let mut repository = String::new();
436 let mut from_repo = String::new();
437 let mut size = String::new();
438 let mut source = String::new();
439 let mut summary = String::new();
440 let mut url = String::new();
441 let mut license = String::new();
442 let mut description = String::new();
443
444 for (_, line) in parse_answer.lines().into_iter().enumerate() {
445 let split_the_output: Vec<&str> = line.split(" :").collect::<Vec<&str>>();
446
447 if line.starts_with("Name") {
448 name = split_the_output[1].trim().to_string();
449 }
450
451 if line.starts_with("Architecture") {
452 core_type = split_the_output[1].trim().to_string();
453 }
454
455 if line.starts_with("Version") {
456 version = split_the_output[1].trim().to_string();
457 }
458
459 if line.starts_with("Release") {
460 release = split_the_output[1].trim().to_string();
461 }
462
463 if line.starts_with("Size") {
464 size = split_the_output[1].trim().to_string();
465 }
466
467 if line.starts_with("Source") {
468 source = split_the_output[1].trim().to_string();
469 }
470
471 if line.starts_with("Repository") {
472 repository = split_the_output[1].trim().to_string();
473 }
474
475 if line.starts_with("From repo") {
476 from_repo = split_the_output[1].trim().to_string();
477 }
478
479 if line.starts_with("Summary") {
480 summary = split_the_output[1].trim().to_string();
481 }
482
483 if line.starts_with("URL") {
484 url = split_the_output[1].trim().to_string();
485 }
486
487 if line.starts_with("License") {
488 license = split_the_output[1].trim().to_string();
489 }
490
491 if line.starts_with("Description") {
492 description = split_the_output[1].trim().to_string();
493 }
494
495 if line.starts_with(" ") {
496 description.push_str(split_the_output[1].trim());
497 description.push_str(" ");
498 }
499 }
500
501 Ok(YumProgram{
502 name, core_type, version, release, description, summary, license, repository, from_repo, url, source, size
503 })
504 },
505 Err(error) => {
506 eprintln!("that error occured: {}", error);
507
508 Err(std::io::Error::new(std::io::ErrorKind::NotFound, error))
509 }
510 }
511}
512
513
514pub fn list_all_yum_programs() -> std::result::Result<Vec<YumProgram>, std::io::Error> {
515 let check_if_yum_exist = std::process::Command::new("yum").output();
516
517 let get_yum_lists;
518
519 match check_if_yum_exist {
520 Ok(_) => get_yum_lists = std::process::Command::new("yum").arg("info").arg("installed").output(),
521 Err(_) => get_yum_lists = std::process::Command::new("dnf").arg("info").arg("installed").output()
522 }
523
524 match get_yum_lists {
525 Ok(answer) => {
526 let parse_answer = std::str::from_utf8(&answer.stdout).unwrap();
527 let split_the_parsed_answer: Vec<&str> = parse_answer.split("Name").collect::<Vec<&str>>();
528
529 let mut programs = vec![];
530
531 let mut i = 0;
532 for program in split_the_parsed_answer.into_iter() {
533 if i == 0 {
534 i = i + 1;
535 continue;
536 }
537
538 let mut name = String::new();
539 let mut core_type = String::new();
540 let mut version = String::new();
541 let mut release = String::new();
542 let mut repository = String::new();
543 let mut from_repo = String::new();
544 let mut size = String::new();
545 let mut source = String::new();
546 let mut summary = String::new();
547 let mut url = String::new();
548 let mut license = String::new();
549 let mut description = String::new();
550
551 for (info_index, line) in program.lines().into_iter().enumerate() {
552 let split_the_output: Vec<&str> = line.split(":").collect::<Vec<&str>>();
553
554 if info_index == 0 {
555 name = split_the_output.join("").trim().to_string();
556 }
557
558 if line.starts_with("Architecture") {
559 core_type = split_the_output[1].trim().to_string();
560 }
561
562 if line.starts_with("Version") {
563 version = split_the_output[1].trim().to_string();
564 }
565
566 if line.starts_with("Release") {
567 release = split_the_output[1].trim().to_string();
568 }
569
570 if line.starts_with("Size") {
571 size = split_the_output[1].trim().to_string();
572 }
573
574 if line.starts_with("Source") {
575 source = split_the_output[1].trim().to_string();
576 }
577
578 if line.starts_with("Repository") {
579 repository = split_the_output[1].trim().to_string();
580 }
581
582 if line.starts_with("From repo") {
583 from_repo = split_the_output[1].trim().to_string();
584 }
585
586 if line.starts_with("Summary") {
587 summary = split_the_output[1].trim().to_string();
588 }
589
590 if line.starts_with("URL") {
591 let split_the_output: Vec<&str> = line.split(" :").collect::<Vec<&str>>();
592
593 url = split_the_output[1].trim().to_string();
594 }
595
596 if line.starts_with("License") {
597 license = split_the_output[1].trim().to_string();
598 }
599
600 if line.starts_with("Description") {
601 description = split_the_output[1].trim().to_string();
602 description.push_str(" ");
603 }
604
605 if line.starts_with(" ") && info_index != 0 {
606 description.push_str(split_the_output[1].trim());
607 description.push_str(" ");
608 }
609 }
610
611 let yum_program = YumProgram{
612 name, core_type, version, release, description, summary, license, repository,
613 from_repo, url, source, size
614 };
615
616 programs.push(yum_program);
617 }
618
619 Ok(programs)
620 },
621 Err(error) => {
622 eprintln!("That Error Occured: {}", error);
623
624 Err(std::io::Error::new(std::io::ErrorKind::NotFound, error))
625 }
626 }
627}
628
629pub fn check_if_exist_in_dpkg(program_name: &str) -> bool {
630 let mut result = false;
631
632 let get_programs_command = std::process::Command::new("dpkg")
633 .arg("-l")
634 .output();
635
636 match get_programs_command {
637 Ok(programs) => {
638 let our_command = std::str::from_utf8(&programs.stdout).unwrap();
639
640 for line in our_command.lines() {
641 let split_the_line: Vec<&str> = line.split(" ").collect();
642
643 let split_the_line: Vec<&str> = split_the_line.into_iter().filter(|l| *l != "").collect();
644
645 if split_the_line.len() >= 2 {
646 if program_name == split_the_line[1] {
647 result = true;
648 break;
649 }
650 }
651 }
652 },
653 Err(error) => {
654 eprintln!("that error occured: {}", error)
655 }
656 }
657
658 return result
659}
660
661pub fn check_if_exist_in_dnf(program_name: &str) -> bool {
662 let mut result = false;
663
664 let get_programs_command = std::process::Command::new("dnf")
665 .arg("list")
666 .arg("installed")
667 .output();
668
669 match get_programs_command {
670 Ok(programs) => {
671 let our_command = std::str::from_utf8(&programs.stdout).unwrap();
672
673 for line in our_command.lines() {
674 if line.starts_with(program_name) {
675 result = true;
676 break;
677 }
678 }
679 },
680 Err(error) => {
681 eprintln!("that error occured: {}", error)
682 }
683 }
684
685 return result
686}
687
688pub fn check_if_exist_in_yum(program_name: &str) -> bool {
689 let mut result = false;
690
691 let get_programs_command = std::process::Command::new("yum")
692 .arg("list")
693 .arg("installed")
694 .output();
695
696 match get_programs_command {
697 Ok(programs) => {
698 let our_command = std::str::from_utf8(&programs.stdout).unwrap();
699
700 for line in our_command.lines() {
701 if line.starts_with(program_name) {
702 result = true;
703 break;
704 }
705 }
706 },
707 Err(error) => {
708 eprintln!("that error occured: {}", error)
709 }
710 }
711
712 return result
713}
714
715pub fn check_if_exist_in_rpm(program_name: &str) -> bool {
716 let mut result = false;
717
718 let get_programs_command = std::process::Command::new("rpm")
719 .arg("-qa")
720 .output();
721
722 match get_programs_command {
723 Ok(programs) => {
724 let our_command = std::str::from_utf8(&programs.stdout).unwrap();
725
726 for line in our_command.lines() {
727 if line == program_name {
728 result = true;
729 break;
730 }
731 }
732 },
733 Err(error) => {
734 eprintln!("that error occured: {}", error)
735 }
736 }
737
738 return result
739}
740
741pub fn get_pacman_program(program_name: &str) -> std::result::Result<PacmanProgram, std::io::Error> {
742 let get_pacman_program = std::process::Command::new("pacman").arg("-Qi").arg(program_name).output();
743
744 match get_pacman_program {
745 Ok(answer) => {
746 let parse_the_answer = std::str::from_utf8(&answer.stdout).unwrap();
747
748 let mut name: String = "".to_string();
749 let mut version: String = "".to_string();
750 let mut description: String = "".to_string();
751 let mut core_type: String = "".to_string();
752 let mut url: String = "".to_string();
753 let mut licenses: Vec<String> = vec![];
754 let mut groups: Vec<String> = vec![];
755 let mut provides: Vec<String> = vec![];
756 let mut depends_on: Vec<String> = vec![];
757 let mut optional_dependencies: Vec<String> = vec![];
758 let mut required_by: Vec<String> = vec![];
759 let mut optional_for: Vec<String> = vec![];
760 let mut conflicts_with: Vec<String> = vec![];
761 let mut replaces: Vec<String> = vec![];
762 let mut size: i32 = 0;
763 let mut packager: String = "".to_string();
764 let mut build_date: String = "".to_string();
765 let mut install_date: String = "".to_string();
766 let mut install_reason: String = "".to_string();
767 let mut install_script: String = "".to_string();
768 let mut validated_by: String = "".to_string();
769
770 for line in parse_the_answer.lines() {
771 let split_the_line: Vec<&str> = line.split(" :").collect();
772
773 if line.starts_with("Name") {
774 name = split_the_line[1].trim().to_string();
775 }
776
777 if line.starts_with("Version") {
778 version = split_the_line[1].trim().to_string();
779 }
780
781 if line.starts_with("Description") {
782 description = split_the_line[1].trim().to_string();
783 }
784
785 if line.starts_with("Architecture") {
786 let splitted_part = split_the_line[1].trim().to_string();
787
788 if splitted_part == "x86_64" {
789 core_type = "64 bit".to_string();
790 }
791
792 if splitted_part == "i686" || splitted_part == "x86" {
793 core_type = "32 bit".to_string();
794 }
795
796 if splitted_part == "any" {
797 core_type = "all".to_string();
798 }
799 }
800
801
802 if line.starts_with("URL") {
803 url = split_the_line[1].trim().to_string();
804 }
805
806 if line.starts_with("Licenses") {
807 let split_the_licenses_line: Vec<&str> = split_the_line[1].trim().split(" ").collect::<Vec<&str>>();
808 for license in split_the_licenses_line {
809 licenses.push(license.to_string());
810 }
811 }
812
813 if line.starts_with("Groups") {
814 let split_the_groups_line = split_the_line[1].trim();
815
816 if split_the_groups_line == "None" {
817 continue;
818 } else {
819 let split_the_splitted_groups_line: Vec<&str> = split_the_groups_line.split(" ").collect::<Vec<&str>>();
820
821 for group in split_the_splitted_groups_line {
822 groups.push(group.to_string());
823 }
824 }
825 }
826
827 if line.starts_with("Provides") {
828 let split_the_provides_line = split_the_line[1].trim();
829
830 if split_the_provides_line == "None" {
831 continue;
832 } else {
833 let split_the_splitted_provides_line: Vec<&str> = split_the_provides_line.split(" ").collect::<Vec<&str>>();
834
835 for provide in split_the_splitted_provides_line {
836 provides.push(provide.to_string());
837 }
838 }
839 }
840
841 if line.starts_with("Depends On") {
842 let split_the_depends_on_line: Vec<&str> = split_the_line[1].trim().split(" ").collect::<Vec<&str>>();
843
844 if split_the_depends_on_line[0] == "None" {
845 continue;
846 }
847
848 for dependence in split_the_depends_on_line {
849 depends_on.push(dependence.to_string());
850 }
851 }
852
853 if line.starts_with("Optional Deps") {
854 let split_the_optional_deps_line: Vec<&str> = split_the_line[1].trim().split("\n").collect::<Vec<&str>>();
855 if split_the_optional_deps_line[0].contains("None") {
856 continue;
857 }
858
859 optional_dependencies.push(split_the_optional_deps_line[0].to_string());
860
861 for (index, parsed_lines) in parse_the_answer.lines().into_iter().enumerate() {
862 if index > 9 && parsed_lines.starts_with(" ") {
863 optional_dependencies.push(parsed_lines.trim().to_string());
864 }
865 }
866 }
867
868 if line.starts_with("Required By") {
869 let split_the_required_by_line: Vec<&str> = split_the_line[1].trim().split(" ").collect::<Vec<&str>>();
870
871 if split_the_required_by_line[0] == "None" {
872 continue;
873 }
874
875 for requireds in split_the_required_by_line {
876 required_by.push(requireds.to_string());
877 }
878 }
879
880 if line.starts_with("Optional For") {
881 let split_the_optional_for_line: Vec<&str> = split_the_line[1].trim().split(" ").collect::<Vec<&str>>();
882
883 if split_the_optional_for_line[0] == "None" {
884 continue;
885 }
886
887 for optionals in split_the_optional_for_line {
888 optional_for.push(optionals.to_string());
889 }
890
891 }
892
893
894 if line.starts_with("Conflicts With") {
895 let split_the_conflicts_with_line: Vec<&str> = split_the_line[1].trim().split(" ").collect::<Vec<&str>>();
896
897 if split_the_conflicts_with_line[0] == "None" {
898 continue;
899 }
900
901 for conflicters in split_the_conflicts_with_line {
902 conflicts_with.push(conflicters.to_string());
903 }
904 }
905
906 if line.starts_with("Replaces") {
907 let split_the_replaces_line: Vec<&str> = split_the_line[1].trim().split(" ").collect::<Vec<&str>>();
908
909 if split_the_replaces_line[0] == "None" {
910 continue;
911 }
912
913 for replaceds in split_the_replaces_line {
914 replaces.push(replaceds.to_string());
915 }
916 }
917
918 if line.starts_with("Installed Size") {
919 let split_the_installed_size_line: Vec<&str> = split_the_line[1].trim().split(" ").collect::<Vec<&str>>();
920
921 if line.contains("KiB") {
922 let split_further_the_size: Vec<&str> = split_the_installed_size_line[0].trim().split(" ").collect::<Vec<&str>>();
923
924 let add_one_zero_to_end = format!("{}0", split_further_the_size[0]);
925
926 let replace_the_string = add_one_zero_to_end.replace(".", "");
927
928 size = replace_the_string.parse::<i32>().unwrap();
929 }
930
931
932 if line.contains("MiB") {
933 let split_further_the_size: Vec<&str> = split_the_installed_size_line[0].trim().split(" ").collect::<Vec<&str>>();
934
935 let add_one_zero_to_end = format!("{}0000", split_further_the_size[0]);
936
937 let replace_the_string = add_one_zero_to_end.replace(".", "");
938
939 size = replace_the_string.parse::<i32>().unwrap();
940 }
941
942 }
943
944 if line.starts_with("Packager") {
945 let split_the_packager_line = split_the_line[1].trim();
946
947 packager = split_the_packager_line.to_string();
948 }
949
950
951 if line.starts_with("Build Date") {
952 let split_the_build_date_line = split_the_line[1].trim();
953
954 build_date = split_the_build_date_line.to_string();
955 }
956
957 if line.starts_with("Install Date") {
958 let split_the_install_date_line = split_the_line[1].trim();
959
960 install_date = split_the_install_date_line.to_string();
961 }
962
963 if line.starts_with("Install Reason") {
964 let split_the_install_reason_line = split_the_line[1].trim();
965
966 install_reason = split_the_install_reason_line.to_string();
967 }
968
969 if line.starts_with("Install Script") {
970 let split_the_install_script_line = split_the_line[1].trim();
971
972 install_script = split_the_install_script_line.to_string();
973 }
974
975 if line.starts_with("Validated By") {
976 let split_the_validated_by_line = split_the_line[1].trim();
977
978 validated_by = split_the_validated_by_line.to_string();
979 }
980 }
981
982 let pacman_program = PacmanProgram {
983 name, version, description, url, core_type, licenses, groups, provides, depends_on, optional_dependencies, optional_for, required_by, conflicts_with, replaces, size: size, packager, build_date, install_date, install_reason, install_script, validated_by
984 };
985
986 return Ok(pacman_program);
987 },
988 Err(error) => Err(std::io::Error::new(std::io::ErrorKind::NotFound, error))
989 }
990}
991
992pub fn list_all_pacman_programs() -> std::result::Result<Vec<PacmanProgram>, std::io::Error> {
993 let get_pacman_programs = std::process::Command::new("pacman").arg("-Qi").output();
994 let mut error_string = String::new();
995 let mut programs = vec![];
996
997 match get_pacman_programs {
998 Ok(answer) => {
999 let parse_the_answer = std::str::from_utf8(&answer.stdout).unwrap();
1000 let split_the_parsed_answer: Vec<&str> = parse_the_answer.split("Name ").collect::<Vec<&str>>();
1001
1002 for program in split_the_parsed_answer.clone().into_iter() {
1003 let mut name: String = "".to_string();
1004 let mut version: String = "".to_string();
1005 let mut description: String = "".to_string();
1006 let mut core_type: String = "".to_string();
1007 let mut url: String = "".to_string();
1008 let mut licenses: Vec<String> = vec![];
1009 let mut groups: Vec<String> = vec![];
1010 let mut provides: Vec<String> = vec![];
1011 let mut depends_on: Vec<String> = vec![];
1012 let mut optional_dependencies: Vec<String> = vec![];
1013 let mut required_by: Vec<String> = vec![];
1014 let mut optional_for: Vec<String> = vec![];
1015 let mut conflicts_with: Vec<String> = vec![];
1016 let mut replaces: Vec<String> = vec![];
1017 let mut size: i32 = 0;
1018 let mut packager: String = "".to_string();
1019 let mut build_date: String = "".to_string();
1020 let mut install_date: String = "".to_string();
1021 let mut install_reason: String = "".to_string();
1022 let mut install_script: String = "".to_string();
1023 let mut validated_by: String = "".to_string();
1024
1025 for (_, line) in program.lines().into_iter().enumerate() {
1026 if line.starts_with(" ") {
1027 continue;
1028 }
1029
1030 let split_the_line: Vec<&str> = line.split(" :").collect();
1031
1032 if line.starts_with(": ") {
1033 name = split_the_line[0].trim().to_string().replace(": ", "");
1034 }
1035
1036 if line.starts_with("Version") {
1037 version = split_the_line[1].trim().to_string();
1038 }
1039
1040 if line.starts_with("Description") {
1041 description = split_the_line[1].trim().to_string();
1042 }
1043
1044 if line.starts_with("Architecture") {
1045 let splitted_part = split_the_line[1].trim().to_string();
1046
1047 if splitted_part == "x86_64" {
1048 core_type = "64 bit".to_string();
1049 }
1050
1051 if splitted_part == "i686" || splitted_part == "x86" {
1052 core_type = "32 bit".to_string();
1053 }
1054
1055 if splitted_part == "any" {
1056 core_type = "all".to_string();
1057 }
1058 }
1059
1060 if line.starts_with("URL") {
1061 url = split_the_line[1].trim().to_string();
1062 }
1063
1064 if line.starts_with("Licenses") {
1065 let split_the_licenses_line: Vec<&str> = split_the_line[1].trim().split(" ").collect::<Vec<&str>>();
1066
1067 for license in split_the_licenses_line {
1068 licenses.push(license.to_string());
1069 }
1070 }
1071
1072 if line.starts_with("Groups") {
1073 let split_the_groups_line = split_the_line[1].trim();
1074
1075 if split_the_groups_line == "None" {
1076 continue;
1077 } else {
1078 let split_the_splitted_groups_line: Vec<&str> = split_the_groups_line.split(" ").collect::<Vec<&str>>();
1079
1080 for group in split_the_splitted_groups_line {
1081 groups.push(group.to_string());
1082 }
1083 }
1084 }
1085
1086 if line.starts_with("Provides") {
1087 let split_the_provides_line = split_the_line[1].trim();
1088
1089 if split_the_provides_line == "None" {
1090 continue;
1091 } else {
1092 let split_the_splitted_provides_line: Vec<&str> = split_the_provides_line.split(" ").collect::<Vec<&str>>();
1093
1094 for provide in split_the_splitted_provides_line {
1095 provides.push(provide.to_string());
1096 }
1097 }
1098 }
1099
1100 if line.starts_with("Depends On") {
1101 let split_the_depends_on_line: Vec<&str> = split_the_line[1].trim().split(" ").collect::<Vec<&str>>();
1102
1103 if split_the_depends_on_line[0] == "None" {
1104 continue;
1105 }
1106
1107 for dependence in split_the_depends_on_line {
1108 depends_on.push(dependence.to_string());
1109 }
1110 }
1111
1112 if line.starts_with("Optional Deps") {
1113 let split_the_optional_deps_line: Vec<&str> = split_the_line[1].trim().split("\n").collect::<Vec<&str>>();
1114
1115 let stopl1 = split_the_optional_deps_line[0].trim();
1116
1117 if stopl1 == "None" {
1118 continue;
1119 }
1120
1121 let format_the_starting_name = format!(": {}\n", name);
1122
1123 for parsed_entity in &split_the_parsed_answer {
1124 if parsed_entity.starts_with(&format_the_starting_name) {
1125
1126 let split_the_parsed_entity = parsed_entity.split("Required By : ").collect::<Vec<&str>>()[0];
1127
1128 optional_dependencies.push(stopl1.to_string());
1129
1130 for opt_dep_lines in split_the_parsed_entity.lines() {
1131 if !opt_dep_lines.starts_with(" ") {
1132 continue;
1133 }
1134
1135 optional_dependencies.push(opt_dep_lines.trim().to_string());
1136 }
1137 }
1138 }
1139 }
1140
1141 if line.starts_with("Required By") {
1142 let split_the_required_by_line: Vec<&str> = split_the_line[1].trim().split(" ").collect::<Vec<&str>>();
1143
1144 if split_the_required_by_line[0] == "None" {
1145 continue;
1146 }
1147
1148 for requireds in split_the_required_by_line {
1149 required_by.push(requireds.to_string());
1150 }
1151 }
1152
1153 if line.starts_with("Optional For") {
1154 let split_the_optional_for_line: Vec<&str> = split_the_line[1].trim().split(" ").collect::<Vec<&str>>();
1155
1156 if split_the_optional_for_line[0] == "None" {
1157 continue;
1158 }
1159
1160 for optionals in split_the_optional_for_line {
1161 optional_for.push(optionals.to_string());
1162 }
1163 }
1164
1165 if line.starts_with("Conflicts With") {
1166 let split_the_conflicts_with_line: Vec<&str> = split_the_line[1].trim().split(" ").collect::<Vec<&str>>();
1167
1168 if split_the_conflicts_with_line[0] == "None" {
1169 continue;
1170 }
1171
1172 for conflicters in split_the_conflicts_with_line {
1173 conflicts_with.push(conflicters.to_string());
1174 }
1175 }
1176
1177 if line.starts_with("Replaces") {
1178 let split_the_replaces_line: Vec<&str> = split_the_line[1].trim().split(" ").collect::<Vec<&str>>();
1179
1180 if split_the_replaces_line[0] == "None" {
1181 continue;
1182 }
1183
1184 for replaceds in split_the_replaces_line {
1185 replaces.push(replaceds.to_string());
1186 }
1187 }
1188
1189 if line.starts_with("Installed Size") {
1190 let split_the_installed_size_line: Vec<&str> = split_the_line[1].trim().split(" ").collect::<Vec<&str>>();
1191
1192 if line.contains("KiB") {
1193 let split_further_the_size: Vec<&str> = split_the_installed_size_line[0].trim().split(" ").collect::<Vec<&str>>();
1194
1195 let add_one_zero_to_end = format!("{}0", split_further_the_size[0]);
1196
1197 let replace_the_string = add_one_zero_to_end.replace(".", "");
1198
1199 size = replace_the_string.parse::<i32>().unwrap();
1200 }
1201
1202 if line.contains("MiB") {
1203 let split_further_the_size: Vec<&str> = split_the_installed_size_line[0].trim().split(" ").collect::<Vec<&str>>();
1204
1205 let add_one_zero_to_end = format!("{}0000", split_further_the_size[0]);
1206
1207 let replace_the_string = add_one_zero_to_end.replace(".", "");
1208
1209 size = replace_the_string.parse::<i32>().unwrap();
1210 }
1211 }
1212
1213 if line.starts_with("Packager") {
1214 let split_the_packager_line = split_the_line[1].trim();
1215
1216 packager = split_the_packager_line.to_string();
1217 }
1218
1219
1220 if line.starts_with("Build Date") {
1221 let split_the_build_date_line = split_the_line[1].trim();
1222
1223 build_date = split_the_build_date_line.to_string();
1224 }
1225
1226 if line.starts_with("Install Date") {
1227 let split_the_install_date_line = split_the_line[1].trim();
1228
1229 install_date = split_the_install_date_line.to_string();
1230 }
1231
1232 if line.starts_with("Install Reason") {
1233 let split_the_install_reason_line = split_the_line[1].trim();
1234
1235 install_reason = split_the_install_reason_line.to_string();
1236 }
1237
1238 if line.starts_with("Install Script") {
1239 let split_the_install_script_line = split_the_line[1].trim();
1240
1241 install_script = split_the_install_script_line.to_string();
1242 }
1243
1244 if line.starts_with("Validated By") {
1245 let split_the_validated_by_line = split_the_line[1].trim();
1246
1247 validated_by = split_the_validated_by_line.to_string();
1248 }
1249 }
1250
1251 let pacman_program = PacmanProgram {
1252 name, version, description, url, core_type, licenses, groups, provides, depends_on, optional_dependencies, optional_for, required_by, conflicts_with, replaces, size: size, packager, build_date, install_date, install_reason, install_script, validated_by
1253 };
1254
1255 programs.push(pacman_program);
1256 }
1257 },
1258 Err(error) => {
1259 eprintln!("this error occured: {}", error);
1260
1261 error_string = error.to_string();
1262 }
1263 }
1264
1265 return match error_string.as_str() {
1266 "" => Ok(programs),
1267 &_ => Err(std::io::Error::new(std::io::ErrorKind::NotFound, error_string))
1268 };
1269}
1270
1271
1272
1273pub fn check_if_exist_in_pacman(program_name: &str) -> bool {
1274 let mut result = false;
1275
1276 let get_programs_command = std::process::Command::new("pacman")
1277 .arg("-Q")
1278 .output();
1279
1280 match get_programs_command {
1281 Ok(programs) => {
1282 let our_command = std::str::from_utf8(&programs.stdout).unwrap();
1283
1284 for line in our_command.lines() {
1285 if line.starts_with(program_name) {
1286 result = true;
1287 break;
1288 }
1289 }
1290 },
1291 Err(error) => {
1292 eprintln!("that error occured: {}", error)
1293 }
1294 }
1295
1296 return result
1297}
1298
1299pub fn check_if_exist_in_busybox(program_name: &str) -> bool {
1300 let mut result = false;
1301
1302 let get_programs_command = std::process::Command::new("busybox")
1303 .arg("--list")
1304 .output();
1305
1306 match get_programs_command {
1307 Ok(programs) => {
1308 let our_command = std::str::from_utf8(&programs.stdout).unwrap();
1309
1310 for line in our_command.lines() {
1311 if program_name == line {
1312 result = true;
1313 break;
1314 }
1315 }
1316 },
1317 Err(error) => {
1318 eprintln!("that error occured: {}", error)
1319 }
1320 }
1321
1322 return result
1323}
1324
1325pub fn check_if_exist_in_apk(program_name: &str) -> bool {
1326 let mut result = false;
1327
1328 let get_programs_command = std::process::Command::new("apk")
1329 .arg("info")
1330 .arg("-vv")
1331 .output();
1332
1333 match get_programs_command {
1334 Ok(programs) => {
1335 let our_command = std::str::from_utf8(&programs.stdout).unwrap();
1336
1337 for line in our_command.lines() {
1338 if line.starts_with(program_name) {
1339 result = true;
1340 break;
1341 }
1342 }
1343 },
1344 Err(error) => {
1345 eprintln!("that error occured: {}", error)
1346 }
1347 }
1348
1349 return result
1350}
1351
1352pub fn get_apk_program(program_name: &str) -> std::result::Result<ApkProgram, std::io::Error> {
1353 let get_program_command = std::process::Command::new("apk")
1354 .arg("info")
1355 .arg("-vv")
1356 .arg(program_name)
1357 .output();
1358
1359 match get_program_command {
1360 Ok(output) => {
1361 let our_output = std::str::from_utf8(&output.stdout).unwrap();
1362 let mut long_name = "".to_string();
1363 let mut version = "".to_string();
1364 let mut description = "".to_string();
1365 let mut website = "".to_string();
1366 let mut size = "".to_string();
1367 let mut update_info = "".to_string();
1368
1369 let mut get_individual_programs = our_output
1370 .lines()
1371 .into_iter()
1372 .map(|line| line.split(": ").collect::<Vec<&str>>()[0])
1373 .collect::<Vec<&str>>();
1374
1375 let mut prev_item: &str = "";
1376 get_individual_programs.retain(|current_item| {
1377 if prev_item == "" {
1378 prev_item = *current_item;
1379 return true
1380 } else {
1381 if prev_item != *current_item {
1382 prev_item = *current_item;
1383 return true
1384 } else {
1385 return false;
1386 }
1387 }
1388 });
1389
1390 let mut subversions: Vec<ApkProgramSubVersion> = vec![];
1391
1392 for pr in get_individual_programs.into_iter() {
1393 let mut sub_program_name = "".to_string();
1394 let mut sub_program_description = "".to_string();
1395 let mut sub_program_website = "".to_string();
1396 let mut sub_program_size = "".to_string();
1397
1398 for line in our_output.lines().into_iter() {
1399 let split_the_line = line.split(": ").collect::<Vec<&str>>();
1400 let first_part_of_line = split_the_line[0].trim();
1401 let second_part_of_line = split_the_line[1].trim();
1402
1403 if first_part_of_line == program_name {
1404 if second_part_of_line.starts_with("http") {
1405 website = second_part_of_line.to_string();
1406 } else if second_part_of_line.contains("MiB") {
1407 size = format!("{}000000", second_part_of_line.split(" ").collect::<Vec<&str>>()[0]);
1408 } else if second_part_of_line.contains("KiB") {
1409 size = format!("{}000", second_part_of_line.split(" ").collect::<Vec<&str>>()[0]);
1410 }
1411 } else {
1412 sub_program_name = pr.to_string();
1413
1414 if second_part_of_line.starts_with("http") {
1415 sub_program_website = second_part_of_line.to_string();
1416 } else if second_part_of_line.contains("MiB") {
1417 sub_program_size = format!("{}000000", second_part_of_line.split(" ").collect::<Vec<&str>>()[0]);
1418 } else if second_part_of_line.contains("KiB") {
1419 sub_program_size = format!("{}000", second_part_of_line.split(" ").collect::<Vec<&str>>()[0]);
1420 } else {
1421 sub_program_description = second_part_of_line.to_string();
1422 }
1423 }
1424 }
1425
1426 if sub_program_name != "".to_string() &&
1427 sub_program_description != "".to_string() &&
1428 sub_program_website != "".to_string() &&
1429 sub_program_size != "".to_string() {
1430 subversions.push(ApkProgramSubVersion {
1431 name: sub_program_name,
1432 description: sub_program_description,
1433 website: sub_program_website,
1434 size: sub_program_size.parse::<i32>().unwrap()
1435 })
1436 }
1437 }
1438
1439 let get_program_command = std::process::Command::new("apk")
1440 .arg("info")
1441 .arg("-vv")
1442 .output()
1443 .unwrap();
1444
1445 let get_program_command = std::str::from_utf8(&get_program_command.stdout).unwrap();
1446
1447 for line in get_program_command.lines() {
1448 if line.starts_with(program_name) {
1449 let splitted_line = line.split(" - ").collect::<Vec<&str>>();
1450
1451 description = splitted_line[1].to_string();
1452
1453 let split_the_splitted_line = splitted_line[0].split("-").collect::<Vec<&str>>();
1454 let length_of_the_split = split_the_splitted_line.len();
1455
1456 for (index, split) in split_the_splitted_line.clone().into_iter().enumerate() {
1457 if index + 1 == length_of_the_split {
1458 update_info = split.to_string()
1459 }
1460
1461 if split.chars().next().map_or(false, |char| char.is_numeric()) {
1462 version = split.to_string();
1463 }
1464 };
1465
1466 update_info = split_the_splitted_line[length_of_the_split-1].to_string();
1467
1468 long_name = split_the_splitted_line.join("-");
1469
1470 break;
1471 } else {
1472 continue;
1473 }
1474 }
1475
1476 subversions.retain(|item| {
1477 if item.name == program_name {
1478 return false;
1479 } else {
1480 return true;
1481 }
1482 });
1483
1484 let size_val: Option<i32>;
1485
1486 if size == "" {
1487 size_val = None;
1488 } else {
1489 size_val = Some(size.parse::<i32>().unwrap());
1490 }
1491
1492 Ok(ApkProgram {
1493 name: program_name.to_string(),
1494 long_name,
1495 version,
1496 description,
1497 website,
1498 size: size_val,
1499 update: update_info,
1500 sub_versions: subversions
1501 })
1502 }
1503 Err(error) => Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, error))
1504 }
1505}
1506
1507pub fn list_all_apk_programs() -> std::result::Result<Vec<ApkProgram>, std::io::Error> {
1508 let get_all_apk_program_names = std::process::Command::new("apk")
1509 .arg("info")
1510 .output();
1511
1512 match get_all_apk_program_names {
1513 Ok(output) => {
1514 let get_output = std::str::from_utf8(&output.stdout).unwrap();
1515
1516 let mut all_apk_programs = vec![];
1517
1518 for line in get_output.lines() {
1519 let apk_program = get_apk_program(line.trim()).unwrap();
1520
1521 all_apk_programs.push(apk_program);
1522 }
1523
1524 Ok(all_apk_programs)
1525 },
1526 Err(error) => Err(std::io::Error::new(std::io::ErrorKind::Other, error))
1527 }
1528}
1529
1530pub fn check_if_curl_exist() -> bool {
1531 let result;
1532 let curl_command = std::process::Command::new("curl").output();
1533
1534 match curl_command {
1535 Ok(_) => result = true,
1536 Err(_) => result = false
1537 }
1538
1539 return result
1540}
1541
1542pub fn check_if_wget_exist() -> bool {
1543 let result;
1544 let wget_command = std::process::Command::new("wget").output();
1545
1546 match wget_command {
1547 Ok(_) => result = true,
1548 Err(_) => result = false
1549 }
1550
1551 return result
1552}
1553
1554pub fn check_if_dig_exist() -> bool {
1555 let result;
1556 let dig_command = std::process::Command::new("dig").output();
1557
1558 match dig_command {
1559 Ok(_) => result = true,
1560 Err(_) => result = false
1561 }
1562
1563 return result
1564}
1565
1566pub fn check_if_ip_exist() -> bool {
1567 let result;
1568 let ip_command = std::process::Command::new("ip").output();
1569
1570 match ip_command {
1571 Ok(_) => result = true,
1572 Err(_) => result = false
1573 }
1574
1575 return result
1576}