|
3 | 3 | // For the full copyright and license information, please view the LICENSE |
4 | 4 | // file that was distributed with this source code. |
5 | 5 |
|
| 6 | +use crate::display; |
6 | 7 | use crate::errors::TarError; |
7 | | -use chrono::{TimeZone, Utc}; |
8 | 8 | use std::fs::File; |
9 | 9 | use std::io::{self, BufWriter, Write}; |
10 | 10 | use std::path::Path; |
11 | 11 | use tar::Archive; |
12 | 12 | use uucore::error::UResult; |
13 | | -use uucore::fs::display_permissions_unix; |
14 | 13 |
|
15 | 14 | /// List the contents of a tar archive, printing one entry per line. |
16 | | -pub fn list_archive(archive_path: &Path, verbose: bool) -> UResult<()> { |
| 15 | +pub fn list_archive(archive_path: &Path, verbose: u8) -> UResult<()> { |
17 | 16 | let file: File = |
18 | 17 | File::open(archive_path).map_err(|e| TarError::from_io_error(e, archive_path))?; |
19 | 18 | let mut archive = Archive::new(file); |
20 | 19 | let mut out = BufWriter::new(io::stdout().lock()); |
21 | 20 |
|
22 | 21 | for entry_result in archive.entries().map_err(TarError::CannotReadEntries)? { |
23 | 22 | let entry = entry_result.map_err(TarError::CannotReadEntry)?; |
| 23 | + let path = entry.path().map_err(TarError::CannotReadEntryPath)?; |
24 | 24 |
|
25 | | - if verbose { |
26 | | - // Collect all header fields into owned values before borrowing entry for the path, |
27 | | - // since both header() and path() require a borrow of entry. |
28 | | - let (mode, entry_type, owner, group, size, mtime) = { |
29 | | - let header = entry.header(); |
30 | | - ( |
31 | | - header.mode().unwrap_or(0), |
32 | | - header.entry_type(), |
33 | | - header |
34 | | - .username() |
35 | | - .ok() |
36 | | - .flatten() |
37 | | - .unwrap_or_default() |
38 | | - .to_owned(), |
39 | | - header |
40 | | - .groupname() |
41 | | - .ok() |
42 | | - .flatten() |
43 | | - .unwrap_or_default() |
44 | | - .to_owned(), |
45 | | - header.size().unwrap_or(0), |
46 | | - header.mtime().unwrap_or(0), |
47 | | - ) |
48 | | - }; |
49 | | - |
50 | | - let path = entry.path().map_err(TarError::CannotReadEntryPath)?; |
51 | | - |
52 | | - let type_char = match entry_type { |
53 | | - tar::EntryType::Directory => 'd', |
54 | | - tar::EntryType::Symlink => 'l', |
55 | | - tar::EntryType::Char => 'c', |
56 | | - tar::EntryType::Block => 'b', |
57 | | - tar::EntryType::Fifo => 'p', |
58 | | - _ => '-', |
59 | | - }; |
60 | | - // Tar headers store the type separately from the mode bits, so we get the |
61 | | - // 9-character rwx string from uucore and prepend our own type character. |
62 | | - let perm_str = display_permissions_unix(mode, false); |
63 | | - let permissions = format!("{type_char}{perm_str}"); |
64 | | - |
65 | | - // TODO: GNU tar displays mtime in the user's local timezone; we |
66 | | - // currently format in UTC. Convert to local time for compatibility. |
67 | | - let dt: chrono::DateTime<Utc> = Utc |
68 | | - .timestamp_opt(mtime as i64, 0) |
69 | | - .single() |
70 | | - .unwrap_or_else(Utc::now); |
71 | | - let date_str = dt.format("%Y-%m-%d %H:%M"); |
72 | | - |
73 | | - writeln!( |
74 | | - out, |
75 | | - "{permissions} {owner}/{group} {size:>8} {date_str} {}", |
76 | | - path.display() |
77 | | - ) |
78 | | - .map_err(TarError::Io)?; |
| 25 | + if verbose >= 1 { |
| 26 | + display::print_entry_verbose(&mut out, entry.header(), &path).map_err(TarError::Io)?; |
79 | 27 | } else { |
80 | | - let path = entry.path().map_err(TarError::CannotReadEntryPath)?; |
81 | | - |
82 | 28 | writeln!(out, "{}", path.display()).map_err(TarError::Io)?; |
83 | 29 | } |
84 | 30 | } |
|
0 commit comments