Use crates for cpio code

This commit is contained in:
topjohnwu 2023-09-22 01:39:21 -07:00
parent 46275b90c2
commit b28326198c
3 changed files with 34 additions and 25 deletions

2
native/src/Cargo.lock generated
View File

@ -462,12 +462,14 @@ version = "0.0.0"
dependencies = [ dependencies = [
"argh", "argh",
"base", "base",
"bytemuck",
"byteorder", "byteorder",
"cxx", "cxx",
"cxx-gen", "cxx-gen",
"der", "der",
"digest", "digest",
"fdt", "fdt",
"num-traits",
"p256", "p256",
"p384", "p384",
"pb-rs", "pb-rs",

View File

@ -27,3 +27,5 @@ rsa = { workspace = true, features = ["sha2"] }
x509-cert = { workspace = true } x509-cert = { workspace = true }
der = { workspace = true, features = ["derive"] } der = { workspace = true, features = ["derive"] }
fdt = { workspace = true } fdt = { workspace = true }
bytemuck = { workspace = true, features = ["derive", "min_const_generics"] }
num-traits = { workspace = true }

View File

@ -1,7 +1,6 @@
#![allow(clippy::useless_conversion)] #![allow(clippy::useless_conversion)]
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::ffi::CStr;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::fs::{metadata, read, DirBuilder, File}; use std::fs::{metadata, read, DirBuilder, File};
use std::io::Write; use std::io::Write;
@ -9,8 +8,11 @@ use std::mem::size_of;
use std::os::unix::fs::{symlink, DirBuilderExt, FileTypeExt, MetadataExt}; use std::os::unix::fs::{symlink, DirBuilderExt, FileTypeExt, MetadataExt};
use std::path::Path; use std::path::Path;
use std::process::exit; use std::process::exit;
use std::str;
use argh::FromArgs; use argh::FromArgs;
use bytemuck::{from_bytes, Pod, Zeroable};
use num_traits::cast::AsPrimitive;
use size::{Base, Size, Style}; use size::{Base, Size, Style};
use base::libc::{ use base::libc::{
@ -183,6 +185,7 @@ Supported commands:
) )
} }
#[derive(Copy, Clone, Pod, Zeroable)]
#[repr(C, packed)] #[repr(C, packed)]
struct CpioHeader { struct CpioHeader {
magic: [u8; 6], magic: [u8; 6],
@ -223,17 +226,17 @@ impl Cpio {
fn load_from_data(data: &[u8]) -> LoggedResult<Self> { fn load_from_data(data: &[u8]) -> LoggedResult<Self> {
let mut cpio = Cpio::new(); let mut cpio = Cpio::new();
let mut pos = 0usize; let mut pos = 0_usize;
while pos < data.len() { while pos < data.len() {
let hdr = unsafe { &*(data.as_ptr().add(pos) as *const CpioHeader) }; let hdr_sz = size_of::<CpioHeader>();
let hdr = from_bytes::<CpioHeader>(&data[pos..(pos + hdr_sz)]);
if &hdr.magic != b"070701" { if &hdr.magic != b"070701" {
return Err(log_err!("invalid cpio magic")); return Err(log_err!("invalid cpio magic"));
} }
pos += size_of::<CpioHeader>(); pos += hdr_sz;
let name = CStr::from_bytes_until_nul(&data[pos..])? let name_sz = x8u(&hdr.namesize)? as usize;
.to_str()? let name = Utf8CStr::from_bytes(&data[pos..(pos + name_sz)])?.to_string();
.to_string(); pos += name_sz;
pos += x8u::<usize>(&hdr.namesize)?;
pos = align_4(pos); pos = align_4(pos);
if name == "." || name == ".." { if name == "." || name == ".." {
continue; continue;
@ -245,16 +248,16 @@ impl Cpio {
} }
continue; continue;
} }
let file_size = x8u::<usize>(&hdr.filesize)?; let file_sz = x8u(&hdr.filesize)? as usize;
let entry = Box::new(CpioEntry { let entry = Box::new(CpioEntry {
mode: x8u(&hdr.mode)?, mode: x8u(&hdr.mode)?.as_(),
uid: x8u(&hdr.uid)?, uid: x8u(&hdr.uid)?.as_(),
gid: x8u(&hdr.gid)?, gid: x8u(&hdr.gid)?.as_(),
rdevmajor: x8u(&hdr.rdevmajor)?, rdevmajor: x8u(&hdr.rdevmajor)?.as_(),
rdevminor: x8u(&hdr.rdevminor)?, rdevminor: x8u(&hdr.rdevminor)?.as_(),
data: data[pos..pos + file_size].to_vec(), data: data[pos..(pos + file_sz)].to_vec(),
}); });
pos += file_size; pos += file_sz;
cpio.entries.insert(name, entry); cpio.entries.insert(name, entry);
pos = align_4(pos); pos = align_4(pos);
} }
@ -352,7 +355,7 @@ impl Cpio {
file.write_all(&entry.data)?; file.write_all(&entry.data)?;
} }
S_IFLNK => { S_IFLNK => {
symlink(Path::new(&std::str::from_utf8(entry.data.as_slice())?), out)?; symlink(Path::new(&str::from_utf8(entry.data.as_slice())?), out)?;
} }
S_IFBLK | S_IFCHR => { S_IFBLK | S_IFCHR => {
let dev = makedev(entry.rdevmajor.try_into()?, entry.rdevminor.try_into()?); let dev = makedev(entry.rdevmajor.try_into()?, entry.rdevminor.try_into()?);
@ -600,15 +603,14 @@ pub fn cpio_commands(argc: i32, argv: *const *const c_char) -> bool {
.is_ok() .is_ok()
} }
fn x8u<U: TryFrom<u32>>(x: &[u8; 8]) -> LoggedResult<U> { fn x8u(x: &[u8; 8]) -> LoggedResult<u32> {
// parse hex // parse hex
let mut ret = 0u32; let mut ret = 0u32;
for i in x { let s = str::from_utf8(x).log_with_msg(|w| w.write_str("bad cpio header"))?;
let c = *i as char; for c in s.chars() {
let v = c.to_digit(16).ok_or_else(|| log_err!("bad cpio header"))?; ret = ret * 16 + c.to_digit(16).ok_or_else(|| log_err!("bad cpio header"))?;
ret = ret * 16 + v;
} }
ret.try_into().map_err(|_| log_err!("bad cpio header")) Ok(ret)
} }
#[inline(always)] #[inline(always)]
@ -618,8 +620,11 @@ fn align_4(x: usize) -> usize {
#[inline(always)] #[inline(always)]
fn norm_path(path: &str) -> String { fn norm_path(path: &str) -> String {
let path = path.strip_prefix('/').unwrap_or(path); path.strip_prefix('/')
path.strip_suffix('/').unwrap_or(path).to_string() .unwrap_or(path)
.strip_suffix('/')
.unwrap_or(path)
.to_string()
} }
fn parse_mode(s: &str) -> Result<mode_t, String> { fn parse_mode(s: &str) -> Result<mode_t, String> {