1use crate::date_time::DosDateTime;
2
3#[repr(u8)]
4#[derive(Debug, PartialEq, Clone, Copy)]
5pub enum HostOS {
6 MsDos = 0,
7 PrimOS = 1,
8 Unix = 2,
9 Amiga = 3,
10 MacOs = 4,
11 OS2 = 5,
12 AppleGS = 6,
13 AtariST = 7,
14 NeXT = 8,
15 VaxVMS = 9,
16 Win95 = 10,
17 Win32 = 11,
18
19 Unknown(u8),
20}
21
22impl From<u8> for HostOS {
23 fn from(value: u8) -> Self {
24 match value {
25 0 => HostOS::MsDos,
26 1 => HostOS::PrimOS,
27 2 => HostOS::Unix,
28 3 => HostOS::Amiga,
29 4 => HostOS::MacOs,
30 5 => HostOS::OS2,
31 6 => HostOS::AppleGS,
32 7 => HostOS::AtariST,
33 8 => HostOS::NeXT,
34 9 => HostOS::VaxVMS,
35 10 => HostOS::Win95,
36 11 => HostOS::Win32,
37 _ => HostOS::Unknown(value),
38 }
39 }
40}
41
42pub struct MainHeader {
43 pub archiver_version_number: u8,
44 pub min_version_to_extract: u8,
45 pub host_os: HostOS,
46 pub flags: u8,
47 pub security_version: u8,
48 pub file_type: u8,
49
50 pub creation_date_time: DosDateTime,
51 pub compr_size: u32,
52 pub archive_size: u32,
53 pub security_envelope: u32,
55 pub file_spec_position: u16,
56 pub security_envelope_length: u16,
57 pub encryption_version: u8,
58 pub last_chapter: u8,
59 pub arj_protection_factor: u8,
60 pub flags2: u8,
61 pub name: String,
62 pub comment: String,
63}
64const FIRST_HDR_SIZE: u8 = 34;
65impl MainHeader {
66 pub fn load_from(mut header_bytes: &[u8]) -> Self {
67 convert_u8!(header_size, header_bytes);
68 convert_u8!(archiver_version_number, header_bytes);
69 convert_u8!(min_version_to_extract, header_bytes);
70 convert_u8!(host_os, header_bytes);
71 convert_u8!(flags, header_bytes);
72 convert_u8!(security_version, header_bytes);
73 convert_u8!(file_type, header_bytes);
74 skip!(header_bytes, 1);
75 convert_u32!(creation_date_time, header_bytes);
76 convert_u32!(compr_size, header_bytes);
77 convert_u32!(archive_size, header_bytes);
78 convert_u32!(security_envelope, header_bytes);
79 convert_u16!(file_spec_position, header_bytes);
80 convert_u16!(security_envelope_length, header_bytes);
81
82 convert_u8!(encryption_version, header_bytes);
83 convert_u8!(last_chapter, header_bytes);
84
85 let mut arj_protection_factor = 0;
86 let mut flags2 = 0;
87
88 if header_size >= FIRST_HDR_SIZE {
89 convert_u8!(arj_protection_factor2, header_bytes);
90 convert_u8!(arj_flags22, header_bytes);
91 arj_protection_factor = arj_protection_factor2;
92 flags2 = arj_flags22;
93 skip!(header_bytes, 2);
94 }
95
96 convert_string!(name, header_bytes);
97 convert_string!(comment, header_bytes);
98 Self {
99 archiver_version_number,
100 min_version_to_extract,
101 host_os: host_os.into(),
102 flags,
103 security_version,
104 file_type,
105 creation_date_time: DosDateTime::new(creation_date_time),
106 compr_size,
107 archive_size,
108 security_envelope,
109 file_spec_position,
110 security_envelope_length,
111 encryption_version,
112 last_chapter,
113 arj_protection_factor,
114 flags2,
115 name,
116 comment,
117 }
118 }
119
120 pub fn is_gabled(&self) -> bool {
121 self.flags & 0x01 != 0
122 }
123
124 pub fn is_ansi_page(&self) -> bool {
125 self.flags & 0x02 != 0
126 }
127
128 pub fn is_volume(&self) -> bool {
129 self.flags & 0x04 != 0
130 }
131
132 pub fn is_arj_protected(&self) -> bool {
133 self.flags & 0x08 != 0
134 }
135
136 pub fn is_path_sym(&self) -> bool {
137 self.flags & 0x10 != 0
138 }
139
140 pub fn is_backup(&self) -> bool {
141 self.flags & 0x20 != 0
142 }
143
144 pub fn is_secured(&self) -> bool {
145 self.flags & 0x40 != 0
146 }
147
148 pub fn is_altname(&self) -> bool {
149 self.flags & 0x80 != 0
150 }
151}