basic_tar/header/
mod.rs

1pub mod raw;
2
3use crate::{
4	BasicTarError,
5	header::raw::{ StringExt, U64Ext, Checksum }
6};
7
8
9/// A tar header
10#[derive(Default, Debug, Clone, Eq, PartialEq)]
11pub struct Header {
12	/// The record's path and name
13	pub path: String,
14	/// The record's access mode bits (e.g. 0o777)
15	pub mode: Option<u64>,
16	/// The record's UID
17	pub uid: Option<u64>,
18	/// The record's GID
19	pub gid: Option<u64>,
20	/// The record's size
21	pub size: u64,
22	/// The record's modification time
23	pub mtime: Option<u64>,
24	/// The record's type
25	pub typeflag: u8,
26	/// The record's link name
27	pub linkname: Option<String>
28}
29impl Header {
30	/// Parses a raw byte block into a classic tar header
31	pub fn parse(data: raw::header::Raw) -> Result<Self, BasicTarError> {
32		// Check if we have an empty header
33		if data.as_ref() == raw::header::raw().as_ref() {
34			Err(BasicTarError::EmptyHeader)?
35		}
36		
37		// Parse the basic tar header and verify the checksum
38		let tar = raw::header::Header::from(data);
39		Checksum::verify(&tar)?;
40		
41		// Decode the path
42		let path = String::from_field(&tar.name)?;
43		
44		// Decode the mode, UID and GID
45		let mode = Option::from_octal_field(&tar.mode)?;
46		let uid = Option::from_octal_field(&tar.uid)?;
47		let gid = Option::from_octal_field(&tar.gid)?;
48		
49		// Decode the size and the modification time
50		let size = u64::from_octal_field(&tar.size)?;
51		let mtime = Option::from_octal_field(&tar.mtime)?;
52		
53		// Decode link name and create the struct
54		let linkname = Option::from_field(&tar.linkname)?;
55		Ok(Self{ path, mode, uid, gid, size, typeflag: tar.typeflag[0], mtime, linkname })
56	}
57	
58	/// Serializes the tar header into a raw byte block
59	///
60	/// _Note: this function can fail because the struct may contain values that cannot be
61	/// serialized, e.g. a name longer than 100 bytes or a size greater than 8 GiB_
62	pub fn serialize(self) -> Result<raw::header::Raw, BasicTarError> {
63		// Create and populate the header
64		let mut tar = raw::header::header();
65		self.path.into_field(&mut tar.name)?;
66		
67		self.mode.into_octal_field(&mut tar.mode)?;
68		self.uid.into_octal_field(&mut tar.uid)?;
69		self.gid.into_octal_field(&mut tar.gid)?;
70		
71		self.size.into_octal_field(&mut tar.size)?;
72		self.mtime.into_octal_field(&mut tar.mtime)?;
73		
74		tar.typeflag[0] = self.typeflag;
75		self.linkname.into_field(&mut tar.linkname)?;
76		
77		// Write the checksum and return the header
78		Checksum::write(&mut tar);
79		Ok(tar.into())
80	}
81}