diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 79083a0..94a25f7 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,8 +2,5 @@ - - - \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 5d2f1b6..0d8dcc3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,12 +44,52 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cpuid-bool" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" + +[[package]] +name = "crc32fast" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "failure" version = "0.1.8" @@ -72,12 +112,40 @@ dependencies = [ "synstructure", ] +[[package]] +name = "flate2" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide", +] + +[[package]] +name = "generic-array" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "gimli" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" +[[package]] +name = "keccak" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" + [[package]] name = "libc" version = "0.2.90" @@ -90,7 +158,10 @@ version = "0.0.2-placeholder" dependencies = [ "failure", "maplit", + "object", "regex", + "sha2", + "sha3", ] [[package]] @@ -120,6 +191,16 @@ name = "object" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" +dependencies = [ + "flate2", + "wasmparser", +] + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "pkg6depotd" @@ -174,6 +255,31 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" +[[package]] +name = "sha2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de" +dependencies = [ + "block-buffer", + "cfg-if", + "cpuid-bool", + "digest", + "opaque-debug", +] + +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer", + "digest", + "keccak", + "opaque-debug", +] + [[package]] name = "syn" version = "1.0.64" @@ -197,8 +303,26 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "typenum" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" + [[package]] name = "unicode-xid" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "version_check" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" + +[[package]] +name = "wasmparser" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32fddd575d477c6e9702484139cf9f23dcd554b06d185ed0f56c857dd3a47aa6" diff --git a/libips/Cargo.toml b/libips/Cargo.toml index 06d4314..6d64750 100644 --- a/libips/Cargo.toml +++ b/libips/Cargo.toml @@ -18,4 +18,7 @@ keywords = ["packaging", "illumos"] [dependencies] regex = "1.3.7" failure = "0.1.8" -maplit = "0.1.6" \ No newline at end of file +maplit = "0.1.6" +object = "0.23.0" +sha2 = "0.9.3" +sha3 = "0.9.1" \ No newline at end of file diff --git a/libips/src/actions/mod.rs b/libips/src/actions/mod.rs index f867530..fc78623 100644 --- a/libips/src/actions/mod.rs +++ b/libips/src/actions/mod.rs @@ -15,8 +15,9 @@ use crate::payload::Payload; use std::clone::Clone; use crate::digest::Digest; use std::str::FromStr; +use std::path::{Path, PathBuf}; -trait FacetedAction { +pub trait FacetedAction { // Add a facet to the action if the facet is already present the function returns false. fn add_facet(&mut self, facet: Facet) -> bool; @@ -33,7 +34,7 @@ pub struct Action { } impl Action { - fn new(kind: ActionKind) -> Action{ + pub fn new(kind: ActionKind) -> Action{ Action{ kind, payload: Payload::default(), @@ -90,6 +91,21 @@ pub struct File { pub facets: HashSet, } +impl File { + pub fn read_from_path(p: &Path) -> Result { + let mut f = File::default(); + f.payload = Payload::compute_payload(p)?; + match p.to_str() { + Some(str) => f.path = str.to_string(), + None => return Err(FileError::FilePathIsNoStringError)?, + } + + //TODO group owner mode + + Ok(f) + } +} + impl FacetedAction for File { fn add_facet(&mut self, facet: Facet) -> bool { return self.facets.insert(facet) @@ -100,6 +116,12 @@ impl FacetedAction for File { } } +#[derive(Debug, Fail)] +pub enum FileError { + #[fail(display = "file path is not a string")] + FilePathIsNoStringError, +} + //TODO implement multiple FMRI for require-any #[derive(Debug, Default)] pub struct Dependency { @@ -157,10 +179,14 @@ impl Manifest { dependencies: Vec::new(), }; } + + pub fn add_file(&mut self, f: File) { + self.files.push(f); + } } #[derive(Debug)] -enum ActionKind { +pub enum ActionKind { Attr, Dir, File, diff --git a/libips/src/digest/mod.rs b/libips/src/digest/mod.rs index bcd7ad7..92b3327 100644 --- a/libips/src/digest/mod.rs +++ b/libips/src/digest/mod.rs @@ -4,6 +4,10 @@ // obtain one at https://mozilla.org/MPL/2.0/. use std::str::FromStr; +use sha2::{Digest as Sha2Digest}; +use sha3::{Digest as Sha3Digest}; + +static DEFAULT_ALGORITHM: DigestAlgorithm = DigestAlgorithm::SHA512; #[derive(Debug, PartialEq)] pub enum DigestAlgorithm { @@ -85,6 +89,35 @@ impl FromStr for Digest { } } +impl Digest { + pub fn from_bytes(b: &[u8], algo: DigestAlgorithm, src: DigestSource) -> Result { + let hash = match algo { + DigestAlgorithm::SHA256=> { + format!("{:x}", sha2::Sha256::digest(b)) + } + DigestAlgorithm::SHA512Half => { + format!("{:x}", sha2::Sha512Trunc256::digest(b)) + } + DigestAlgorithm::SHA512 => { + format!("{:x}", sha2::Sha512::digest(b)) + } + DigestAlgorithm::SHA3512Half | DigestAlgorithm::SHA3256 => { + format!("{:x}", sha3::Sha3_256::digest(b)) + } + DigestAlgorithm::SHA3512 | _ => { + format!("{:x}", sha3::Sha3_512::digest(b)) + } + }; + + + Ok(Digest{ + source: src, + algorithm: algo, + hash, + }) + } +} + #[derive(Debug, Fail)] pub enum DigestError { #[fail(display = "hashing algorithm {} is not known by this library", algorithm)] diff --git a/libips/src/lib.rs b/libips/src/lib.rs index eeef24a..e5ec93e 100644 --- a/libips/src/lib.rs +++ b/libips/src/lib.rs @@ -3,9 +3,9 @@ // MPL was not distributed with this file, You can // obtain one at https://mozilla.org/MPL/2.0/. -mod actions; -mod digest; -mod payload; +pub mod actions; +pub mod digest; +pub mod payload; #[macro_use] extern crate failure; #[macro_use] extern crate maplit; diff --git a/libips/src/payload/mod.rs b/libips/src/payload/mod.rs index b150e2d..77ab258 100644 --- a/libips/src/payload/mod.rs +++ b/libips/src/payload/mod.rs @@ -3,19 +3,22 @@ // MPL was not distributed with this file, You can // obtain one at https://mozilla.org/MPL/2.0/. -use crate::digest::Digest; +use crate::digest::{Digest, DigestAlgorithm, DigestSource}; +use failure::Error; +use object::Object; +use std::path::Path; -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub enum PayloadCompressionAlgorithm { Gzip, LZ4 } impl Default for PayloadCompressionAlgorithm { - fn default() -> Self { PayloadCompressionAlgorithm::Gzip } + fn default() -> Self { PayloadCompressionAlgorithm::LZ4 } } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub enum PayloadBits { Independent, Bits32, @@ -26,7 +29,7 @@ impl Default for PayloadBits { fn default() -> Self { PayloadBits::Independent } } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub enum PayloadArchitecture { NOARCH, I386, @@ -46,4 +49,45 @@ pub struct Payload { pub compression_algorithm: PayloadCompressionAlgorithm, pub bitness: PayloadBits, pub architecture: PayloadArchitecture, +} + +impl Payload { + pub fn is_elf(&self) -> bool { + self.architecture == PayloadArchitecture::NOARCH && self.bitness == PayloadBits::Independent + } + + pub fn compute_payload(path: &Path) -> Result { + let f = std::fs::read(path)?; + + let (bitness, architecture) = match object::File::parse(f.as_slice()) { + Ok(bin) => { + let bitness = if bin.is_64() { + PayloadBits::Bits64 + } else { + PayloadBits::Bits32 + }; + + let architecture = match bin.architecture() { + object::Architecture::X86_64 | object::Architecture::I386 => { + PayloadArchitecture::I386 + } + object::Architecture::Aarch64 | object::Architecture::Arm => { + PayloadArchitecture::ARM + } + _ => PayloadArchitecture::NOARCH, + }; + + (bitness, architecture) + } + Err(_) => (PayloadBits::Independent, PayloadArchitecture::NOARCH), + }; + + Ok(Payload{ + primary_identifier:Digest::from_bytes(f.as_slice(), DigestAlgorithm::SHA3512, DigestSource::PrimaryPayloadHash)?, + additional_identifiers: Vec::::new(), + compression_algorithm: PayloadCompressionAlgorithm::default(), + bitness, + architecture + }) + } } \ No newline at end of file