1use bitflags::bitflags;
21
22use crate::iso9660::entry::IsoEntry;
23
24impl IsoEntry<'_> {
25 pub fn xa(&self) -> Option<XaAttributes> {
27 let have_xa = unsafe { (*self.stat.as_ptr()).b_xa };
28 if !have_xa {
29 return None;
30 }
31
32 let xa = unsafe { (*self.stat.as_ptr()).xa };
34
35 Some(XaAttributes {
36 file_attr: XaFileAttributes::from_bits_retain(u16::from_be(xa.attributes)),
37 file_num: u8::from_be(xa.filenum),
38 group_id: u16::from_be(xa.group_id),
39 user_id: u16::from_be(xa.user_id),
40 total_size: self.total_size(),
41 })
42 }
43}
44
45#[derive(Clone, Debug)]
47#[non_exhaustive]
48pub struct XaAttributes {
49 pub file_attr: XaFileAttributes,
50 pub file_num: u8,
51 pub group_id: u16,
52 pub user_id: u16,
53 total_size: u64,
54}
55
56impl XaAttributes {
57 pub const fn mode2form2_size(&self) -> Option<u64> {
62 if !self.file_attr.contains(XaFileAttributes::Mode2Form2) {
63 return None;
64 }
65
66 const ISO_BLOCK_BYTES: u64 = 2048;
67 const MODE2FORM2_SECTOR_BYTES: u64 = 2324;
68
69 let total_sectors = self.total_size.div_ceil(ISO_BLOCK_BYTES);
70
71 Some(total_sectors * MODE2FORM2_SECTOR_BYTES)
72 }
73}
74
75bitflags! {
76 #[derive(Clone, Copy, Debug)]
80 pub struct XaFileAttributes: u16 {
81 const OwnerRead = 1 << 0;
82 const OwnerExecute = 1 << 2;
83 const GroupRead = 1 << 4;
84 const GroupExecute = 1 << 6;
85 const WorldRead = 1 << 8;
86 const WorldExecute = 1 << 10;
87 const Mode2 = 1 << 11;
88 const Mode2Form2 = 1 << 12;
89 const Interleaved = 1 << 13;
90 const Cdda = 1 << 14;
91 const Directory = 1 << 15;
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use std::path::PathBuf;
98
99 use crate::iso9660::Iso;
100
101 use super::*;
102
103 #[test]
104 fn xa() {
105 let iso = Iso::new(PathBuf::from("tests/data/xa.iso")).unwrap();
106 let entry = iso.entry("/copying".to_string()).unwrap();
107 let xa = entry.xa().unwrap();
108 assert_eq!(xa.file_num, 0);
109 assert_eq!(xa.group_id, 3000);
110 assert_eq!(xa.user_id, 1000);
111
112 let expected_attr =
113 XaFileAttributes::GroupRead & XaFileAttributes::GroupExecute & XaFileAttributes::Mode2;
114 assert!(xa.file_attr.contains(expected_attr));
115 }
116}