1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
use core::mem; use core::str; use ptr::Align; #[repr(C)] struct Header { pub filename: [u8; 100], pub mode: [u8; 8], pub uid: [u8; 8], pub gid: [u8; 8], pub size: [u8; 12], pub mtime: [u8; 12], pub chksum: [u8; 8], pub typeflag: [u8; 1], } impl Header { pub fn parse_size(&self) -> usize { let mut size = 0usize; let mut j = 11; let mut count = 1; while j > 0 { size += (self.size[j - 1] - ('0' as u8)) as usize * count; j -= 1; count *= 8; } size } } fn nul_terminate(s: &[u8]) -> &[u8] { match s.iter().position(|b| *b == 0) { Some(index) => &s[0..index], None => s } } pub fn locate<'a>(data: &'a [u8], filename: &str) -> Option<&'a [u8]> { let mut offset = 0; while offset < data.len() { let header = unsafe { let header_slice = &data[offset .. offset + mem::size_of::<Header>()]; &*(header_slice.as_ptr() as *const Header) }; let header_filename = nul_terminate(&header.filename[..]); if header_filename.len() == 0 { break; } offset += 512; let size = header.parse_size(); if let Ok(header_filename) = str::from_utf8(header_filename) { if header_filename == filename { return Some(&data[offset .. offset + size]); } } offset += Align::up(size, 512); } None }