aboutsummaryrefslogtreecommitdiff
path: root/vendor/object/src/read/archive.rs
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
committerValentin Popov <valentin@popov.link>2024-07-19 15:37:58 +0300
commita990de90fe41456a23e58bd087d2f107d321f3a1 (patch)
tree15afc392522a9e85dc3332235e311b7d39352ea9 /vendor/object/src/read/archive.rs
parent3d48cd3f81164bbfc1a755dc1d4a9a02f98c8ddd (diff)
downloadfparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.tar.xz
fparkan-a990de90fe41456a23e58bd087d2f107d321f3a1.zip
Deleted vendor folder
Diffstat (limited to 'vendor/object/src/read/archive.rs')
-rw-r--r--vendor/object/src/read/archive.rs759
1 files changed, 0 insertions, 759 deletions
diff --git a/vendor/object/src/read/archive.rs b/vendor/object/src/read/archive.rs
deleted file mode 100644
index 5d4ec4a..0000000
--- a/vendor/object/src/read/archive.rs
+++ /dev/null
@@ -1,759 +0,0 @@
-//! Support for archive files.
-//!
-//! ## Example
-//! ```no_run
-//! use object::{Object, ObjectSection};
-//! use std::error::Error;
-//! use std::fs;
-//!
-//! /// Reads an archive and displays the name of each member.
-//! fn main() -> Result<(), Box<dyn Error>> {
-//! # #[cfg(feature = "std")] {
-//! let data = fs::read("path/to/binary")?;
-//! let file = object::read::archive::ArchiveFile::parse(&*data)?;
-//! for member in file.members() {
-//! let member = member?;
-//! println!("{}", String::from_utf8_lossy(member.name()));
-//! }
-//! # }
-//! Ok(())
-//! }
-//! ```
-
-use core::convert::TryInto;
-
-use crate::archive;
-use crate::read::{self, Bytes, Error, ReadError, ReadRef};
-
-/// The kind of archive format.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-#[non_exhaustive]
-pub enum ArchiveKind {
- /// There are no special files that indicate the archive format.
- Unknown,
- /// The GNU (or System V) archive format.
- Gnu,
- /// The GNU (or System V) archive format with 64-bit symbol table.
- Gnu64,
- /// The BSD archive format.
- Bsd,
- /// The BSD archive format with 64-bit symbol table.
- ///
- /// This is used for Darwin.
- Bsd64,
- /// The Windows COFF archive format.
- Coff,
- /// The AIX big archive format.
- AixBig,
-}
-
-/// The list of members in the archive.
-#[derive(Debug, Clone, Copy)]
-enum Members<'data> {
- Common {
- offset: u64,
- end_offset: u64,
- },
- AixBig {
- index: &'data [archive::AixMemberOffset],
- },
-}
-
-/// A partially parsed archive file.
-#[derive(Debug, Clone, Copy)]
-pub struct ArchiveFile<'data, R: ReadRef<'data> = &'data [u8]> {
- data: R,
- kind: ArchiveKind,
- members: Members<'data>,
- symbols: (u64, u64),
- names: &'data [u8],
-}
-
-impl<'data, R: ReadRef<'data>> ArchiveFile<'data, R> {
- /// Parse the archive header and special members.
- pub fn parse(data: R) -> read::Result<Self> {
- let len = data.len().read_error("Unknown archive length")?;
- let mut tail = 0;
- let magic = data
- .read_bytes(&mut tail, archive::MAGIC.len() as u64)
- .read_error("Invalid archive size")?;
-
- if magic == archive::AIX_BIG_MAGIC {
- return Self::parse_aixbig(data);
- } else if magic != archive::MAGIC {
- return Err(Error("Unsupported archive identifier"));
- }
-
- let mut members_offset = tail;
- let members_end_offset = len;
-
- let mut file = ArchiveFile {
- data,
- kind: ArchiveKind::Unknown,
- members: Members::Common {
- offset: 0,
- end_offset: 0,
- },
- symbols: (0, 0),
- names: &[],
- };
-
- // The first few members may be special, so parse them.
- // GNU has:
- // - "/" or "/SYM64/": symbol table (optional)
- // - "//": names table (optional)
- // COFF has:
- // - "/": first linker member
- // - "/": second linker member
- // - "//": names table
- // BSD has:
- // - "__.SYMDEF" or "__.SYMDEF SORTED": symbol table (optional)
- // BSD 64-bit has:
- // - "__.SYMDEF_64" or "__.SYMDEF_64 SORTED": symbol table (optional)
- // BSD may use the extended name for the symbol table. This is handled
- // by `ArchiveMember::parse`.
- if tail < len {
- let member = ArchiveMember::parse(data, &mut tail, &[])?;
- if member.name == b"/" {
- // GNU symbol table (unless we later determine this is COFF).
- file.kind = ArchiveKind::Gnu;
- file.symbols = member.file_range();
- members_offset = tail;
-
- if tail < len {
- let member = ArchiveMember::parse(data, &mut tail, &[])?;
- if member.name == b"/" {
- // COFF linker member.
- file.kind = ArchiveKind::Coff;
- file.symbols = member.file_range();
- members_offset = tail;
-
- if tail < len {
- let member = ArchiveMember::parse(data, &mut tail, &[])?;
- if member.name == b"//" {
- // COFF names table.
- file.names = member.data(data)?;
- members_offset = tail;
- }
- }
- } else if member.name == b"//" {
- // GNU names table.
- file.names = member.data(data)?;
- members_offset = tail;
- }
- }
- } else if member.name == b"/SYM64/" {
- // GNU 64-bit symbol table.
- file.kind = ArchiveKind::Gnu64;
- file.symbols = member.file_range();
- members_offset = tail;
-
- if tail < len {
- let member = ArchiveMember::parse(data, &mut tail, &[])?;
- if member.name == b"//" {
- // GNU names table.
- file.names = member.data(data)?;
- members_offset = tail;
- }
- }
- } else if member.name == b"//" {
- // GNU names table.
- file.kind = ArchiveKind::Gnu;
- file.names = member.data(data)?;
- members_offset = tail;
- } else if member.name == b"__.SYMDEF" || member.name == b"__.SYMDEF SORTED" {
- // BSD symbol table.
- file.kind = ArchiveKind::Bsd;
- file.symbols = member.file_range();
- members_offset = tail;
- } else if member.name == b"__.SYMDEF_64" || member.name == b"__.SYMDEF_64 SORTED" {
- // BSD 64-bit symbol table.
- file.kind = ArchiveKind::Bsd64;
- file.symbols = member.file_range();
- members_offset = tail;
- } else {
- // TODO: This could still be a BSD file. We leave this as unknown for now.
- }
- }
- file.members = Members::Common {
- offset: members_offset,
- end_offset: members_end_offset,
- };
- Ok(file)
- }
-
- fn parse_aixbig(data: R) -> read::Result<Self> {
- let mut tail = 0;
-
- let file_header = data
- .read::<archive::AixFileHeader>(&mut tail)
- .read_error("Invalid AIX big archive file header")?;
- // Caller already validated this.
- debug_assert_eq!(file_header.magic, archive::AIX_BIG_MAGIC);
-
- let mut file = ArchiveFile {
- data,
- kind: ArchiveKind::AixBig,
- members: Members::AixBig { index: &[] },
- symbols: (0, 0),
- names: &[],
- };
-
- // Read the span of symbol table.
- let symtbl64 = parse_u64_digits(&file_header.gst64off, 10)
- .read_error("Invalid offset to 64-bit symbol table in AIX big archive")?;
- if symtbl64 > 0 {
- // The symbol table is also a file with header.
- let member = ArchiveMember::parse_aixbig(data, symtbl64)?;
- file.symbols = member.file_range();
- } else {
- let symtbl = parse_u64_digits(&file_header.gstoff, 10)
- .read_error("Invalid offset to symbol table in AIX big archive")?;
- if symtbl > 0 {
- // The symbol table is also a file with header.
- let member = ArchiveMember::parse_aixbig(data, symtbl)?;
- file.symbols = member.file_range();
- }
- }
-
- // Big archive member index table lists file entries with offsets and names.
- // To avoid potential infinite loop (members are double-linked list), the
- // iterator goes through the index instead of real members.
- let member_table_offset = parse_u64_digits(&file_header.memoff, 10)
- .read_error("Invalid offset for member table of AIX big archive")?;
- if member_table_offset == 0 {
- // The offset would be zero if archive contains no file.
- return Ok(file);
- }
-
- // The member index table is also a file with header.
- let member = ArchiveMember::parse_aixbig(data, member_table_offset)?;
- let mut member_data = Bytes(member.data(data)?);
-
- // Structure of member index table:
- // Number of entries (20 bytes)
- // Offsets of each entry (20*N bytes)
- // Names string table (the rest of bytes to fill size defined in header)
- let members_count_bytes = member_data
- .read_slice::<u8>(20)
- .read_error("Missing member count in AIX big archive")?;
- let members_count = parse_u64_digits(members_count_bytes, 10)
- .and_then(|size| size.try_into().ok())
- .read_error("Invalid member count in AIX big archive")?;
- let index = member_data
- .read_slice::<archive::AixMemberOffset>(members_count)
- .read_error("Member count overflow in AIX big archive")?;
- file.members = Members::AixBig { index };
-
- Ok(file)
- }
-
- /// Return the archive format.
- #[inline]
- pub fn kind(&self) -> ArchiveKind {
- self.kind
- }
-
- /// Iterate over the members of the archive.
- ///
- /// This does not return special members.
- #[inline]
- pub fn members(&self) -> ArchiveMemberIterator<'data, R> {
- ArchiveMemberIterator {
- data: self.data,
- members: self.members,
- names: self.names,
- }
- }
-}
-
-/// An iterator over the members of an archive.
-#[derive(Debug)]
-pub struct ArchiveMemberIterator<'data, R: ReadRef<'data> = &'data [u8]> {
- data: R,
- members: Members<'data>,
- names: &'data [u8],
-}
-
-impl<'data, R: ReadRef<'data>> Iterator for ArchiveMemberIterator<'data, R> {
- type Item = read::Result<ArchiveMember<'data>>;
-
- fn next(&mut self) -> Option<Self::Item> {
- match &mut self.members {
- Members::Common {
- ref mut offset,
- ref mut end_offset,
- } => {
- if *offset >= *end_offset {
- return None;
- }
- let member = ArchiveMember::parse(self.data, offset, self.names);
- if member.is_err() {
- *offset = *end_offset;
- }
- Some(member)
- }
- Members::AixBig { ref mut index } => match **index {
- [] => None,
- [ref first, ref rest @ ..] => {
- *index = rest;
- let member = ArchiveMember::parse_aixbig_index(self.data, first);
- if member.is_err() {
- *index = &[];
- }
- Some(member)
- }
- },
- }
- }
-}
-
-/// An archive member header.
-#[derive(Debug, Clone, Copy)]
-enum MemberHeader<'data> {
- /// Common header used by many formats.
- Common(&'data archive::Header),
- /// AIX big archive header
- AixBig(&'data archive::AixHeader),
-}
-
-/// A partially parsed archive member.
-#[derive(Debug)]
-pub struct ArchiveMember<'data> {
- header: MemberHeader<'data>,
- name: &'data [u8],
- offset: u64,
- size: u64,
-}
-
-impl<'data> ArchiveMember<'data> {
- /// Parse the member header, name, and file data in an archive with the common format.
- ///
- /// This reads the extended name (if any) and adjusts the file size.
- fn parse<R: ReadRef<'data>>(
- data: R,
- offset: &mut u64,
- names: &'data [u8],
- ) -> read::Result<Self> {
- let header = data
- .read::<archive::Header>(offset)
- .read_error("Invalid archive member header")?;
- if header.terminator != archive::TERMINATOR {
- return Err(Error("Invalid archive terminator"));
- }
-
- let mut file_offset = *offset;
- let mut file_size =
- parse_u64_digits(&header.size, 10).read_error("Invalid archive member size")?;
- *offset = offset
- .checked_add(file_size)
- .read_error("Archive member size is too large")?;
- // Entries are padded to an even number of bytes.
- if (file_size & 1) != 0 {
- *offset = offset.saturating_add(1);
- }
-
- let name = if header.name[0] == b'/' && (header.name[1] as char).is_ascii_digit() {
- // Read file name from the names table.
- parse_sysv_extended_name(&header.name[1..], names)
- .read_error("Invalid archive extended name offset")?
- } else if &header.name[..3] == b"#1/" && (header.name[3] as char).is_ascii_digit() {
- // Read file name from the start of the file data.
- parse_bsd_extended_name(&header.name[3..], data, &mut file_offset, &mut file_size)
- .read_error("Invalid archive extended name length")?
- } else if header.name[0] == b'/' {
- let name_len = memchr::memchr(b' ', &header.name).unwrap_or(header.name.len());
- &header.name[..name_len]
- } else {
- let name_len = memchr::memchr(b'/', &header.name)
- .or_else(|| memchr::memchr(b' ', &header.name))
- .unwrap_or(header.name.len());
- &header.name[..name_len]
- };
-
- Ok(ArchiveMember {
- header: MemberHeader::Common(header),
- name,
- offset: file_offset,
- size: file_size,
- })
- }
-
- /// Parse a member index entry in an AIX big archive,
- /// and then parse the member header, name, and file data.
- fn parse_aixbig_index<R: ReadRef<'data>>(
- data: R,
- index: &archive::AixMemberOffset,
- ) -> read::Result<Self> {
- let offset = parse_u64_digits(&index.0, 10)
- .read_error("Invalid AIX big archive file member offset")?;
- Self::parse_aixbig(data, offset)
- }
-
- /// Parse the member header, name, and file data in an AIX big archive.
- fn parse_aixbig<R: ReadRef<'data>>(data: R, mut offset: u64) -> read::Result<Self> {
- // The format was described at
- // https://www.ibm.com/docs/en/aix/7.3?topic=formats-ar-file-format-big
- let header = data
- .read::<archive::AixHeader>(&mut offset)
- .read_error("Invalid AIX big archive member header")?;
- let name_length = parse_u64_digits(&header.namlen, 10)
- .read_error("Invalid AIX big archive member name length")?;
- let name = data
- .read_bytes(&mut offset, name_length)
- .read_error("Invalid AIX big archive member name")?;
-
- // The actual data for a file member begins at the first even-byte boundary beyond the
- // member header and continues for the number of bytes specified by the ar_size field. The
- // ar command inserts null bytes for padding where necessary.
- if offset & 1 != 0 {
- offset = offset.saturating_add(1);
- }
- // Because of the even-byte boundary, we have to read and check terminator after header.
- let terminator = data
- .read_bytes(&mut offset, 2)
- .read_error("Invalid AIX big archive terminator")?;
- if terminator != archive::TERMINATOR {
- return Err(Error("Invalid AIX big archive terminator"));
- }
-
- let size = parse_u64_digits(&header.size, 10)
- .read_error("Invalid archive member size in AIX big archive")?;
- Ok(ArchiveMember {
- header: MemberHeader::AixBig(header),
- name,
- offset,
- size,
- })
- }
-
- /// Return the raw header that is common to many archive formats.
- ///
- /// Returns `None` if this archive does not use the common header format.
- #[inline]
- pub fn header(&self) -> Option<&'data archive::Header> {
- match self.header {
- MemberHeader::Common(header) => Some(header),
- _ => None,
- }
- }
-
- /// Return the raw header for AIX big archives.
- ///
- /// Returns `None` if this is not an AIX big archive.
- #[inline]
- pub fn aix_header(&self) -> Option<&'data archive::AixHeader> {
- match self.header {
- MemberHeader::AixBig(header) => Some(header),
- _ => None,
- }
- }
-
- /// Return the parsed file name.
- ///
- /// This may be an extended file name.
- #[inline]
- pub fn name(&self) -> &'data [u8] {
- self.name
- }
-
- /// Parse the file modification timestamp from the header.
- #[inline]
- pub fn date(&self) -> Option<u64> {
- match &self.header {
- MemberHeader::Common(header) => parse_u64_digits(&header.date, 10),
- MemberHeader::AixBig(header) => parse_u64_digits(&header.date, 10),
- }
- }
-
- /// Parse the user ID from the header.
- #[inline]
- pub fn uid(&self) -> Option<u64> {
- match &self.header {
- MemberHeader::Common(header) => parse_u64_digits(&header.uid, 10),
- MemberHeader::AixBig(header) => parse_u64_digits(&header.uid, 10),
- }
- }
-
- /// Parse the group ID from the header.
- #[inline]
- pub fn gid(&self) -> Option<u64> {
- match &self.header {
- MemberHeader::Common(header) => parse_u64_digits(&header.gid, 10),
- MemberHeader::AixBig(header) => parse_u64_digits(&header.gid, 10),
- }
- }
-
- /// Parse the file mode from the header.
- #[inline]
- pub fn mode(&self) -> Option<u64> {
- match &self.header {
- MemberHeader::Common(header) => parse_u64_digits(&header.mode, 8),
- MemberHeader::AixBig(header) => parse_u64_digits(&header.mode, 8),
- }
- }
-
- /// Return the offset and size of the file data.
- pub fn file_range(&self) -> (u64, u64) {
- (self.offset, self.size)
- }
-
- /// Return the file data.
- #[inline]
- pub fn data<R: ReadRef<'data>>(&self, data: R) -> read::Result<&'data [u8]> {
- data.read_bytes_at(self.offset, self.size)
- .read_error("Archive member size is too large")
- }
-}
-
-// Ignores bytes starting from the first space.
-fn parse_u64_digits(digits: &[u8], radix: u32) -> Option<u64> {
- if let [b' ', ..] = digits {
- return None;
- }
- let mut result: u64 = 0;
- for &c in digits {
- if c == b' ' {
- return Some(result);
- } else {
- let x = (c as char).to_digit(radix)?;
- result = result
- .checked_mul(u64::from(radix))?
- .checked_add(u64::from(x))?;
- }
- }
- Some(result)
-}
-
-fn parse_sysv_extended_name<'data>(digits: &[u8], names: &'data [u8]) -> Result<&'data [u8], ()> {
- let offset = parse_u64_digits(digits, 10).ok_or(())?;
- let offset = offset.try_into().map_err(|_| ())?;
- let name_data = names.get(offset..).ok_or(())?;
- let name = match memchr::memchr2(b'/', b'\0', name_data) {
- Some(len) => &name_data[..len],
- None => name_data,
- };
- Ok(name)
-}
-
-/// Modifies `data` to start after the extended name.
-fn parse_bsd_extended_name<'data, R: ReadRef<'data>>(
- digits: &[u8],
- data: R,
- offset: &mut u64,
- size: &mut u64,
-) -> Result<&'data [u8], ()> {
- let len = parse_u64_digits(digits, 10).ok_or(())?;
- *size = size.checked_sub(len).ok_or(())?;
- let name_data = data.read_bytes(offset, len)?;
- let name = match memchr::memchr(b'\0', name_data) {
- Some(len) => &name_data[..len],
- None => name_data,
- };
- Ok(name)
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn kind() {
- let data = b"!<arch>\n";
- let archive = ArchiveFile::parse(&data[..]).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::Unknown);
-
- let data = b"\
- !<arch>\n\
- / 4 `\n\
- 0000";
- let archive = ArchiveFile::parse(&data[..]).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::Gnu);
-
- let data = b"\
- !<arch>\n\
- // 4 `\n\
- 0000";
- let archive = ArchiveFile::parse(&data[..]).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::Gnu);
-
- let data = b"\
- !<arch>\n\
- / 4 `\n\
- 0000\
- // 4 `\n\
- 0000";
- let archive = ArchiveFile::parse(&data[..]).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::Gnu);
-
- let data = b"\
- !<arch>\n\
- /SYM64/ 4 `\n\
- 0000";
- let archive = ArchiveFile::parse(&data[..]).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::Gnu64);
-
- let data = b"\
- !<arch>\n\
- /SYM64/ 4 `\n\
- 0000\
- // 4 `\n\
- 0000";
- let archive = ArchiveFile::parse(&data[..]).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::Gnu64);
-
- let data = b"\
- !<arch>\n\
- __.SYMDEF 4 `\n\
- 0000";
- let archive = ArchiveFile::parse(&data[..]).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::Bsd);
-
- let data = b"\
- !<arch>\n\
- #1/9 13 `\n\
- __.SYMDEF0000";
- let archive = ArchiveFile::parse(&data[..]).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::Bsd);
-
- let data = b"\
- !<arch>\n\
- #1/16 20 `\n\
- __.SYMDEF SORTED0000";
- let archive = ArchiveFile::parse(&data[..]).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::Bsd);
-
- let data = b"\
- !<arch>\n\
- __.SYMDEF_64 4 `\n\
- 0000";
- let archive = ArchiveFile::parse(&data[..]).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::Bsd64);
-
- let data = b"\
- !<arch>\n\
- #1/12 16 `\n\
- __.SYMDEF_640000";
- let archive = ArchiveFile::parse(&data[..]).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::Bsd64);
-
- let data = b"\
- !<arch>\n\
- #1/19 23 `\n\
- __.SYMDEF_64 SORTED0000";
- let archive = ArchiveFile::parse(&data[..]).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::Bsd64);
-
- let data = b"\
- !<arch>\n\
- / 4 `\n\
- 0000\
- / 4 `\n\
- 0000\
- // 4 `\n\
- 0000";
- let archive = ArchiveFile::parse(&data[..]).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::Coff);
-
- let data = b"\
- <bigaf>\n\
- 0 0 \
- 0 0 \
- 0 128 \
- 6 0 \
- 0 \0\0\0\0\0\0\0\0\0\0\0\0\
- \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
- \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
- \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
- let archive = ArchiveFile::parse(&data[..]).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::AixBig);
- }
-
- #[test]
- fn gnu_names() {
- let data = b"\
- !<arch>\n\
- // 18 `\n\
- 0123456789abcdef/\n\
- s p a c e/ 0 0 0 644 4 `\n\
- 0000\
- 0123456789abcde/0 0 0 644 3 `\n\
- odd\n\
- /0 0 0 0 644 4 `\n\
- even";
- let data = &data[..];
- let archive = ArchiveFile::parse(data).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::Gnu);
- let mut members = archive.members();
-
- let member = members.next().unwrap().unwrap();
- assert_eq!(member.name(), b"s p a c e");
- assert_eq!(member.data(data).unwrap(), &b"0000"[..]);
-
- let member = members.next().unwrap().unwrap();
- assert_eq!(member.name(), b"0123456789abcde");
- assert_eq!(member.data(data).unwrap(), &b"odd"[..]);
-
- let member = members.next().unwrap().unwrap();
- assert_eq!(member.name(), b"0123456789abcdef");
- assert_eq!(member.data(data).unwrap(), &b"even"[..]);
-
- assert!(members.next().is_none());
- }
-
- #[test]
- fn bsd_names() {
- let data = b"\
- !<arch>\n\
- 0123456789abcde 0 0 0 644 3 `\n\
- odd\n\
- #1/16 0 0 0 644 20 `\n\
- 0123456789abcdefeven";
- let data = &data[..];
- let archive = ArchiveFile::parse(data).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::Unknown);
- let mut members = archive.members();
-
- let member = members.next().unwrap().unwrap();
- assert_eq!(member.name(), b"0123456789abcde");
- assert_eq!(member.data(data).unwrap(), &b"odd"[..]);
-
- let member = members.next().unwrap().unwrap();
- assert_eq!(member.name(), b"0123456789abcdef");
- assert_eq!(member.data(data).unwrap(), &b"even"[..]);
-
- assert!(members.next().is_none());
- }
-
- #[test]
- fn aix_names() {
- let data = b"\
- <bigaf>\n\
- 396 0 0 \
- 128 262 0 \
- 4 262 0 \
- 1662610370 223 1 644 16 \
- 0123456789abcdef`\nord\n\
- 4 396 128 \
- 1662610374 223 1 644 16 \
- fedcba9876543210`\nrev\n\
- 94 0 262 \
- 0 0 0 0 0 \
- `\n2 128 \
- 262 0123456789abcdef\0fedcba9876543210\0";
- let data = &data[..];
- let archive = ArchiveFile::parse(data).unwrap();
- assert_eq!(archive.kind(), ArchiveKind::AixBig);
- let mut members = archive.members();
-
- let member = members.next().unwrap().unwrap();
- assert_eq!(member.name(), b"0123456789abcdef");
- assert_eq!(member.data(data).unwrap(), &b"ord\n"[..]);
-
- let member = members.next().unwrap().unwrap();
- assert_eq!(member.name(), b"fedcba9876543210");
- assert_eq!(member.data(data).unwrap(), &b"rev\n"[..]);
-
- assert!(members.next().is_none());
- }
-}