From ce565ad6f33f65ff6ee2605c8f4b37d051668f43 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 26 Jul 2018 16:08:46 -0700 Subject: [PATCH] Run rustfmt over whole codebase --- examples/extract_file.rs | 2 +- examples/raw_list.rs | 9 +- examples/write.rs | 3 +- src/archive.rs | 134 ++++++----- src/builder.rs | 90 +++++--- src/entry.rs | 183 ++++++++------- src/entry_type.rs | 29 ++- src/header.rs | 474 ++++++++++++++++++++++++--------------- src/lib.rs | 24 +- src/pax.rs | 52 +++-- tests/all.rs | 185 +++++++++------ tests/entry.rs | 10 +- tests/header/mod.rs | 22 +- 13 files changed, 723 insertions(+), 494 deletions(-) diff --git a/examples/extract_file.rs b/examples/extract_file.rs index 33264d1f..425e9a35 100644 --- a/examples/extract_file.rs +++ b/examples/extract_file.rs @@ -6,8 +6,8 @@ extern crate tar; -use std::io::{stdin, stdout, copy}; use std::env::args_os; +use std::io::{copy, stdin, stdout}; use std::path::Path; use tar::Archive; diff --git a/examples/raw_list.rs b/examples/raw_list.rs index 8465bdd7..9b86da22 100644 --- a/examples/raw_list.rs +++ b/examples/raw_list.rs @@ -37,11 +37,12 @@ fn main() { println!("pax extensions:"); for e in extensions { let e = e.unwrap(); - println!("\t{:?} = {:?}", - String::from_utf8_lossy(e.key_bytes()), - String::from_utf8_lossy(e.value_bytes())); + println!( + "\t{:?} = {:?}", + String::from_utf8_lossy(e.key_bytes()), + String::from_utf8_lossy(e.value_bytes()) + ); } } } } - diff --git a/examples/write.rs b/examples/write.rs index 14392c2b..167263d9 100644 --- a/examples/write.rs +++ b/examples/write.rs @@ -8,5 +8,6 @@ fn main() { let mut a = Builder::new(file); a.append_path("README.md").unwrap(); - a.append_file("lib.rs", &mut File::open("src/lib.rs").unwrap()).unwrap(); + a.append_file("lib.rs", &mut File::open("src/lib.rs").unwrap()) + .unwrap(); } diff --git a/src/archive.rs b/src/archive.rs index 6861f331..fa6614fb 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -1,14 +1,14 @@ -use std::cell::{RefCell, Cell}; +use std::cell::{Cell, RefCell}; use std::cmp; -use std::io::prelude::*; use std::io; +use std::io::prelude::*; use std::marker; use std::path::Path; use entry::{EntryFields, EntryIo}; use error::TarError; use other; -use {Entry, Header, GnuSparseHeader, GnuExtSparseHeader}; +use {Entry, GnuExtSparseHeader, GnuSparseHeader, Header}; /// A top-level representation of an archive file. /// @@ -63,8 +63,9 @@ impl Archive { /// corrupted. pub fn entries(&mut self) -> io::Result> { let me: &mut Archive = self; - me._entries().map(|fields| { - Entries { fields: fields, _ignored: marker::PhantomData } + me._entries().map(|fields| Entries { + fields: fields, + _ignored: marker::PhantomData, }) } @@ -116,8 +117,10 @@ impl Archive { impl<'a> Archive { fn _entries(&mut self) -> io::Result { if self.inner.pos.get() != 0 { - return Err(other("cannot call entries unless archive is at \ - position 0")) + return Err(other( + "cannot call entries unless archive is at \ + position 0", + )); } Ok(EntriesFields { archive: self, @@ -129,9 +132,7 @@ impl<'a> Archive { fn _unpack(&mut self, dst: &Path) -> io::Result<()> { for entry in self._entries()? { - let mut file = entry.map_err(|e| { - TarError::new("failed to iterate over archive", e) - })?; + let mut file = entry.map_err(|e| TarError::new("failed to iterate over archive", e))?; file.unpack_in(dst)?; } Ok(()) @@ -143,7 +144,7 @@ impl<'a> Archive { let n = cmp::min(amt, buf.len() as u64); let n = (&self.inner).read(&mut buf[..n as usize])?; if n == 0 { - return Err(other("unexpected EOF during skip")) + return Err(other("unexpected EOF during skip")); } amt -= n as u64; } @@ -171,9 +172,9 @@ impl<'a, R: Read> Iterator for Entries<'a, R> { type Item = io::Result>; fn next(&mut self) -> Option>> { - self.fields.next().map(|result| { - result.map(|e| EntryFields::from(e).into_entry()) - }) + self.fields + .next() + .map(|result| result.map(|e| EntryFields::from(e).into_entry())) } } @@ -198,18 +199,21 @@ impl<'a> EntriesFields<'a> { return if header.as_bytes().iter().all(|i| *i == 0) { Ok(None) } else { - Err(other("found block of 0s not followed by a second \ - block of 0s")) - } + Err(other( + "found block of 0s not followed by a second \ + block of 0s", + )) + }; } // Make sure the checksum is ok - let sum = header.as_bytes()[..148].iter() - .chain(&header.as_bytes()[156..]) - .fold(0, |a, b| a + (*b as u32)) + 8 * 32; + let sum = header.as_bytes()[..148] + .iter() + .chain(&header.as_bytes()[156..]) + .fold(0, |a, b| a + (*b as u32)) + 8 * 32; let cksum = header.cksum()?; if sum != cksum { - return Err(other("archive header checksum mismatch")) + return Err(other("archive header checksum mismatch")); } let file_pos = self.next; @@ -238,7 +242,7 @@ impl<'a> EntriesFields<'a> { fn next_entry(&mut self) -> io::Result>> { if self.raw { - return self.next_entry_raw() + return self.next_entry_raw(); } let mut gnu_longname = None; @@ -250,40 +254,47 @@ impl<'a> EntriesFields<'a> { let entry = match self.next_entry_raw()? { Some(entry) => entry, None if processed > 1 => { - return Err(other("members found describing a future member \ - but no future member found")) + return Err(other( + "members found describing a future member \ + but no future member found", + )) } None => return Ok(None), }; - if entry.header().as_gnu().is_some() && - entry.header().entry_type().is_gnu_longname() { + if entry.header().as_gnu().is_some() && entry.header().entry_type().is_gnu_longname() { if gnu_longname.is_some() { - return Err(other("two long name entries describing \ - the same member")) + return Err(other( + "two long name entries describing \ + the same member", + )); } gnu_longname = Some(EntryFields::from(entry).read_all()?); - continue + continue; } - if entry.header().as_gnu().is_some() && - entry.header().entry_type().is_gnu_longlink() { + if entry.header().as_gnu().is_some() && entry.header().entry_type().is_gnu_longlink() { if gnu_longlink.is_some() { - return Err(other("two long name entries describing \ - the same member")) + return Err(other( + "two long name entries describing \ + the same member", + )); } gnu_longlink = Some(EntryFields::from(entry).read_all()?); - continue + continue; } - if entry.header().as_ustar().is_some() && - entry.header().entry_type().is_pax_local_extensions() { + if entry.header().as_ustar().is_some() + && entry.header().entry_type().is_pax_local_extensions() + { if pax_extensions.is_some() { - return Err(other("two pax extensions entries describing \ - the same member")) + return Err(other( + "two pax extensions entries describing \ + the same member", + )); } pax_extensions = Some(EntryFields::from(entry).read_all()?); - continue + continue; } let mut fields = EntryFields::from(entry); @@ -291,14 +302,13 @@ impl<'a> EntriesFields<'a> { fields.long_linkname = gnu_longlink; fields.pax_extensions = pax_extensions; self.parse_sparse_header(&mut fields)?; - return Ok(Some(fields.into_entry())) + return Ok(Some(fields.into_entry())); } } - fn parse_sparse_header(&mut self, - entry: &mut EntryFields<'a>) -> io::Result<()> { + fn parse_sparse_header(&mut self, entry: &mut EntryFields<'a>) -> io::Result<()> { if !entry.header.entry_type().is_gnu_sparse() { - return Ok(()) + return Ok(()); } let gnu = match entry.header.as_gnu() { Some(gnu) => gnu, @@ -334,27 +344,33 @@ impl<'a> EntriesFields<'a> { let size = entry.size; let mut add_block = |block: &GnuSparseHeader| -> io::Result<_> { if block.is_empty() { - return Ok(()) + return Ok(()); } let off = block.offset()?; let len = block.length()?; if (size - remaining) % 512 != 0 { - return Err(other("previous block in sparse file was not \ - aligned to 512-byte boundary")) + return Err(other( + "previous block in sparse file was not \ + aligned to 512-byte boundary", + )); } else if off < cur { - return Err(other("out of order or overlapping sparse \ - blocks")) + return Err(other( + "out of order or overlapping sparse \ + blocks", + )); } else if cur < off { let block = io::repeat(0).take(off - cur); data.push(EntryIo::Pad(block)); } - cur = off.checked_add(len).ok_or_else(|| { - other("more bytes listed in sparse file than u64 can hold") - })?; + cur = off + .checked_add(len) + .ok_or_else(|| other("more bytes listed in sparse file than u64 can hold"))?; remaining = remaining.checked_sub(len).ok_or_else(|| { - other("sparse file consumed more data than the header \ - listed") + other( + "sparse file consumed more data than the header \ + listed", + ) })?; data.push(EntryIo::Data(reader.take(len))); Ok(()) @@ -375,13 +391,17 @@ impl<'a> EntriesFields<'a> { } } if cur != gnu.real_size()? { - return Err(other("mismatch in sparse file chunks and \ - size in header")) + return Err(other( + "mismatch in sparse file chunks and \ + size in header", + )); } entry.size = cur; if remaining > 0 { - return Err(other("mismatch in sparse file chunks and \ - entry size in header")) + return Err(other( + "mismatch in sparse file chunks and \ + entry size in header", + )); } Ok(()) } diff --git a/src/builder.rs b/src/builder.rs index 0210d4ce..5b5c615f 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,11 +1,11 @@ +use std::borrow::Cow; +use std::fs; use std::io; -use std::path::Path; use std::io::prelude::*; -use std::fs; -use std::borrow::Cow; +use std::path::Path; -use {EntryType, Header, other}; -use header::{bytes2path, HeaderMode, path2bytes}; +use header::{bytes2path, path2bytes, HeaderMode}; +use {other, EntryType, Header}; /// A structure for building archives /// @@ -96,8 +96,7 @@ impl Builder { /// ar.append(&header, data).unwrap(); /// let data = ar.into_inner().unwrap(); /// ``` - pub fn append(&mut self, header: &Header, mut data: R) - -> io::Result<()> { + pub fn append(&mut self, header: &Header, mut data: R) -> io::Result<()> { append(self.inner(), header, &mut data) } @@ -141,8 +140,12 @@ impl Builder { /// ar.append_data(&mut header, "really/long/path/to/foo", data).unwrap(); /// let data = ar.into_inner().unwrap(); /// ``` - pub fn append_data, R: Read>(&mut self, header: &mut Header, path: P, data: R) - -> io::Result<()> { + pub fn append_data, R: Read>( + &mut self, + header: &mut Header, + path: P, + data: R, + ) -> io::Result<()> { prepare_header(self.inner(), header, path.as_ref())?; header.set_cksum(); self.append(&header, data) @@ -204,8 +207,7 @@ impl Builder { /// let mut f = File::open("foo/bar/baz.txt").unwrap(); /// ar.append_file("bar/baz.txt", &mut f).unwrap(); /// ``` - pub fn append_file>(&mut self, path: P, file: &mut fs::File) - -> io::Result<()> { + pub fn append_file>(&mut self, path: P, file: &mut fs::File) -> io::Result<()> { let mode = self.mode.clone(); append_file(self.inner(), path.as_ref(), file, mode) } @@ -236,7 +238,9 @@ impl Builder { /// ar.append_dir("bardir", ".").unwrap(); /// ``` pub fn append_dir(&mut self, path: P, src_path: Q) -> io::Result<()> - where P: AsRef, Q: AsRef + where + P: AsRef, + Q: AsRef, { let mode = self.mode.clone(); append_dir(self.inner(), path.as_ref(), src_path.as_ref(), mode) @@ -265,7 +269,9 @@ impl Builder { /// ar.append_dir_all("bardir", ".").unwrap(); /// ``` pub fn append_dir_all(&mut self, path: P, src_path: Q) -> io::Result<()> - where P: AsRef, Q: AsRef + where + P: AsRef, + Q: AsRef, { let mode = self.mode.clone(); let follow = self.follow; @@ -281,16 +287,14 @@ impl Builder { /// In most situations the `into_inner` method should be preferred. pub fn finish(&mut self) -> io::Result<()> { if self.finished { - return Ok(()) + return Ok(()); } self.finished = true; self.inner().write_all(&[0; 1024]) } } -fn append(mut dst: &mut Write, - header: &Header, - mut data: &mut Read) -> io::Result<()> { +fn append(mut dst: &mut Write, header: &Header, mut data: &mut Read) -> io::Result<()> { dst.write_all(header.as_bytes())?; let len = io::copy(&mut data, &mut dst)?; @@ -306,15 +310,19 @@ fn append(mut dst: &mut Write, fn append_path(dst: &mut Write, path: &Path, mode: HeaderMode, follow: bool) -> io::Result<()> { let stat = if follow { - fs::metadata(path).map_err(|err| io::Error::new( - err.kind(), - format!("{} when getting metadata for {}", err, path.display()), - ))? + fs::metadata(path).map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when getting metadata for {}", err, path.display()), + ) + })? } else { - fs::symlink_metadata(path).map_err(|err| io::Error::new( - err.kind(), - format!("{} when getting metadata for {}", err, path.display()), - ))? + fs::symlink_metadata(path).map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when getting metadata for {}", err, path.display()), + ) + })? }; if stat.is_file() { append_fs(dst, path, &stat, &mut fs::File::open(path)?, mode, None) @@ -328,8 +336,12 @@ fn append_path(dst: &mut Write, path: &Path, mode: HeaderMode, follow: bool) -> } } -fn append_file(dst: &mut Write, path: &Path, file: &mut fs::File, mode: HeaderMode) - -> io::Result<()> { +fn append_file( + dst: &mut Write, + path: &Path, + file: &mut fs::File, + mode: HeaderMode, +) -> io::Result<()> { let stat = file.metadata()?; append_fs(dst, path, &stat, file, mode, None) } @@ -347,7 +359,7 @@ fn prepare_header(dst: &mut Write, header: &mut Header, path: &Path) -> io::Resu let data = path2bytes(&path)?; let max = header.as_old().name.len(); if data.len() < max { - return Err(e) + return Err(e); } let mut header2 = Header::new_gnu(); header2.as_gnu_mut().unwrap().name[..13].clone_from_slice(b"././@LongLink"); @@ -368,12 +380,14 @@ fn prepare_header(dst: &mut Write, header: &mut Header, path: &Path) -> io::Resu Ok(()) } -fn append_fs(dst: &mut Write, - path: &Path, - meta: &fs::Metadata, - read: &mut Read, - mode: HeaderMode, - link_name: Option<&Path>) -> io::Result<()> { +fn append_fs( + dst: &mut Write, + path: &Path, + meta: &fs::Metadata, + read: &mut Read, + mode: HeaderMode, + link_name: Option<&Path>, +) -> io::Result<()> { let mut header = Header::new_gnu(); prepare_header(dst, &mut header, path)?; @@ -385,7 +399,13 @@ fn append_fs(dst: &mut Write, append(dst, &header, read) } -fn append_dir_all(dst: &mut Write, path: &Path, src_path: &Path, mode: HeaderMode, follow: bool) -> io::Result<()> { +fn append_dir_all( + dst: &mut Write, + path: &Path, + src_path: &Path, + mode: HeaderMode, + follow: bool, +) -> io::Result<()> { let mut stack = vec![(src_path.to_path_buf(), true, false)]; while let Some((src, is_dir, is_symlink)) = stack.pop() { let dest = path.join(src.strip_prefix(&src_path).unwrap()); diff --git a/src/entry.rs b/src/entry.rs index d426e837..f040287b 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -8,12 +8,12 @@ use std::path::{Component, Path, PathBuf}; use filetime::{self, FileTime}; -use {Header, Archive, PaxExtensions}; use archive::ArchiveInner; use error::TarError; use header::bytes2path; use other; use pax::pax_extensions; +use {Archive, Header, PaxExtensions}; /// A read-only view into an entry of an archive. /// @@ -274,7 +274,7 @@ impl<'a> EntryFields<'a> { .find(|f| f.key_bytes() == b"path") .map(|f| f.value_bytes()); if let Some(field) = pax { - return Cow::Borrowed(field) + return Cow::Borrowed(field); } } self.header.path_bytes() @@ -309,9 +309,10 @@ impl<'a> EntryFields<'a> { fn pax_extensions(&mut self) -> io::Result> { if self.pax_extensions.is_none() { - if !self.header.entry_type().is_pax_global_extensions() && - !self.header.entry_type().is_pax_local_extensions() { - return Ok(None) + if !self.header.entry_type().is_pax_global_extensions() + && !self.header.entry_type().is_pax_local_extensions() + { + return Ok(None); } self.pax_extensions = Some(self.read_all()?); } @@ -335,16 +336,17 @@ impl<'a> EntryFields<'a> { let mut file_dst = dst.to_path_buf(); { let path = self.path().map_err(|e| { - TarError::new(&format!("invalid path in entry header: {}", self.path_lossy()), e) + TarError::new( + &format!("invalid path in entry header: {}", self.path_lossy()), + e, + ) })?; for part in path.components() { match part { // Leading '/' characters, root paths, and '.' // components are just ignored and treated as "empty // components" - Component::Prefix(..) | - Component::RootDir | - Component::CurDir => continue, + Component::Prefix(..) | Component::RootDir | Component::CurDir => continue, // If any part of the filename is '..', then skip over // unpacking the file to prevent directory traversal @@ -366,47 +368,47 @@ impl<'a> EntryFields<'a> { // Skip entries without a parent (i.e. outside of FS root) let parent = match file_dst.parent() { Some(p) => p, - None => return Ok(false), + None => return Ok(false), }; if parent.symlink_metadata().is_err() { fs::create_dir_all(&parent).map_err(|e| { - TarError::new(&format!("failed to create `{}`", - parent.display()), e) + TarError::new(&format!("failed to create `{}`", parent.display()), e) })?; } let canon_target = self.validate_inside_dst(&dst, parent)?; - self.unpack(Some(&canon_target), &file_dst).map_err(|e| { - TarError::new(&format!("failed to unpack `{}`", file_dst.display()), e) - })?; + self.unpack(Some(&canon_target), &file_dst) + .map_err(|e| TarError::new(&format!("failed to unpack `{}`", file_dst.display()), e))?; Ok(true) } /// Returns access to the header of this entry in the archive. - fn unpack(&mut self, - target_base: Option<&Path>, - dst: &Path) -> io::Result<()> { + fn unpack(&mut self, target_base: Option<&Path>, dst: &Path) -> io::Result<()> { let kind = self.header.entry_type(); if kind.is_dir() { // If the directory already exists just let it slide let prev = fs::metadata(&dst); if prev.map(|m| m.is_dir()).unwrap_or(false) { - return Ok(()) + return Ok(()); } - return fs::create_dir(&dst).map_err(|err| Error::new( - err.kind(), - format!("{} when creating dir {}", err, dst.display()) - )); + return fs::create_dir(&dst).map_err(|err| { + Error::new( + err.kind(), + format!("{} when creating dir {}", err, dst.display()), + ) + }); } else if kind.is_hard_link() || kind.is_symlink() { let src = match self.link_name()? { Some(name) => name, - None => return Err(other(&format!( - "hard link listed for {} but no link name found", - String::from_utf8_lossy(self.header.as_bytes()) - ))), + None => { + return Err(other(&format!( + "hard link listed for {} but no link name found", + String::from_utf8_lossy(self.header.as_bytes()) + ))) + } }; if src.iter().count() == 0 { @@ -436,25 +438,29 @@ impl<'a> EntryFields<'a> { } None => src.into_owned(), }; - fs::hard_link(&link_src, dst).map_err(|err| Error::new( - err.kind(), - format!( - "{} when hard linking {} to {}", - err, - link_src.display(), - dst.display() + fs::hard_link(&link_src, dst).map_err(|err| { + Error::new( + err.kind(), + format!( + "{} when hard linking {} to {}", + err, + link_src.display(), + dst.display() + ), ) - )) + }) } else { - symlink(&src, dst).map_err(|err| Error::new( - err.kind(), - format!( - "{} when symlinking {} to {}", - err, - src.display(), - dst.display() + symlink(&src, dst).map_err(|err| { + Error::new( + err.kind(), + format!( + "{} when symlinking {} to {}", + err, + src.display(), + dst.display() + ), ) - )) + }) }; #[cfg(windows)] @@ -466,11 +472,12 @@ impl<'a> EntryFields<'a> { fn symlink(src: &Path, dst: &Path) -> io::Result<()> { ::std::os::unix::fs::symlink(src, dst) } - } else if kind.is_pax_global_extensions() || - kind.is_pax_local_extensions() || - kind.is_gnu_longname() || - kind.is_gnu_longlink() { - return Ok(()) + } else if kind.is_pax_global_extensions() + || kind.is_pax_local_extensions() + || kind.is_gnu_longname() + || kind.is_gnu_longlink() + { + return Ok(()); }; // Note the lack of `else` clause above. According to the FreeBSD @@ -489,7 +496,7 @@ impl<'a> EntryFields<'a> { match fs::remove_file(dst) { Ok(()) => {} Err(ref e) if e.kind() == io::ErrorKind::NotFound => {} - Err(e) => return Err(e) + Err(e) => return Err(e), } let mut f = fs::File::create(dst)?; for io in self.data.drain(..) { @@ -511,22 +518,33 @@ impl<'a> EntryFields<'a> { Ok(()) })().map_err(|e| { let header = self.header.path_bytes(); - TarError::new(&format!("failed to unpack `{}` into `{}`", - String::from_utf8_lossy(&header), - dst.display()), e) + TarError::new( + &format!( + "failed to unpack `{}` into `{}`", + String::from_utf8_lossy(&header), + dst.display() + ), + e, + ) })?; if let Ok(mtime) = self.header.mtime() { let mtime = FileTime::from_unix_time(mtime as i64, 0); filetime::set_file_times(dst, mtime, mtime).map_err(|e| { - TarError::new(&format!("failed to set mtime for `{}`", - dst.display()), e) + TarError::new(&format!("failed to set mtime for `{}`", dst.display()), e) })?; } if let Ok(mode) = self.header.mode() { set_perms(dst, mode, self.preserve_permissions).map_err(|e| { - TarError::new(&format!("failed to set permissions to {:o} \ - for `{}`", mode, dst.display()), e) + TarError::new( + &format!( + "failed to set permissions to {:o} \ + for `{}`", + mode, + dst.display() + ), + e, + ) })?; } if self.unpack_xattrs { @@ -538,11 +556,7 @@ impl<'a> EntryFields<'a> { fn set_perms(dst: &Path, mode: u32, preserve: bool) -> io::Result<()> { use std::os::unix::prelude::*; - let mode = if preserve { - mode - } else { - mode & 0o777 - }; + let mode = if preserve { mode } else { mode & 0o777 }; let perm = fs::Permissions::from_mode(mode as _); fs::set_permissions(dst, perm) @@ -556,35 +570,40 @@ impl<'a> EntryFields<'a> { #[cfg(all(unix, feature = "xattr"))] fn set_xattrs(me: &mut EntryFields, dst: &Path) -> io::Result<()> { - use std::os::unix::prelude::*; use std::ffi::OsStr; + use std::os::unix::prelude::*; use xattr; let exts = match me.pax_extensions() { Ok(Some(e)) => e, _ => return Ok(()), }; - let exts = exts.filter_map(|e| e.ok()).filter_map(|e| { - let key = e.key_bytes(); - let prefix = b"SCHILY.xattr."; - if key.starts_with(prefix) { - Some((&key[prefix.len()..], e)) - } else { - None - } - }).map(|(key, e)| { - (OsStr::from_bytes(key), e.value_bytes()) - }); + let exts = exts + .filter_map(|e| e.ok()) + .filter_map(|e| { + let key = e.key_bytes(); + let prefix = b"SCHILY.xattr."; + if key.starts_with(prefix) { + Some((&key[prefix.len()..], e)) + } else { + None + } + }) + .map(|(key, e)| (OsStr::from_bytes(key), e.value_bytes())); for (key, value) in exts { xattr::set(dst, key, value).map_err(|e| { - TarError::new(&format!("failed to set extended \ - attributes to {}. \ - Xattrs: key={:?}, value={:?}.", - dst.display(), - key, - String::from_utf8_lossy(value)), - e) + TarError::new( + &format!( + "failed to set extended \ + attributes to {}. \ + Xattrs: key={:?}, value={:?}.", + dst.display(), + key, + String::from_utf8_lossy(value) + ), + e, + ) })?; } @@ -631,7 +650,9 @@ impl<'a> Read for EntryFields<'a> { fn read(&mut self, into: &mut [u8]) -> io::Result { loop { match self.data.get_mut(0).map(|io| io.read(into)) { - Some(Ok(0)) => { self.data.remove(0); } + Some(Ok(0)) => { + self.data.remove(0); + } Some(r) => return r, None => return Ok(0), } diff --git a/src/entry_type.rs b/src/entry_type.rs index e9a256a8..951388d5 100644 --- a/src/entry_type.rs +++ b/src/entry_type.rs @@ -49,8 +49,7 @@ impl EntryType { /// appropriate to create a file type from. pub fn new(byte: u8) -> EntryType { match byte { - b'\x00' | - b'0' => EntryType::Regular, + b'\x00' | b'0' => EntryType::Regular, b'1' => EntryType::Link, b'2' => EntryType::Symlink, b'3' => EntryType::Char, @@ -63,26 +62,26 @@ impl EntryType { b'L' => EntryType::GNULongName, b'K' => EntryType::GNULongLink, b'S' => EntryType::GNUSparse, - b => EntryType::__Nonexhaustive(b), + b => EntryType::__Nonexhaustive(b), } } /// Returns the raw underlying byte that this entry type represents. pub fn as_byte(&self) -> u8 { match *self { - EntryType::Regular => b'0', - EntryType::Link => b'1', - EntryType::Symlink => b'2', - EntryType::Char => b'3', - EntryType::Block => b'4', - EntryType::Directory => b'5', - EntryType::Fifo => b'6', - EntryType::Continuous => b'7', - EntryType::XHeader => b'x', + EntryType::Regular => b'0', + EntryType::Link => b'1', + EntryType::Symlink => b'2', + EntryType::Char => b'3', + EntryType::Block => b'4', + EntryType::Directory => b'5', + EntryType::Fifo => b'6', + EntryType::Continuous => b'7', + EntryType::XHeader => b'x', EntryType::XGlobalHeader => b'g', - EntryType::GNULongName => b'L', - EntryType::GNULongLink => b'K', - EntryType::GNUSparse => b'S', + EntryType::GNULongName => b'L', + EntryType::GNULongLink => b'K', + EntryType::GNUSparse => b'S', EntryType::__Nonexhaustive(b) => b, } } diff --git a/src/header.rs b/src/header.rs index 76364e98..124c466d 100644 --- a/src/header.rs +++ b/src/header.rs @@ -1,18 +1,20 @@ -#[cfg(any(unix, target_os = "redox"))] use std::os::unix::prelude::*; -#[cfg(windows)] use std::os::windows::prelude::*; +#[cfg(any(unix, target_os = "redox"))] +use std::os::unix::prelude::*; +#[cfg(windows)] +use std::os::windows::prelude::*; use std::borrow::Cow; use std::fmt; use std::fs; use std::io; -use std::iter::repeat; use std::iter; +use std::iter::repeat; use std::mem; -use std::path::{Path, PathBuf, Component}; +use std::path::{Component, Path, PathBuf}; use std::str; -use EntryType; use other; +use EntryType; /// Representation of the header of an entry in an archive #[repr(C)] @@ -212,12 +214,20 @@ impl Header { /// magic/version fields of the UStar format have the appropriate values, /// returning `None` if they aren't correct. pub fn as_ustar(&self) -> Option<&UstarHeader> { - if self.is_ustar() {Some(unsafe { cast(self) })} else {None} + if self.is_ustar() { + Some(unsafe { cast(self) }) + } else { + None + } } /// Same as `as_ustar_mut`, but the mutable version. pub fn as_ustar_mut(&mut self) -> Option<&mut UstarHeader> { - if self.is_ustar() {Some(unsafe { cast_mut(self) })} else {None} + if self.is_ustar() { + Some(unsafe { cast_mut(self) }) + } else { + None + } } /// View this archive header as a raw GNU archive header. @@ -230,12 +240,20 @@ impl Header { /// magic/version fields of the GNU format have the appropriate values, /// returning `None` if they aren't correct. pub fn as_gnu(&self) -> Option<&GnuHeader> { - if self.is_gnu() {Some(unsafe { cast(self) })} else {None} + if self.is_gnu() { + Some(unsafe { cast(self) }) + } else { + None + } } /// Same as `as_gnu`, but the mutable version. pub fn as_gnu_mut(&mut self) -> Option<&mut GnuHeader> { - if self.is_gnu() {Some(unsafe { cast_mut(self) })} else {None} + if self.is_gnu() { + Some(unsafe { cast_mut(self) }) + } else { + None + } } /// Treats the given byte slice as a header. @@ -244,7 +262,7 @@ impl Header { pub fn from_byte_slice(bytes: &[u8]) -> &Header { assert_eq!(bytes.len(), mem::size_of::
()); assert_eq!(mem::align_of_val(bytes), mem::align_of::
()); - unsafe { &*(bytes.as_ptr() as * const Header) } + unsafe { &*(bytes.as_ptr() as *const Header) } } /// Returns a view into this header as a byte array. @@ -282,10 +300,12 @@ impl Header { /// /// May return an error if the field is corrupted. pub fn entry_size(&self) -> io::Result { - num_field_wrapper_from(&self.as_old().size) - .map_err(|err| io::Error::new(err.kind(), - format!( "{} when getting size for {}", err, self.path_lossy()), - )) + num_field_wrapper_from(&self.as_old().size).map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when getting size for {}", err, self.path_lossy()), + ) + }) } /// Returns the file size this header represents. @@ -293,9 +313,9 @@ impl Header { /// May return an error if the field is corrupted. pub fn size(&self) -> io::Result { if self.entry_type().is_gnu_sparse() { - self.as_gnu().ok_or_else(|| { - other("sparse header was not a gnu header") - }).and_then(|h| h.real_size()) + self.as_gnu() + .ok_or_else(|| other("sparse header was not a gnu header")) + .and_then(|h| h.real_size()) } else { self.entry_size() } @@ -349,13 +369,14 @@ impl Header { fn _set_path(&mut self, path: &Path) -> io::Result<()> { if let Some(ustar) = self.as_ustar_mut() { - return ustar.set_path(path) + return ustar.set_path(path); } - copy_path_into(&mut self.as_old_mut().name, path, false) - .map_err(|err| io::Error::new( + copy_path_into(&mut self.as_old_mut().name, path, false).map_err(|err| { + io::Error::new( err.kind(), - format!( "{} when setting path for {}", err, self.path_lossy()), - )) + format!("{} when setting path for {}", err, self.path_lossy()), + ) + }) } /// Returns the link name stored in this header, if any is found. @@ -399,21 +420,26 @@ impl Header { } fn _set_link_name(&mut self, path: &Path) -> io::Result<()> { - copy_path_into(&mut self.as_old_mut().linkname, path, true) - .map_err(|err| io::Error::new( - err.kind(), - format!( "{} when setting link name for {}", err, self.path_lossy()), - )) + copy_path_into(&mut self.as_old_mut().linkname, path, true).map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when setting link name for {}", err, self.path_lossy()), + ) + }) } /// Returns the mode bits for this file /// /// May return an error if the field is corrupted. pub fn mode(&self) -> io::Result { - octal_from(&self.as_old().mode).map(|u| u as u32).map_err(|err| io::Error::new( - err.kind(), - format!( "{} when getting mode for {}", err, self.path_lossy()), - )) + octal_from(&self.as_old().mode) + .map(|u| u as u32) + .map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when getting mode for {}", err, self.path_lossy()), + ) + }) } /// Encodes the `mode` provided into this header. @@ -425,10 +451,14 @@ impl Header { /// /// May return an error if the field is corrupted. pub fn uid(&self) -> io::Result { - num_field_wrapper_from(&self.as_old().uid).map(|u| u as u64) - .map_err(|err| io::Error::new(err.kind(), - format!( "{} when getting uid for {}", err, self.path_lossy()), - )) + num_field_wrapper_from(&self.as_old().uid) + .map(|u| u as u64) + .map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when getting uid for {}", err, self.path_lossy()), + ) + }) } /// Encodes the `uid` provided into this header. @@ -438,10 +468,14 @@ impl Header { /// Returns the value of the group's user ID field pub fn gid(&self) -> io::Result { - num_field_wrapper_from(&self.as_old().gid).map(|u| u as u64) - .map_err(|err| io::Error::new(err.kind(), - format!( "{} when getting gid for {}", err, self.path_lossy()), - )) + num_field_wrapper_from(&self.as_old().gid) + .map(|u| u as u64) + .map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when getting gid for {}", err, self.path_lossy()), + ) + }) } /// Encodes the `gid` provided into this header. @@ -451,10 +485,12 @@ impl Header { /// Returns the last modification time in Unix time format pub fn mtime(&self) -> io::Result { - num_field_wrapper_from(&self.as_old().mtime) - .map_err(|err| io::Error::new(err.kind(), - format!( "{} when getting mtime for {}", err, self.path_lossy()), - )) + num_field_wrapper_from(&self.as_old().mtime).map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when getting mtime for {}", err, self.path_lossy()), + ) + }) } /// Encodes the `mtime` provided into this header. @@ -498,7 +534,7 @@ impl Header { /// user name or the name is too long. pub fn set_username(&mut self, name: &str) -> io::Result<()> { if let Some(ustar) = self.as_ustar_mut() { - return ustar.set_username(name) + return ustar.set_username(name); } if let Some(gnu) = self.as_gnu_mut() { gnu.set_username(name) @@ -540,7 +576,7 @@ impl Header { /// group name or the name is too long. pub fn set_groupname(&mut self, name: &str) -> io::Result<()> { if let Some(ustar) = self.as_ustar_mut() { - return ustar.set_groupname(name) + return ustar.set_groupname(name); } if let Some(gnu) = self.as_gnu_mut() { gnu.set_groupname(name) @@ -572,7 +608,7 @@ impl Header { /// major device number. pub fn set_device_major(&mut self, major: u32) -> io::Result<()> { if let Some(ustar) = self.as_ustar_mut() { - return Ok(ustar.set_device_major(major)) + return Ok(ustar.set_device_major(major)); } if let Some(gnu) = self.as_gnu_mut() { Ok(gnu.set_device_major(major)) @@ -604,7 +640,7 @@ impl Header { /// minor device number. pub fn set_device_minor(&mut self, minor: u32) -> io::Result<()> { if let Some(ustar) = self.as_ustar_mut() { - return Ok(ustar.set_device_minor(minor)) + return Ok(ustar.set_device_minor(minor)); } if let Some(gnu) = self.as_gnu_mut() { Ok(gnu.set_device_minor(minor)) @@ -627,10 +663,14 @@ impl Header { /// /// May return an error if the field is corrupted. pub fn cksum(&self) -> io::Result { - octal_from(&self.as_old().cksum).map(|u| u as u32).map_err(|err| io::Error::new( - err.kind(), - format!( "{} when getting cksum for {}", err, self.path_lossy()), - )) + octal_from(&self.as_old().cksum) + .map(|u| u as u32) + .map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when getting cksum for {}", err, self.path_lossy()), + ) + }) } /// Sets the checksum field of this header based on the current fields in @@ -646,7 +686,8 @@ impl Header { let cksum_start = old.cksum.as_ptr() as *const _ as usize; let offset = cksum_start - start; let len = old.cksum.len(); - self.bytes[0..offset].iter() + self.bytes[0..offset] + .iter() .chain(iter::repeat(&b' ').take(len)) .chain(&self.bytes[offset + len..]) .fold(0, |a, b| a + (*b as u32)) @@ -655,7 +696,11 @@ impl Header { fn fill_from(&mut self, meta: &fs::Metadata, mode: HeaderMode) { self.fill_platform_from(meta, mode); // Set size of directories to zero - self.set_size(if meta.is_dir() || meta.file_type().is_symlink() { 0 } else { meta.len() }); + self.set_size(if meta.is_dir() || meta.file_type().is_symlink() { + 0 + } else { + meta.len() + }); if let Some(ustar) = self.as_ustar_mut() { ustar.set_device_major(0); ustar.set_device_minor(0); @@ -674,21 +719,20 @@ impl Header { self.set_uid(meta.uid() as u64); self.set_gid(meta.gid() as u64); self.set_mode(meta.mode() as u32); - }, + } HeaderMode::Deterministic => { self.set_mtime(0); self.set_uid(0); self.set_gid(0); // Use a default umask value, but propagate the (user) execute bit. - let fs_mode = - if meta.is_dir() || (0o100 & meta.mode() == 0o100) { + let fs_mode = if meta.is_dir() || (0o100 & meta.mode() == 0o100) { 0o755 - } else { + } else { 0o644 - }; + }; self.set_mode(fs_mode); - }, + } HeaderMode::__Nonexhaustive => panic!(), } @@ -754,19 +798,14 @@ impl Header { } }; self.set_mode(fs_mode); - }, + } HeaderMode::Deterministic => { self.set_uid(0); self.set_gid(0); self.set_mtime(0); - let fs_mode = - if meta.is_dir() { - 0o755 - } else { - 0o644 - }; + let fs_mode = if meta.is_dir() { 0o755 } else { 0o644 }; self.set_mode(fs_mode); - }, + } HeaderMode::__Nonexhaustive => panic!(), } @@ -923,37 +962,43 @@ impl UstarHeader { let bytes = path2bytes(path)?; let (maxnamelen, maxprefixlen) = (self.name.len(), self.prefix.len()); if bytes.len() <= maxnamelen { - copy_path_into(&mut self.name, path, false) - .map_err(|err| io::Error::new( - err.kind(), - format!( "{} when setting path for {}", err, self.path_lossy()), - ))?; + copy_path_into(&mut self.name, path, false).map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when setting path for {}", err, self.path_lossy()), + ) + })?; } else { let mut prefix = path; let mut prefixlen; loop { match prefix.parent() { Some(parent) => prefix = parent, - None => return Err(other(&format!( - "path cannot be split to be inserted into archive: {}", path.display() - ))), + None => { + return Err(other(&format!( + "path cannot be split to be inserted into archive: {}", + path.display() + ))) + } } prefixlen = path2bytes(prefix)?.len(); if prefixlen <= maxprefixlen { - break + break; } } - copy_path_into(&mut self.prefix, prefix, false) - .map_err(|err| io::Error::new( - err.kind(), - format!( "{} when setting path for {}", err, self.path_lossy()), - ))?; + copy_path_into(&mut self.prefix, prefix, false).map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when setting path for {}", err, self.path_lossy()), + ) + })?; let path = bytes2path(Cow::Borrowed(&bytes[prefixlen + 1..]))?; - copy_path_into(&mut self.name, &path, false) - .map_err(|err| io::Error::new( - err.kind(), - format!( "{} when setting path for {}", err, self.path_lossy()), - ))?; + copy_path_into(&mut self.name, &path, false).map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when setting path for {}", err, self.path_lossy()), + ) + })?; } Ok(()) } @@ -965,10 +1010,12 @@ impl UstarHeader { /// See `Header::set_username` pub fn set_username(&mut self, name: &str) -> io::Result<()> { - copy_into(&mut self.uname, name.as_bytes()).map_err(|err| io::Error::new( - err.kind(), - format!( "{} when setting username for {}", err, self.path_lossy()), - )) + copy_into(&mut self.uname, name.as_bytes()).map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when setting username for {}", err, self.path_lossy()), + ) + }) } /// See `Header::groupname_bytes` @@ -978,18 +1025,28 @@ impl UstarHeader { /// See `Header::set_groupname` pub fn set_groupname(&mut self, name: &str) -> io::Result<()> { - copy_into(&mut self.gname, name.as_bytes()).map_err(|err| io::Error::new( - err.kind(), - format!( "{} when setting groupname for {}", err, self.path_lossy()), - )) + copy_into(&mut self.gname, name.as_bytes()).map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when setting groupname for {}", err, self.path_lossy()), + ) + }) } /// See `Header::device_major` pub fn device_major(&self) -> io::Result { - octal_from(&self.dev_major).map(|u| u as u32).map_err(|err| io::Error::new( - err.kind(), - format!( "{} when getting device_major for {}", err, self.path_lossy()), - )) + octal_from(&self.dev_major) + .map(|u| u as u32) + .map_err(|err| { + io::Error::new( + err.kind(), + format!( + "{} when getting device_major for {}", + err, + self.path_lossy() + ), + ) + }) } /// See `Header::set_device_major` @@ -999,10 +1056,18 @@ impl UstarHeader { /// See `Header::device_minor` pub fn device_minor(&self) -> io::Result { - octal_from(&self.dev_minor).map(|u| u as u32).map_err(|err| io::Error::new( - err.kind(), - format!( "{} when getting device_minor for {}", err, self.path_lossy()), - )) + octal_from(&self.dev_minor) + .map(|u| u as u32) + .map_err(|err| { + io::Error::new( + err.kind(), + format!( + "{} when getting device_minor for {}", + err, + self.path_lossy() + ), + ) + }) } /// See `Header::set_device_minor` @@ -1046,10 +1111,16 @@ impl GnuHeader { /// See `Header::set_username` pub fn set_username(&mut self, name: &str) -> io::Result<()> { - copy_into(&mut self.uname, name.as_bytes()).map_err(|err| io::Error::new( - err.kind(), - format!( "{} when setting username for {}", err, self.fullname_lossy()), - )) + copy_into(&mut self.uname, name.as_bytes()).map_err(|err| { + io::Error::new( + err.kind(), + format!( + "{} when setting username for {}", + err, + self.fullname_lossy() + ), + ) + }) } /// See `Header::groupname_bytes` @@ -1059,18 +1130,32 @@ impl GnuHeader { /// See `Header::set_groupname` pub fn set_groupname(&mut self, name: &str) -> io::Result<()> { - copy_into(&mut self.gname, name.as_bytes()).map_err(|err| io::Error::new( - err.kind(), - format!( "{} when setting groupname for {}", err, self.fullname_lossy()), - )) + copy_into(&mut self.gname, name.as_bytes()).map_err(|err| { + io::Error::new( + err.kind(), + format!( + "{} when setting groupname for {}", + err, + self.fullname_lossy() + ), + ) + }) } /// See `Header::device_major` pub fn device_major(&self) -> io::Result { - octal_from(&self.dev_major).map(|u| u as u32).map_err(|err| io::Error::new( - err.kind(), - format!( "{} when getting device_major for {}", err, self.fullname_lossy()), - )) + octal_from(&self.dev_major) + .map(|u| u as u32) + .map_err(|err| { + io::Error::new( + err.kind(), + format!( + "{} when getting device_major for {}", + err, + self.fullname_lossy() + ), + ) + }) } /// See `Header::set_device_major` @@ -1080,10 +1165,18 @@ impl GnuHeader { /// See `Header::device_minor` pub fn device_minor(&self) -> io::Result { - octal_from(&self.dev_minor).map(|u| u as u32).map_err(|err| io::Error::new( - err.kind(), - format!( "{} when getting device_minor for {}", err, self.fullname_lossy()), - )) + octal_from(&self.dev_minor) + .map(|u| u as u32) + .map_err(|err| { + io::Error::new( + err.kind(), + format!( + "{} when getting device_minor for {}", + err, + self.fullname_lossy() + ), + ) + }) } /// See `Header::set_device_minor` @@ -1093,10 +1186,12 @@ impl GnuHeader { /// Returns the last modification time in Unix time format pub fn atime(&self) -> io::Result { - num_field_wrapper_from(&self.atime).map_err(|err| io::Error::new( - err.kind(), - format!( "{} when getting atime for {}", err, self.fullname_lossy()), - )) + num_field_wrapper_from(&self.atime).map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when getting atime for {}", err, self.fullname_lossy()), + ) + }) } /// Encodes the `atime` provided into this header. @@ -1109,10 +1204,12 @@ impl GnuHeader { /// Returns the last modification time in Unix time format pub fn ctime(&self) -> io::Result { - num_field_wrapper_from(&self.ctime).map_err(|err| io::Error::new( - err.kind(), - format!( "{} when getting ctime for {}", err, self.fullname_lossy()), - )) + num_field_wrapper_from(&self.ctime).map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when getting ctime for {}", err, self.fullname_lossy()), + ) + }) } /// Encodes the `ctime` provided into this header. @@ -1128,10 +1225,16 @@ impl GnuHeader { /// This is applicable for sparse files where the returned size here is the /// size of the entire file after the sparse regions have been filled in. pub fn real_size(&self) -> io::Result { - octal_from(&self.realsize).map_err(|err| io::Error::new( - err.kind(), - format!( "{} when getting real_size for {}", err, self.fullname_lossy()), - )) + octal_from(&self.realsize).map_err(|err| { + io::Error::new( + err.kind(), + format!( + "{} when getting real_size for {}", + err, + self.fullname_lossy() + ), + ) + }) } /// Indicates whether this header will be followed by additional @@ -1165,8 +1268,8 @@ impl fmt::Debug for GnuHeader { f.field("ctime", &ctime); } f.field("is_extended", &self.is_extended()) - .field("sparse", &DebugSparseHeaders(&self.sparse)) - .finish() + .field("sparse", &DebugSparseHeaders(&self.sparse)) + .finish() } } @@ -1194,20 +1297,24 @@ impl GnuSparseHeader { /// /// Returns `Err` for a malformed `offset` field. pub fn offset(&self) -> io::Result { - octal_from(&self.offset).map_err(|err| io::Error::new( - err.kind(), - format!( "{} when getting offset from sparce header", err), - )) + octal_from(&self.offset).map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when getting offset from sparce header", err), + ) + }) } /// Length of the block /// /// Returns `Err` for a malformed `numbytes` field. pub fn length(&self) -> io::Result { - octal_from(&self.numbytes).map_err(|err| io::Error::new( - err.kind(), - format!( "{} when getting length from sparse header", err), - )) + octal_from(&self.numbytes).map_err(|err| { + io::Error::new( + err.kind(), + format!("{} when getting length from sparse header", err), + ) + }) } } @@ -1266,14 +1373,16 @@ fn octal_from(slice: &[u8]) -> io::Result { let trun = truncate(slice); let num = match str::from_utf8(trun) { Ok(n) => n, - Err(_) => return Err(other( - &format!("numeric field did not have utf-8 text: {}", - String::from_utf8_lossy(trun)))), + Err(_) => { + return Err(other(&format!( + "numeric field did not have utf-8 text: {}", + String::from_utf8_lossy(trun) + ))) + } }; match u64::from_str_radix(num.trim(), 8) { Ok(n) => Ok(n), - Err(_) => Err(other(&format!("numeric field was not a number: {}", - num))), + Err(_) => Err(other(&format!("numeric field was not a number: {}", num))), } } @@ -1312,9 +1421,10 @@ fn num_field_wrapper_from(src: &[u8]) -> io::Result { fn numeric_extended_into(dst: &mut [u8], src: u64) { let len: usize = dst.len(); for (slot, val) in dst.iter_mut().zip( - repeat(0).take(len - 8) // to zero init extra bytes - .chain((0..8).map(|x| ((src.to_be() >> (8 * x)) & 0xff) as u8))) { - *slot = val; + repeat(0).take(len - 8) // to zero init extra bytes + .chain((0..8).map(|x| ((src.to_be() >> (8 * x)) & 0xff) as u8)), + ) { + *slot = val; } dst[0] |= 0x80; } @@ -1322,9 +1432,11 @@ fn numeric_extended_into(dst: &mut [u8], src: u64) { fn numeric_extended_from(src: &[u8]) -> u64 { let mut dst: u64 = 0; let mut b_to_skip = 1; - if src.len() == 8 { // read first byte without extension flag bit + if src.len() == 8 { + // read first byte without extension flag bit dst = (src[0] ^ 0x80) as u64; - } else { // only read last 8 bytes + } else { + // only read last 8 bytes b_to_skip = src.len() - 8; } for byte in src.iter().skip(b_to_skip) { @@ -1364,33 +1476,29 @@ fn copy_into(slot: &mut [u8], bytes: &[u8]) -> io::Result<()> { /// * a nul byte was found /// * an invalid path component is encountered (e.g. a root path or parent dir) /// * the path itself is empty -fn copy_path_into(mut slot: &mut [u8], - path: &Path, - is_link_name: bool) -> io::Result<()> { +fn copy_path_into(mut slot: &mut [u8], path: &Path, is_link_name: bool) -> io::Result<()> { let mut emitted = false; let mut needs_slash = false; for component in path.components() { let bytes = path2bytes(Path::new(component.as_os_str()))?; match (component, is_link_name) { - (Component::Prefix(..), false) | - (Component::RootDir, false) => { + (Component::Prefix(..), false) | (Component::RootDir, false) => { return Err(other("paths in archives must be relative")) } (Component::ParentDir, false) => { return Err(other("paths in archives must not have `..`")) } // Allow "./" as the path - (Component::CurDir, false) if path.components().count() == 1 => {}, + (Component::CurDir, false) if path.components().count() == 1 => {} (Component::CurDir, false) => continue, - (Component::Normal(_), _) | - (_, true) => {} + (Component::Normal(_), _) | (_, true) => {} }; if needs_slash { copy(&mut slot, b"/")?; } if bytes.contains(&b'/') { if let Component::Normal(..) = component { - return Err(other("path component in archive cannot contain `/`")) + return Err(other("path component in archive cannot contain `/`")); } } copy(&mut slot, &*bytes)?; @@ -1400,7 +1508,7 @@ fn copy_path_into(mut slot: &mut [u8], emitted = true; } if !emitted { - return Err(other("paths in archives must have at least one component")) + return Err(other("paths in archives must have at least one component")); } if ends_with_slash(path) { copy(&mut slot, &[b'/'])?; @@ -1428,22 +1536,24 @@ fn ends_with_slash(p: &Path) -> bool { #[cfg(windows)] pub fn path2bytes(p: &Path) -> io::Result> { - p.as_os_str().to_str().map(|s| s.as_bytes()).ok_or_else(|| { - other(&format!("path {} was not valid unicode", p.display())) - }).map(|bytes| { - if bytes.contains(&b'\\') { - // Normalize to Unix-style path separators - let mut bytes = bytes.to_owned(); - for b in &mut bytes { - if *b == b'\\' { - *b = b'/'; + p.as_os_str() + .to_str() + .map(|s| s.as_bytes()) + .ok_or_else(|| other(&format!("path {} was not valid unicode", p.display()))) + .map(|bytes| { + if bytes.contains(&b'\\') { + // Normalize to Unix-style path separators + let mut bytes = bytes.to_owned(); + for b in &mut bytes { + if *b == b'\\' { + *b = b'/'; + } } + Cow::Owned(bytes) + } else { + Cow::Borrowed(bytes) } - Cow::Owned(bytes) - } else { - Cow::Borrowed(bytes) - } - }) + }) } #[cfg(any(unix, target_os = "redox"))] @@ -1458,15 +1568,11 @@ pub fn path2bytes(p: &Path) -> io::Result> { pub fn bytes2path(bytes: Cow<[u8]>) -> io::Result> { return match bytes { Cow::Borrowed(bytes) => { - let s = try!(str::from_utf8(bytes).map_err(|_| { - not_unicode(bytes) - })); + let s = try!(str::from_utf8(bytes).map_err(|_| not_unicode(bytes))); Ok(Cow::Borrowed(Path::new(s))) } Cow::Owned(bytes) => { - let s = try!(String::from_utf8(bytes).map_err(|uerr| { - not_unicode(&uerr.into_bytes()) - })); + let s = try!(String::from_utf8(bytes).map_err(|uerr| not_unicode(&uerr.into_bytes()))); Ok(Cow::Owned(PathBuf::from(s))) } }; @@ -1485,11 +1591,7 @@ pub fn bytes2path(bytes: Cow<[u8]>) -> io::Result> { use std::ffi::{OsStr, OsString}; Ok(match bytes { - Cow::Borrowed(bytes) => Cow::Borrowed({ - Path::new(OsStr::from_bytes(bytes)) - }), - Cow::Owned(bytes) => Cow::Owned({ - PathBuf::from(OsString::from_vec(bytes)) - }) + Cow::Borrowed(bytes) => Cow::Borrowed({ Path::new(OsStr::from_bytes(bytes)) }), + Cow::Owned(bytes) => Cow::Owned({ PathBuf::from(OsString::from_vec(bytes)) }), }) } diff --git a/src/lib.rs b/src/lib.rs index b3b8fe5f..4188cfd1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,24 +21,24 @@ #![deny(missing_docs)] #![cfg_attr(test, deny(warnings))] +extern crate filetime; #[cfg(unix)] extern crate libc; -extern crate filetime; -#[cfg(all(unix, feature = "xattr"))] -extern crate xattr; #[cfg(target_os = "redox")] extern crate syscall; +#[cfg(all(unix, feature = "xattr"))] +extern crate xattr; use std::io::{Error, ErrorKind}; use std::ops::{Deref, DerefMut}; -pub use header::{Header, HeaderMode, OldHeader, UstarHeader, GnuHeader, GnuSparseHeader}; -pub use header::{GnuExtSparseHeader}; -pub use entry_type::EntryType; -pub use entry::Entry; pub use archive::{Archive, Entries}; pub use builder::Builder; -pub use pax::{PaxExtensions, PaxExtension}; +pub use entry::Entry; +pub use entry_type::EntryType; +pub use header::GnuExtSparseHeader; +pub use header::{GnuHeader, GnuSparseHeader, Header, HeaderMode, OldHeader, UstarHeader}; +pub use pax::{PaxExtension, PaxExtensions}; mod archive; mod builder; @@ -60,10 +60,14 @@ struct AlignHigher(u64, R); impl Deref for AlignHigher { type Target = R; - fn deref(&self) -> &R { &self.1 } + fn deref(&self) -> &R { + &self.1 + } } impl DerefMut for AlignHigher { - fn deref_mut(&mut self) -> &mut R { &mut self.1 } + fn deref_mut(&mut self) -> &mut R { + &mut self.1 + } } fn other(msg: &str) -> Error { diff --git a/src/pax.rs b/src/pax.rs index fe6d5aa7..69a1b33f 100644 --- a/src/pax.rs +++ b/src/pax.rs @@ -1,6 +1,6 @@ use std::io; -use std::str; use std::slice; +use std::str; use other; @@ -19,8 +19,12 @@ pub struct PaxExtension<'entry> { } pub fn pax_extensions(a: &[u8]) -> PaxExtensions { - fn is_newline(a: &u8) -> bool { *a == b'\n' } - PaxExtensions { data: a.split(is_newline) } + fn is_newline(a: &u8) -> bool { + *a == b'\n' + } + PaxExtensions { + data: a.split(is_newline), + } } impl<'entry> Iterator for PaxExtensions<'entry> { @@ -33,26 +37,30 @@ impl<'entry> Iterator for PaxExtensions<'entry> { None => return None, }; - Some(line.iter().position(|b| *b == b' ').and_then(|i| { - str::from_utf8(&line[..i]).ok().and_then(|len| { - len.parse::().ok().map(|j| (i + 1, j)) - }) - }).and_then(|(kvstart, reported_len)| { - if line.len() + 1 == reported_len { - line[kvstart..].iter().position(|b| *b == b'=').map(|equals| { - (kvstart, equals) + Some( + line.iter() + .position(|b| *b == b' ') + .and_then(|i| { + str::from_utf8(&line[..i]) + .ok() + .and_then(|len| len.parse::().ok().map(|j| (i + 1, j))) + }) + .and_then(|(kvstart, reported_len)| { + if line.len() + 1 == reported_len { + line[kvstart..] + .iter() + .position(|b| *b == b'=') + .map(|equals| (kvstart, equals)) + } else { + None + } + }) + .map(|(kvstart, equals)| PaxExtension { + key: &line[kvstart..kvstart + equals], + value: &line[kvstart + equals + 1..], }) - } else { - None - } - }).map(|(kvstart, equals)| { - PaxExtension { - key: &line[kvstart..kvstart + equals], - value: &line[kvstart + equals + 1..], - } - }).ok_or_else(|| { - other("malformed pax extension") - })) + .ok_or_else(|| other("malformed pax extension")), + ) } } diff --git a/tests/all.rs b/tests/all.rs index 10eca5e0..0e61f72e 100644 --- a/tests/all.rs +++ b/tests/all.rs @@ -10,19 +10,23 @@ use std::io::{self, Cursor}; use std::iter::repeat; use std::path::{Path, PathBuf}; -use filetime::FileTime; use self::tempdir::TempDir; -use tar::{Archive, Builder, Header, EntryType}; +use filetime::FileTime; +use tar::{Archive, Builder, EntryType, Header}; macro_rules! t { - ($e:expr) => (match $e { - Ok(v) => v, - Err(e) => panic!("{} returned {}", stringify!($e), e), - }) + ($e:expr) => { + match $e { + Ok(v) => v, + Err(e) => panic!("{} returned {}", stringify!($e), e), + } + }; } macro_rules! tar { - ($e:expr) => (&include_bytes!(concat!("archives/", $e))[..]) + ($e:expr) => { + &include_bytes!(concat!("archives/", $e))[..] + }; } mod header; @@ -215,7 +219,10 @@ fn no_xattrs() { ar.set_unpack_xattrs(false); t!(ar.unpack(td.path())); - assert_eq!(xattr::get(td.path().join("a/b"), "user.pax.flags").unwrap(), None); + assert_eq!( + xattr::get(td.path().join("a/b"), "user.pax.flags").unwrap(), + None + ); } #[test] @@ -256,11 +263,19 @@ fn writing_directories_recursively() { let base_dir = td.path().join("foobar"); assert!(fs::metadata(&base_dir).map(|m| m.is_dir()).unwrap_or(false)); let file1_path = base_dir.join("file1"); - assert!(fs::metadata(&file1_path).map(|m| m.is_file()).unwrap_or(false)); + assert!( + fs::metadata(&file1_path) + .map(|m| m.is_file()) + .unwrap_or(false) + ); let sub_dir = base_dir.join("sub"); assert!(fs::metadata(&sub_dir).map(|m| m.is_dir()).unwrap_or(false)); let file2_path = sub_dir.join("file2"); - assert!(fs::metadata(&file2_path).map(|m| m.is_file()).unwrap_or(false)); + assert!( + fs::metadata(&file2_path) + .map(|m| m.is_file()) + .unwrap_or(false) + ); } #[test] @@ -283,11 +298,19 @@ fn append_dir_all_blank_dest() { let base_dir = td.path(); assert!(fs::metadata(&base_dir).map(|m| m.is_dir()).unwrap_or(false)); let file1_path = base_dir.join("file1"); - assert!(fs::metadata(&file1_path).map(|m| m.is_file()).unwrap_or(false)); + assert!( + fs::metadata(&file1_path) + .map(|m| m.is_file()) + .unwrap_or(false) + ); let sub_dir = base_dir.join("sub"); assert!(fs::metadata(&sub_dir).map(|m| m.is_dir()).unwrap_or(false)); let file2_path = sub_dir.join("file2"); - assert!(fs::metadata(&file2_path).map(|m| m.is_file()).unwrap_or(false)); + assert!( + fs::metadata(&file2_path) + .map(|m| m.is_file()) + .unwrap_or(false) + ); } #[test] @@ -349,8 +372,7 @@ fn extracting_malicious_tarball() { let mut a = Builder::new(&mut evil_tar); let mut append = |path: &str| { let mut header = Header::new_gnu(); - assert!(header.set_path(path).is_err(), - "was ok: {:?}", path); + assert!(header.set_path(path).is_err(), "was ok: {:?}", path); { let h = header.as_gnu_mut().unwrap(); for (a, b) in h.name.iter_mut().zip(path.as_bytes()) { @@ -401,20 +423,41 @@ fn extracting_malicious_tarball() { // The `tmp` subdirectory should be created and within this // subdirectory, there should be files named `abs_evil.txt` through // `abs_evil6.txt`. - assert!(fs::metadata(td.path().join("tmp")).map(|m| m.is_dir()) - .unwrap_or(false)); - assert!(fs::metadata(td.path().join("tmp/abs_evil.txt")) - .map(|m| m.is_file()).unwrap_or(false)); - assert!(fs::metadata(td.path().join("tmp/abs_evil2.txt")) - .map(|m| m.is_file()).unwrap_or(false)); - assert!(fs::metadata(td.path().join("tmp/abs_evil3.txt")) - .map(|m| m.is_file()).unwrap_or(false)); - assert!(fs::metadata(td.path().join("tmp/abs_evil4.txt")) - .map(|m| m.is_file()).unwrap_or(false)); - assert!(fs::metadata(td.path().join("tmp/abs_evil5.txt")) - .map(|m| m.is_file()).unwrap_or(false)); - assert!(fs::metadata(td.path().join("tmp/abs_evil6.txt")) - .map(|m| m.is_file()).unwrap_or(false)); + assert!( + fs::metadata(td.path().join("tmp")) + .map(|m| m.is_dir()) + .unwrap_or(false) + ); + assert!( + fs::metadata(td.path().join("tmp/abs_evil.txt")) + .map(|m| m.is_file()) + .unwrap_or(false) + ); + assert!( + fs::metadata(td.path().join("tmp/abs_evil2.txt")) + .map(|m| m.is_file()) + .unwrap_or(false) + ); + assert!( + fs::metadata(td.path().join("tmp/abs_evil3.txt")) + .map(|m| m.is_file()) + .unwrap_or(false) + ); + assert!( + fs::metadata(td.path().join("tmp/abs_evil4.txt")) + .map(|m| m.is_file()) + .unwrap_or(false) + ); + assert!( + fs::metadata(td.path().join("tmp/abs_evil5.txt")) + .map(|m| m.is_file()) + .unwrap_or(false) + ); + assert!( + fs::metadata(td.path().join("tmp/abs_evil6.txt")) + .map(|m| m.is_file()) + .unwrap_or(false) + ); } #[test] @@ -455,8 +498,7 @@ fn extracting_malformed_tar_null_blocks() { } #[test] -fn empty_filename() -{ +fn empty_filename() { let td = t!(TempDir::new("tar-rs")); let rdr = Cursor::new(tar!("empty_filename.tar")); let mut ar = Archive::new(rdr); @@ -516,8 +558,8 @@ fn backslash_treated_well() { #[cfg(unix)] #[test] fn nul_bytes_in_path() { - use std::os::unix::prelude::*; use std::ffi::OsStr; + use std::os::unix::prelude::*; let nul_path = OsStr::from_bytes(b"foo\0"); let td = t!(TempDir::new("tar-rs")); @@ -531,8 +573,10 @@ fn links() { let mut ar = Archive::new(Cursor::new(tar!("link.tar"))); let mut entries = t!(ar.entries()); let link = t!(entries.next().unwrap()); - assert_eq!(t!(link.header().link_name()).as_ref().map(|p| &**p), - Some(Path::new("file"))); + assert_eq!( + t!(link.header().link_name()).as_ref().map(|p| &**p), + Some(Path::new("file")) + ); let other = t!(entries.next().unwrap()); assert!(t!(other.header().link_name()).is_none()); } @@ -546,8 +590,10 @@ fn unpack_links() { let md = t!(fs::symlink_metadata(td.path().join("lnk"))); assert!(md.file_type().is_symlink()); - assert_eq!(&*t!(fs::read_link(td.path().join("lnk"))), - Path::new("file")); + assert_eq!( + &*t!(fs::read_link(td.path().join("lnk"))), + Path::new("file") + ); t!(File::open(td.path().join("lnk"))); } @@ -678,27 +724,27 @@ fn reading_sparse() { assert_eq!(&*a.header().path_bytes(), b"sparse_ext.txt"); t!(a.read_to_string(&mut s)); assert!(s[..0x1000].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0x1000..0x1000+5], "text\n"); - assert!(s[0x1000+5..0x3000].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0x3000..0x3000+5], "text\n"); - assert!(s[0x3000+5..0x5000].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0x5000..0x5000+5], "text\n"); - assert!(s[0x5000+5..0x7000].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0x7000..0x7000+5], "text\n"); - assert!(s[0x7000+5..0x9000].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0x9000..0x9000+5], "text\n"); - assert!(s[0x9000+5..0xb000].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0xb000..0xb000+5], "text\n"); + assert_eq!(&s[0x1000..0x1000 + 5], "text\n"); + assert!(s[0x1000 + 5..0x3000].chars().all(|x| x == '\u{0}')); + assert_eq!(&s[0x3000..0x3000 + 5], "text\n"); + assert!(s[0x3000 + 5..0x5000].chars().all(|x| x == '\u{0}')); + assert_eq!(&s[0x5000..0x5000 + 5], "text\n"); + assert!(s[0x5000 + 5..0x7000].chars().all(|x| x == '\u{0}')); + assert_eq!(&s[0x7000..0x7000 + 5], "text\n"); + assert!(s[0x7000 + 5..0x9000].chars().all(|x| x == '\u{0}')); + assert_eq!(&s[0x9000..0x9000 + 5], "text\n"); + assert!(s[0x9000 + 5..0xb000].chars().all(|x| x == '\u{0}')); + assert_eq!(&s[0xb000..0xb000 + 5], "text\n"); let mut a = t!(entries.next().unwrap()); let mut s = String::new(); assert_eq!(&*a.header().path_bytes(), b"sparse.txt"); t!(a.read_to_string(&mut s)); assert!(s[..0x1000].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0x1000..0x1000+6], "hello\n"); - assert!(s[0x1000+6..0x2fa0].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0x2fa0..0x2fa0+6], "world\n"); - assert!(s[0x2fa0+6..0x4000].chars().all(|x| x == '\u{0}')); + assert_eq!(&s[0x1000..0x1000 + 6], "hello\n"); + assert!(s[0x1000 + 6..0x2fa0].chars().all(|x| x == '\u{0}')); + assert_eq!(&s[0x2fa0..0x2fa0 + 6], "world\n"); + assert!(s[0x2fa0 + 6..0x4000].chars().all(|x| x == '\u{0}')); assert!(entries.next().is_none()); } @@ -723,25 +769,25 @@ fn extract_sparse() { s.truncate(0); t!(t!(File::open(td.path().join("sparse_ext.txt"))).read_to_string(&mut s)); assert!(s[..0x1000].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0x1000..0x1000+5], "text\n"); - assert!(s[0x1000+5..0x3000].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0x3000..0x3000+5], "text\n"); - assert!(s[0x3000+5..0x5000].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0x5000..0x5000+5], "text\n"); - assert!(s[0x5000+5..0x7000].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0x7000..0x7000+5], "text\n"); - assert!(s[0x7000+5..0x9000].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0x9000..0x9000+5], "text\n"); - assert!(s[0x9000+5..0xb000].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0xb000..0xb000+5], "text\n"); + assert_eq!(&s[0x1000..0x1000 + 5], "text\n"); + assert!(s[0x1000 + 5..0x3000].chars().all(|x| x == '\u{0}')); + assert_eq!(&s[0x3000..0x3000 + 5], "text\n"); + assert!(s[0x3000 + 5..0x5000].chars().all(|x| x == '\u{0}')); + assert_eq!(&s[0x5000..0x5000 + 5], "text\n"); + assert!(s[0x5000 + 5..0x7000].chars().all(|x| x == '\u{0}')); + assert_eq!(&s[0x7000..0x7000 + 5], "text\n"); + assert!(s[0x7000 + 5..0x9000].chars().all(|x| x == '\u{0}')); + assert_eq!(&s[0x9000..0x9000 + 5], "text\n"); + assert!(s[0x9000 + 5..0xb000].chars().all(|x| x == '\u{0}')); + assert_eq!(&s[0xb000..0xb000 + 5], "text\n"); s.truncate(0); t!(t!(File::open(td.path().join("sparse.txt"))).read_to_string(&mut s)); assert!(s[..0x1000].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0x1000..0x1000+6], "hello\n"); - assert!(s[0x1000+6..0x2fa0].chars().all(|x| x == '\u{0}')); - assert_eq!(&s[0x2fa0..0x2fa0+6], "world\n"); - assert!(s[0x2fa0+6..0x4000].chars().all(|x| x == '\u{0}')); + assert_eq!(&s[0x1000..0x1000 + 6], "hello\n"); + assert!(s[0x1000 + 6..0x2fa0].chars().all(|x| x == '\u{0}')); + assert_eq!(&s[0x2fa0..0x2fa0 + 6], "world\n"); + assert!(s[0x2fa0 + 6..0x4000].chars().all(|x| x == '\u{0}')); } #[test] @@ -789,9 +835,9 @@ fn path_separators() { #[test] #[cfg(unix)] fn append_path_symlink() { - use std::os::unix::fs::symlink; - use std::env; use std::borrow::Cow; + use std::env; + use std::os::unix::fs::symlink; let mut ar = Builder::new(Vec::new()); ar.follow_symlinks(false); @@ -807,7 +853,10 @@ fn append_path_symlink() { let entry = t!(entries.next().unwrap()); assert_eq!(t!(entry.path()), Path::new("test")); - assert_eq!(t!(entry.link_name()), Some(Cow::from(Path::new("testdest")))); + assert_eq!( + t!(entry.link_name()), + Some(Cow::from(Path::new("testdest"))) + ); assert_eq!(t!(entry.header().size()), 0); assert!(entries.next().is_none()); diff --git a/tests/entry.rs b/tests/entry.rs index f0e04572..2cba1bf6 100644 --- a/tests/entry.rs +++ b/tests/entry.rs @@ -7,10 +7,12 @@ use std::io::Read; use tempdir::TempDir; macro_rules! t { - ($e:expr) => (match $e { - Ok(v) => v, - Err(e) => panic!("{} returned {}", stringify!($e), e), - }) + ($e:expr) => { + match $e { + Ok(v) => v, + Err(e) => panic!("{} returned {}", stringify!($e), e), + } + }; } #[test] diff --git a/tests/header/mod.rs b/tests/header/mod.rs index ba44581c..6f4b735f 100644 --- a/tests/header/mod.rs +++ b/tests/header/mod.rs @@ -5,7 +5,7 @@ use std::{iter, mem, thread, time}; use tempdir::TempDir; -use tar::{Header, HeaderMode, GnuHeader}; +use tar::{GnuHeader, Header, HeaderMode}; #[test] fn default_gnu() { @@ -172,14 +172,14 @@ fn set_metadata_deterministic() { let tmppath = td.path().join("tmpfile"); fn mk_header(path: &Path, readonly: bool) -> Result { - let mut file = t!(File::create(path)); - t!(file.write_all(b"c")); - let mut perms = t!(file.metadata()).permissions(); - perms.set_readonly(readonly); - t!(fs::set_permissions(path, perms)); - let mut h = Header::new_ustar(); - h.set_metadata_in_mode(&t!(path.metadata()), HeaderMode::Deterministic); - Ok(h) + let mut file = t!(File::create(path)); + t!(file.write_all(b"c")); + let mut perms = t!(file.metadata()).permissions(); + perms.set_readonly(readonly); + t!(fs::set_permissions(path, perms)); + let mut h = Header::new_ustar(); + h.set_metadata_in_mode(&t!(path.metadata()), HeaderMode::Deterministic); + Ok(h) } // Create "the same" File twice in a row, one second apart, with differing readonly values. @@ -221,7 +221,9 @@ fn extended_numeric_format() { h.uid = [0x80, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78]; assert_eq!(h.as_header().uid().unwrap(), 0x12345678); - h.mtime = [0x80, 0, 0, 0, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]; + h.mtime = [ + 0x80, 0, 0, 0, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + ]; assert_eq!(h.as_header().mtime().unwrap(), 0x0123456789abcdef); }