1use crate::shared::*;
51
52use std::borrow::Cow;
53use std::fs;
54use std::io::{Error, ErrorKind, Read, Write};
55use std::path::{Path, PathBuf};
56
57use regex::Regex;
58use xz::read::XzDecoder;
59use xz::write::XzEncoder;
60
61#[derive(Debug)]
65struct DebControl {
66 name: String,
67 version: String,
68 priority: DebPriority,
69 architecture: DebArchitecture,
70 essential: bool,
71 depends: Vec<String>,
72 pre_depends: Vec<String>,
73 recommends: Vec<String>,
74 suggests: Vec<String>,
75 breaks: Vec<String>,
76 conflicts: Vec<String>,
77 provides: Vec<String>,
78 replaces: Vec<String>,
79 enhances: Vec<String>,
80 maintainer: String,
81 description: String,
82 homepage: String,
83 built_using: Vec<[String; 2]>,
84}
85
86impl DebControl {
87 fn serialize(&self) -> Vec<u8> {
89 let mut write_out = String::new();
90 let depends = self.depends.join(", ");
92 let pre_depends = self.pre_depends.join(", ");
93 let recommends = self.recommends.join(", ");
94 let suggests = self.suggests.join(", ");
95 let breaks = self.breaks.join(", ");
96 let conflicts = self.conflicts.join(", ");
97 let provides = self.provides.join(", ");
98 let enhances = self.enhances.join(", ");
99 let built_using = {
100 let mut output: Vec<String> = Vec::new();
101 for build_depend in &self.built_using {
102 output.push(format!("{} (= {})", build_depend[0], build_depend[1]));
103 }
104 output.join(", ")
105 };
106 let control = vec![
107 ["Package", self.name.as_str()],
108 ["Version", self.version.as_str()],
109 ["Priority", self.priority.as_str()],
110 ["Architecture", self.architecture.as_str()],
111 [
112 "Essential",
113 match self.essential {
114 true => "yes",
115 false => "no",
116 },
117 ],
118 ["Depends", depends.as_str()],
119 ["Pre-Depends", pre_depends.as_str()],
120 ["Recommends", recommends.as_str()],
121 ["Suggests", suggests.as_str()],
122 ["Breaks", breaks.as_str()],
123 ["Conflicts", conflicts.as_str()],
124 ["Provides", provides.as_str()],
125 ["Enhances", enhances.as_str()],
126 ["Maintainer", self.maintainer.as_str()],
127 ["Description", self.description.as_str()],
128 ["Homepage", self.homepage.as_str()],
129 ["Built-Using", built_using.as_str()],
130 ];
131 for field in control {
132 if !field[1].is_empty() {
133 write_out = format!("{}{}: {}\n", write_out, field[0], field[1]);
134 }
135 }
136 write_out.into_bytes()
137 }
138
139 fn deserialize(control: Vec<u8>) -> std::io::Result<Self> {
141 fn split_to_vec(input: &str) -> Vec<String> {
143 input
144 .split(',')
145 .map(|str| str.trim().to_string())
146 .collect::<Vec<String>>()
147 }
148
149 let mut output = Self {
150 name: String::new(),
151 version: String::new(),
152 priority: DebPriority::Optional,
153 architecture: DebArchitecture::All,
154 essential: false,
155 depends: Vec::new(),
156 pre_depends: Vec::new(),
157 recommends: Vec::new(),
158 suggests: Vec::new(),
159 breaks: Vec::new(),
160 conflicts: Vec::new(),
161 provides: Vec::new(),
162 replaces: Vec::new(),
163 enhances: Vec::new(),
164 maintainer: String::new(),
165 description: String::new(),
166 homepage: String::new(),
167 built_using: Vec::new(),
168 };
169
170 let mut control_string = match String::from_utf8(control) {
171 Ok(string) => string,
172 Err(e) => return Err(Error::new(ErrorKind::Other, e)),
173 };
174
175 let iterator = control_string
179 .split('\n')
180 .collect::<Vec<&str>>()
181 .into_iter()
182 .map(|str| {
183 str.split(':')
184 .collect::<Vec<&str>>()
185 .into_iter()
186 .map(|str| str.trim())
187 .collect::<Vec<&str>>()
188 })
189 .collect::<Vec<Vec<&str>>>();
190
191 for line in iterator {
192 if line.len() == 1 {
195 continue;
196 } else if line.len() != 2 {
197 return Err(Error::new(ErrorKind::Other, "control file is invalid"));
198 }
199 match line[0] {
201 "Package" => {
202 output.name = line[1].to_string();
203 }
204 "Version" => {
205 output.version = line[1].to_string();
206 }
207 "Priority" => {
208 output.priority = DebPriority::from(line[1])?;
209 }
210 "Architecture" => {
211 output.architecture = DebArchitecture::from(line[1])?;
212 }
213 "Essential" => {
214 output.essential = match line[1] {
215 "yes" => true,
216 "no" => false,
217 &_ => {
218 return Err(Error::new(ErrorKind::Other, "control file is invalid"));
219 }
220 }
221 }
222 "Depends" => {
223 output.depends = split_to_vec(line[1]);
224 }
225 "Pre-Depends" => {
226 output.pre_depends = split_to_vec(line[1]);
227 }
228 "Recommends" => {
229 output.recommends = split_to_vec(line[1]);
230 }
231 "Suggests" => {
232 output.suggests = split_to_vec(line[1]);
233 }
234 "Breaks" => {
235 output.breaks = split_to_vec(line[1]);
236 }
237 "Conflicts" => {
238 output.conflicts = split_to_vec(line[1]);
239 }
240 "Provides" => {
241 output.provides = split_to_vec(line[1]);
242 }
243 "Replaces" => {
244 output.replaces = split_to_vec(line[1]);
245 }
246 "Enhances" => {
247 output.enhances = split_to_vec(line[1]);
248 }
249 "Maintainer" => {
250 output.maintainer = line[1].to_string();
251 }
252 "Description" => {
253 output.description = line[1].to_string();
254 }
255 "Homepage" => {
256 output.homepage = line[1].to_string();
257 }
258 "Built-Using" => {
259 let ver_regex: Regex = Regex::new(r"\(= ([^()]*)\)$").unwrap();
263 let mut built_using: Vec<[String; 2]> = Vec::new();
264 let source = split_to_vec(line[1]);
265 for entry in source {
266 built_using.push([
267 entry.split(' ').collect::<Vec<&str>>()[0].to_string(),
268 match ver_regex.find(line[1]) {
269 Some(mat) => mat.as_str().to_string(),
270 None => {
271 return Err(Error::new(
272 ErrorKind::Other,
273 "control file is invalid",
274 ));
275 }
276 },
277 ]);
278 }
279 }
280 &_ => {
281 return Err(Error::new(ErrorKind::Other, "control file is invalid"));
282 }
283 }
284 }
285
286 Ok(output)
287 }
288}
289
290#[derive(Debug)]
301pub struct DebPackage {
302 control: DebControl, data: Vec<DebFile>, config: Option<DebFile>, preinst: Option<DebFile>, postinst: Option<DebFile>, prerm: Option<DebFile>, postrm: Option<DebFile>, compression: DebCompression, }
311
312impl DebPackage {
313 pub fn new(name: &str) -> Self {
315 Self {
316 control: DebControl {
317 name: name.to_string(),
318 version: String::new(),
319 priority: DebPriority::Optional,
320 architecture: DebArchitecture::All,
321 essential: false,
322 depends: Vec::new(),
323 pre_depends: Vec::new(),
324 recommends: Vec::new(),
325 suggests: Vec::new(),
326 breaks: Vec::new(),
327 conflicts: Vec::new(),
328 provides: Vec::new(),
329 replaces: Vec::new(),
330 enhances: Vec::new(),
331 maintainer: String::new(),
332 description: String::new(),
333 homepage: String::new(),
334 built_using: Vec::new(),
335 },
336 data: Vec::new(),
337 config: None,
338 preinst: None,
339 postinst: None,
340 prerm: None,
341 postrm: None,
342 compression: DebCompression::Zstd,
343 }
344 }
345
346 pub fn from<R: Read>(mut input: R) -> std::io::Result<Self> {
348 DebArchive::read(input)?.to_package()
349 }
350
351 pub fn set_name(mut self, name: &str) -> Self {
353 self.control.name = name.to_string();
354 self
355 }
356
357 pub fn set_version(mut self, version: &str) -> Self {
359 self.control.version = version.to_string();
360 self
361 }
362
363 pub fn set_priority(mut self, priority: DebPriority) -> Self {
365 self.control.priority = priority;
366 self
367 }
368
369 pub fn set_architecture(mut self, architecture: DebArchitecture) -> Self {
371 self.control.architecture = architecture;
372 self
373 }
374
375 pub fn set_essential(mut self, essential: bool) -> Self {
377 self.control.essential = essential;
378 self
379 }
380
381 pub fn with_depend(mut self, depend: &str) -> Self {
383 self.control.depends.push(depend.to_string());
384 self
385 }
386
387 pub fn with_depends(mut self, depends: Vec<&str>) -> Self {
389 self.control
390 .depends
391 .append(&mut depends.iter().map(|str| str.to_string()).collect());
392 self
393 }
394
395 pub fn no_depends(mut self) -> Self {
397 self.control.depends = Vec::new();
398 self
399 }
400
401 pub fn with_pre_depend(mut self, depend: &str) -> Self {
403 self.control.pre_depends.push(depend.to_string());
404 self
405 }
406
407 pub fn with_pre_depends(mut self, depends: Vec<&str>) -> Self {
409 self.control
410 .pre_depends
411 .append(&mut depends.iter().map(|str| str.to_string()).collect());
412 self
413 }
414
415 pub fn no_pre_depends(mut self) -> Self {
417 self.control.pre_depends = Vec::new();
418 self
419 }
420
421 pub fn with_recommend(mut self, recommend: &str) -> Self {
423 self.control.recommends.push(recommend.to_string());
424 self
425 }
426
427 pub fn with_recommends(mut self, recommends: Vec<&str>) -> Self {
429 self.control
430 .recommends
431 .append(&mut recommends.iter().map(|str| str.to_string()).collect());
432 self
433 }
434
435 pub fn no_recommends(mut self) -> Self {
437 self.control.recommends = Vec::new();
438 self
439 }
440
441 pub fn with_suggest(mut self, suggest: &str) -> Self {
443 self.control.suggests.push(suggest.to_string());
444 self
445 }
446
447 pub fn with_suggests(mut self, suggests: Vec<&str>) -> Self {
449 self.control
450 .suggests
451 .append(&mut suggests.iter().map(|str| str.to_string()).collect());
452 self
453 }
454
455 pub fn no_suggests(mut self) -> Self {
457 self.control.suggests = Vec::new();
458 self
459 }
460
461 pub fn with_break(mut self, conflict: &str) -> Self {
463 self.control.breaks.push(conflict.to_string());
464 self
465 }
466
467 pub fn with_breaks(mut self, conflicts: Vec<&str>) -> Self {
469 self.control
470 .breaks
471 .append(&mut conflicts.iter().map(|str| str.to_string()).collect());
472 self
473 }
474
475 pub fn no_breaks(mut self) -> Self {
477 self.control.breaks = Vec::new();
478 self
479 }
480
481 pub fn with_conflict(mut self, conflict: &str) -> Self {
483 self.control.conflicts.push(conflict.to_string());
484 self
485 }
486
487 pub fn with_conflicts(mut self, conflicts: Vec<&str>) -> Self {
489 self.control
490 .conflicts
491 .append(&mut conflicts.iter().map(|str| str.to_string()).collect());
492 self
493 }
494
495 pub fn no_conflicts(mut self) -> Self {
497 self.control.conflicts = Vec::new();
498 self
499 }
500
501 pub fn with_provide(mut self, provide: &str) -> Self {
503 self.control.provides.push(provide.to_string());
504 self
505 }
506
507 pub fn with_provides(mut self, provides: Vec<&str>) -> Self {
509 self.control
510 .provides
511 .append(&mut provides.iter().map(|str| str.to_string()).collect());
512 self
513 }
514
515 pub fn no_provides(mut self) -> Self {
517 self.control.provides = Vec::new();
518 self
519 }
520
521 pub fn with_replace(mut self, replace: &str) -> Self {
523 self.control.replaces.push(replace.to_string());
524 self
525 }
526
527 pub fn with_replaces(mut self, replaces: Vec<&str>) -> Self {
529 self.control
530 .replaces
531 .append(&mut replaces.iter().map(|str| str.to_string()).collect());
532 self
533 }
534
535 pub fn no_replaces(mut self) -> Self {
537 self.control.replaces = Vec::new();
538 self
539 }
540
541 pub fn with_enhance(mut self, enhance: &str) -> Self {
543 self.control.enhances.push(enhance.to_string());
544 self
545 }
546
547 pub fn with_enhances(mut self, enhances: Vec<&str>) -> Self {
549 self.control
550 .enhances
551 .append(&mut enhances.iter().map(|str| str.to_string()).collect());
552 self
553 }
554
555 pub fn no_enhances(mut self) -> Self {
557 self.control.enhances = Vec::new();
558 self
559 }
560
561 pub fn set_maintainer(mut self, maintainer: &str) -> Self {
563 self.control.maintainer = maintainer.to_string();
564 self
565 }
566
567 pub fn set_description(mut self, description: &str) -> Self {
569 self.control.description = description.to_string();
570 self
571 }
572
573 pub fn set_homepage(mut self, homepage: &str) -> Self {
575 self.control.homepage = homepage.to_string();
576 self
577 }
578
579 pub fn with_built_using(mut self, using: &str, version: &str) -> Self {
581 self.control
582 .built_using
583 .push([using.to_string(), version.to_string()]);
584 self
585 }
586
587 pub fn no_built_using(mut self) -> Self {
589 self.control.built_using = Vec::new();
590 self
591 }
592
593 pub fn with_file(mut self, file: DebFile) -> Self {
595 self.data.push(file);
596 self
597 }
598
599 #[cfg(unix)]
623 pub fn with_dir<P>(mut self, from: P, to: P) -> std::io::Result<Self>
624 where
625 P: AsRef<Path>,
626 {
627 let mut path_from = PathBuf::new();
628 let mut path_to = PathBuf::new();
629 path_from.push(from);
630 path_to.push(to);
631 for file_result in walkdir::WalkDir::new(&path_from) {
632 let file = file_result?;
633 if file.path().is_file() {
634 let mut components = file.path().components();
636 for _i in path_from.components() {
637 components.next();
638 }
639 self = self.with_file(DebFile::from_path(file.path(), path_to.join(components))?);
640 }
641 }
642 Ok(self)
643 }
644
645 pub fn clear_files(mut self) -> Self {
647 self.data = Vec::new();
648 self
649 }
650
651 pub fn config_from_str(mut self, script: &str) -> Self {
653 self.config = Some(DebFile::from_buf(script.as_bytes().to_vec(), "config").is_exec());
654 self
655 }
656
657 pub fn config_from_buf(mut self, script: Vec<u8>) -> Self {
659 self.config = Some(DebFile::from_buf(script, "config").is_exec());
660 self
661 }
662
663 pub fn no_config(mut self) -> Self {
665 self.config = None;
666 self
667 }
668
669 pub fn preinst_from_str(mut self, script: &str) -> Self {
671 self.preinst = Some(DebFile::from_buf(script.as_bytes().to_vec(), "preinst").is_exec());
672 self
673 }
674
675 pub fn preinst_from_buf(mut self, script: Vec<u8>) -> Self {
677 self.preinst = Some(DebFile::from_buf(script, "preinst").is_exec());
678 self
679 }
680
681 pub fn no_preinst(mut self) -> Self {
683 self.preinst = None;
684 self
685 }
686
687 pub fn postinst_from_str(mut self, script: &str) -> Self {
689 self.postinst = Some(DebFile::from_buf(script.as_bytes().to_vec(), "postinst").is_exec());
690 self
691 }
692
693 pub fn postinst_from_buf(mut self, script: Vec<u8>) -> Self {
695 self.postinst = Some(DebFile::from_buf(script, "postinst").is_exec());
696 self
697 }
698
699 pub fn no_postinst(mut self) -> Self {
701 self.postinst = None;
702 self
703 }
704
705 pub fn prerm_from_str(mut self, script: &str) -> Self {
707 self.prerm = Some(DebFile::from_buf(script.as_bytes().to_vec(), "prerm").is_exec());
708 self
709 }
710
711 pub fn prerm_from_buf(mut self, script: Vec<u8>) -> Self {
713 self.prerm = Some(DebFile::from_buf(script, "prerm").is_exec());
714 self
715 }
716
717 pub fn no_prerm(mut self) -> Self {
719 self.prerm = None;
720 self
721 }
722
723 pub fn postrm_from_str(mut self, script: &str) -> Self {
725 self.postrm = Some(DebFile::from_buf(script.as_bytes().to_vec(), "postrm").is_exec());
726 self
727 }
728
729 pub fn postrm_from_buf(mut self, script: Vec<u8>) -> Self {
731 self.postrm = Some(DebFile::from_buf(script, "postrm").is_exec());
732 self
733 }
734
735 pub fn no_postrm(mut self) -> Self {
737 self.postrm = None;
738 self
739 }
740
741 pub fn set_compression(mut self, compression: DebCompression) -> Self {
743 self.compression = compression;
744 self
745 }
746
747 pub fn name(&self) -> &str {
749 &self.control.name
750 }
751
752 pub fn version(&self) -> &str {
754 &self.control.version
755 }
756
757 pub fn priority(&self) -> &DebPriority {
759 &self.control.priority
760 }
761
762 pub fn architecture(&self) -> &DebArchitecture {
764 &self.control.architecture
765 }
766
767 pub fn essential(&self) -> bool {
769 self.control.essential
770 }
771
772 pub fn depends(&self) -> &Vec<String> {
774 &self.control.depends
775 }
776
777 pub fn pre_depends(&self) -> &Vec<String> {
779 &self.control.pre_depends
780 }
781
782 pub fn recommends(&self) -> &Vec<String> {
784 &self.control.recommends
785 }
786
787 pub fn suggests(&self) -> &Vec<String> {
789 &self.control.suggests
790 }
791
792 pub fn breaks(&self) -> &Vec<String> {
794 &self.control.breaks
795 }
796
797 pub fn conflicts(&self) -> &Vec<String> {
799 &self.control.conflicts
800 }
801
802 pub fn provides(&self) -> &Vec<String> {
804 &self.control.provides
805 }
806
807 pub fn replaces(&self) -> &Vec<String> {
809 &self.control.replaces
810 }
811
812 pub fn enhances(&self) -> &Vec<String> {
814 &self.control.enhances
815 }
816
817 pub fn maintainer(&self) -> &str {
819 &self.control.maintainer
820 }
821
822 pub fn description(&self) -> &str {
824 &self.control.description
825 }
826
827 pub fn homepage(&self) -> &str {
829 &self.control.homepage
830 }
831
832 pub fn built_using(&self) -> &Vec<[String; 2]> {
834 &self.control.built_using
835 }
836
837 pub fn files(&self) -> &Vec<DebFile> {
839 &self.data
840 }
841
842 pub fn config(&self) -> Option<&Vec<u8>> {
844 match &self.config {
845 Some(file) => Some(file.contents()),
846 None => None,
847 }
848 }
849
850 pub fn preinst(&self) -> Option<&Vec<u8>> {
852 match &self.preinst {
853 Some(file) => Some(file.contents()),
854 None => None,
855 }
856 }
857
858 pub fn postinst(&self) -> Option<&Vec<u8>> {
860 match &self.postinst {
861 Some(file) => Some(file.contents()),
862 None => None,
863 }
864 }
865
866 pub fn prerm(&self) -> Option<&Vec<u8>> {
868 match &self.prerm {
869 Some(file) => Some(file.contents()),
870 None => None,
871 }
872 }
873
874 pub fn postrm(&self) -> Option<&Vec<u8>> {
876 match &self.postrm {
877 Some(file) => Some(file.contents()),
878 None => None,
879 }
880 }
881
882 pub fn compression(&self) -> &DebCompression {
884 &self.compression
885 }
886
887 pub fn build(&self) -> std::io::Result<DebArchive> {
889 let mut output = DebArchive {
890 control: Vec::new(),
891 data: Vec::new(),
892 compression: match self.compression {
893 DebCompression::Xz => DebCompression::Xz,
894 DebCompression::Zstd => DebCompression::Zstd,
895 },
896 };
897
898 let mut control_tar = tar::Builder::new(Vec::new());
900 let mut data_tar = tar::Builder::new(Vec::new());
901
902 let control_file = Some(DebFile::from_buf(self.control.serialize(), "control"));
904 let mut control_vec = vec![
905 &control_file,
906 &self.config,
907 &self.preinst,
908 &self.postinst,
909 &self.prerm,
910 &self.postrm,
911 ];
912
913 for file in control_vec.into_iter().flatten() {
915 let mut file_header = tar::Header::new_gnu();
916 file_header.set_path(file.path())?;
919 file_header.set_size(file.contents().len().try_into().unwrap());
920 file_header.set_mode(*file.mode());
921 file_header.set_cksum();
922 control_tar.append(&file_header, file.contents().as_slice())?;
923 }
924
925 for file in &self.data {
927 let mut file_header = tar::Header::new_gnu();
928 if file.path().is_absolute() {
931 match file.path().strip_prefix("/") {
932 Ok(path) => {
933 file_header.set_path(path)?;
934 }
935 Err(e) => {
936 return Err(Error::new(ErrorKind::Other, e));
937 }
938 }
939 } else {
940 file_header.set_path(file.path())?;
941 }
942 file_header.set_size(file.contents().len().try_into().unwrap());
943 file_header.set_mode(*file.mode());
944 file_header.set_cksum();
945 data_tar.append(&file_header, file.contents().as_slice())?;
946 }
947
948 match self.compression {
950 DebCompression::Xz => {
951 let mut control_xz = XzEncoder::new(&mut output.control, 9);
952 control_xz.write_all(control_tar.into_inner()?.as_slice())?;
953 control_xz.finish()?;
954 let mut data_xz = XzEncoder::new(&mut output.data, 9);
955 data_xz.write_all(data_tar.into_inner()?.as_slice())?;
956 data_xz.finish()?;
957 }
958 DebCompression::Zstd => {
959 zstd::stream::copy_encode(
960 control_tar.into_inner()?.as_slice(),
961 &mut output.control,
962 0,
963 )?;
964 zstd::stream::copy_encode(data_tar.into_inner()?.as_slice(), &mut output.data, 0)?;
965 }
966 }
967
968 Ok(output)
969 }
970}
971
972pub struct DebArchive {
980 control: Vec<u8>, data: Vec<u8>, compression: DebCompression, }
984
985impl DebArchive {
986 pub fn write<W: Write>(&self, mut output: W) -> std::io::Result<()> {
988 let (control_name, data_name) = match self.compression {
990 DebCompression::Xz => ("control.tar.xz", "data.tar.xz"),
991 DebCompression::Zstd => ("control.tar.zst", "data.tar.zst"),
992 };
993
994 let mut archive = ar::Builder::new(Vec::new());
996
997 let mut header = ar::Header::new("debian-binary".as_bytes().to_vec(), 4);
1000 header.set_mode(33188);
1001 archive.append(&header, "2.0\n".as_bytes())?;
1002
1003 let mut header = ar::Header::new(
1005 control_name.as_bytes().to_vec(),
1006 self.control.len().try_into().unwrap(),
1007 );
1008 header.set_mode(33188);
1009 archive.append(&header, self.control.as_slice())?;
1010
1011 let mut header = ar::Header::new(
1013 data_name.as_bytes().to_vec(),
1014 self.data.len().try_into().unwrap(),
1015 );
1016 header.set_mode(33188);
1017 archive.append(&header, self.data.as_slice())?;
1018
1019 output.write(&archive.into_inner()?);
1021 Ok(())
1022 }
1023
1024 pub fn read<R: Read>(mut input: R) -> std::io::Result<Self> {
1026 let mut output = Self {
1028 control: Vec::new(),
1029 data: Vec::new(),
1030 compression: DebCompression::Zstd,
1031 };
1032
1033 let mut archive = ar::Archive::new(input);
1035
1036 archive.next_entry().unwrap()?;
1038
1039 match archive.next_entry() {
1041 Some(entry) => {
1042 entry?.read_to_end(&mut output.control)?;
1043 }
1044 None => {
1045 return Err(Error::new(
1046 ErrorKind::Other,
1047 "deb package is missing archive",
1048 ));
1049 }
1050 }
1051
1052 let mut data_entry = match archive.next_entry() {
1054 Some(entry) => entry?,
1055 None => {
1056 return Err(Error::new(
1057 ErrorKind::Other,
1058 "deb package is missing archive",
1059 ))
1060 }
1061 };
1062 data_entry.read_to_end(&mut output.data)?;
1063
1064 let mut data_identifier = String::new();
1066 match String::from_utf8(data_entry.header().identifier().to_vec()) {
1067 Ok(id) => {
1068 data_identifier = id;
1069 }
1070 Err(e) => {
1071 return Err(Error::new(ErrorKind::Other, e));
1072 }
1073 }
1074 if let Some(ext) = Path::new(&data_identifier).extension() {
1075 if ext.to_str() == Some("xz") {
1076 output.compression = DebCompression::Xz;
1077 }
1078 }
1079
1080 Ok(output)
1081 }
1082
1083 pub fn to_package(&self) -> std::io::Result<DebPackage> {
1091 let mut output = DebPackage::new("");
1092 output.compression = match self.compression {
1093 DebCompression::Xz => DebCompression::Xz,
1094 DebCompression::Zstd => DebCompression::Zstd,
1095 };
1096
1097 let mut control_buf: Vec<u8> = Vec::new();
1099 let mut data_buf: Vec<u8> = Vec::new();
1100 match self.compression {
1101 DebCompression::Xz => {
1102 XzDecoder::new(self.control.as_slice()).read_to_end(&mut control_buf)?;
1103 XzDecoder::new(self.data.as_slice()).read_to_end(&mut data_buf)?;
1104 }
1105 DebCompression::Zstd => {
1106 zstd::stream::copy_decode(self.control.as_slice(), &mut control_buf)?;
1107 zstd::stream::copy_decode(self.data.as_slice(), &mut data_buf)?;
1108 }
1109 };
1110 let mut control_tar = tar::Archive::new(control_buf.as_slice());
1111 let mut data_tar = tar::Archive::new(data_buf.as_slice());
1112
1113 for entry_result in control_tar.entries()? {
1115 let mut entry = entry_result?;
1116 let mut buf: Vec<u8> = Vec::new();
1117 entry.read_to_end(&mut buf);
1118 if entry.path()? == Cow::Borrowed(Path::new("control")) {
1119 output.control = DebControl::deserialize(buf)?;
1121 } else if entry.path()? == Cow::Borrowed(Path::new("config")) {
1122 output = output.config_from_buf(buf);
1123 } else if entry.path()? == Cow::Borrowed(Path::new("preinst")) {
1124 output = output.preinst_from_buf(buf);
1125 } else if entry.path()? == Cow::Borrowed(Path::new("postinst")) {
1126 output = output.postinst_from_buf(buf);
1127 } else if entry.path()? == Cow::Borrowed(Path::new("prerm")) {
1128 output = output.prerm_from_buf(buf);
1129 } else if entry.path()? == Cow::Borrowed(Path::new("postrm")) {
1130 output = output.postrm_from_buf(buf);
1131 }
1132 }
1133
1134 for entry_result in data_tar.entries()? {
1136 let mut entry = entry_result?;
1137 let mut buf: Vec<u8> = Vec::new();
1138 entry.read_to_end(&mut buf);
1139 if let Cow::Borrowed(path) = entry.path()? {
1140 output.data.push(
1141 DebFile::from_buf(buf, format!("/{}", path.display()))
1142 .set_mode(entry.header().mode()?),
1143 )
1144 }
1145 }
1146
1147 Ok(output)
1148 }
1149}