From 78e6f4c5048595fd6b2175a6cdd32f03b20ae7fc Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Fri, 3 May 2024 19:52:15 +0200 Subject: [PATCH] header: improve file structure --- src/header.rs | 118 +++++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/src/header.rs b/src/header.rs index ef7340c..9d2d5de 100644 --- a/src/header.rs +++ b/src/header.rs @@ -60,65 +60,6 @@ impl Debug for Mode { } } -/// Header of the TAR format as specified by POSIX (POSIX 1003.1-1990. -/// "New" (version?) GNU Tar versions use this archive format by default. -/// (). -/// -/// Each file is started by such a header, that describes the size and -/// the file name. After that, the file content stands in chunks of 512 bytes. -/// The number of bytes can be derived from the file size. -/// -/// This is also mostly compatible with the "Ustar"-header and the "GNU format". -/// Because this library only needs to fetch data and filename, we don't need -/// further checks. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -#[repr(C, packed)] -pub struct PosixHeader { - pub name: TarFormatString, - pub mode: Mode, - pub uid: TarFormatOctal<8>, - pub gid: TarFormatOctal<8>, - // confusing; size is stored as ASCII string - pub size: TarFormatOctal<12>, - pub mtime: TarFormatDecimal<12>, - pub cksum: TarFormatOctal<8>, - pub typeflag: TypeFlagRaw, - /// Name. There is always a null byte, therefore - /// the max len is 99. - pub linkname: TarFormatString, - pub magic: TarFormatString<6>, - pub version: TarFormatString<2>, - /// Username. There is always a null byte, therefore - /// the max len is N-1. - pub uname: TarFormatString<32>, - /// Groupname. There is always a null byte, therefore - /// the max len is N-1. - pub gname: TarFormatString<32>, - pub dev_major: TarFormatOctal<8>, - pub dev_minor: TarFormatOctal<8>, - pub prefix: TarFormatString, - // padding => to BLOCKSIZE bytes - pub _pad: [u8; 12], -} - -impl PosixHeader { - /// Returns the number of blocks that are required to read the whole file - /// content. Returns an error, if the file size can't be parsed from the - /// header. - pub fn payload_block_count(&self) -> Result { - let parsed_size = self.size.as_number::()?; - Ok(parsed_size.div_ceil(BLOCKSIZE)) - } - - /// A Tar archive is terminated, if an end-of-archive entry, which consists - /// of two 512 blocks of zero bytes, is found. - pub fn is_zero_block(&self) -> bool { - let ptr = self as *const Self as *const u8; - let self_bytes = unsafe { core::slice::from_raw_parts(ptr, BLOCKSIZE) }; - self_bytes.iter().filter(|x| **x == 0).count() == BLOCKSIZE - } -} - #[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq)] pub struct InvalidTypeFlagError(u8); @@ -264,6 +205,65 @@ bitflags::bitflags! { } } +/// Header of the TAR format as specified by POSIX (POSIX 1003.1-1990. +/// "New" (version?) GNU Tar versions use this archive format by default. +/// (). +/// +/// Each file is started by such a header, that describes the size and +/// the file name. After that, the file content stands in chunks of 512 bytes. +/// The number of bytes can be derived from the file size. +/// +/// This is also mostly compatible with the "Ustar"-header and the "GNU format". +/// Because this library only needs to fetch data and filename, we don't need +/// further checks. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[repr(C, packed)] +pub struct PosixHeader { + pub name: TarFormatString, + pub mode: Mode, + pub uid: TarFormatOctal<8>, + pub gid: TarFormatOctal<8>, + // confusing; size is stored as ASCII string + pub size: TarFormatOctal<12>, + pub mtime: TarFormatDecimal<12>, + pub cksum: TarFormatOctal<8>, + pub typeflag: TypeFlagRaw, + /// Name. There is always a null byte, therefore + /// the max len is 99. + pub linkname: TarFormatString, + pub magic: TarFormatString<6>, + pub version: TarFormatString<2>, + /// Username. There is always a null byte, therefore + /// the max len is N-1. + pub uname: TarFormatString<32>, + /// Groupname. There is always a null byte, therefore + /// the max len is N-1. + pub gname: TarFormatString<32>, + pub dev_major: TarFormatOctal<8>, + pub dev_minor: TarFormatOctal<8>, + pub prefix: TarFormatString, + // padding => to BLOCKSIZE bytes + pub _pad: [u8; 12], +} + +impl PosixHeader { + /// Returns the number of blocks that are required to read the whole file + /// content. Returns an error, if the file size can't be parsed from the + /// header. + pub fn payload_block_count(&self) -> Result { + let parsed_size = self.size.as_number::()?; + Ok(parsed_size.div_ceil(BLOCKSIZE)) + } + + /// A Tar archive is terminated, if an end-of-archive entry, which consists + /// of two 512 blocks of zero bytes, is found. + pub fn is_zero_block(&self) -> bool { + let ptr = self as *const Self as *const u8; + let self_bytes = unsafe { core::slice::from_raw_parts(ptr, BLOCKSIZE) }; + self_bytes.iter().filter(|x| **x == 0).count() == BLOCKSIZE + } +} + #[cfg(test)] mod tests { use crate::header::{PosixHeader, TypeFlag};