Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion lib/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 1 addition & 5 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,7 @@ default-features = false
[dependencies.jiff]
version = "0.2"
default-features = false
features = [
"std",
"tz-system",
"tzdb-zoneinfo",
]
features = ["std"]
optional = true

[dependencies.serde]
Expand Down
19 changes: 15 additions & 4 deletions lib/src/crashlog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::bert::{Berr, Bert};
#[cfg(feature = "collateral_manager")]
use crate::collateral::{CollateralManager, CollateralTree};
use crate::cper::{Cper, CperSectionBody};
use crate::header::record_types;
use crate::metadata::Metadata;
use crate::node::Node;
use crate::region::Region;
Expand All @@ -27,8 +28,21 @@ impl CrashLog {
pub(crate) fn from_regions(regions: Vec<Region>) -> Result<Self, Error> {
let mut queue = VecDeque::from(regions);
let mut regions = Vec::new();
let mut metadata = Metadata::default();

while let Some(region) = queue.pop_front() {
for record in region.records.iter() {
let is_box = record.header.version.record_type == record_types::BOX
|| record.header.version.errata().type0_legacy_server_box;

if !is_box
&& let Ok(record_type) = record.header.record_type()
&& !metadata.record_types.contains(&record_type)
{
metadata.record_types.push(record_type);
}
}

for child in region.get_children() {
queue.push_back(child);
}
Expand All @@ -39,10 +53,7 @@ impl CrashLog {
return Err(Error::InvalidCrashLog);
}

Ok(CrashLog {
regions,
..CrashLog::default()
})
Ok(CrashLog { regions, metadata })
}

/// Extracts the Crash Log records from [Berr].
Expand Down
33 changes: 32 additions & 1 deletion lib/src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@ pub struct Metadata {
pub computer: Option<String>,
/// Name of the source where the Crash Log has been extracted from.
pub source: Option<CrashLogSource>,
/// Time of the extraction
/// Time of the extraction, expressed in UTC
pub time: Option<Time>,
/// Types of the records found in the Crash Log (e.g. "Punit", "MCA"...), listed in the order
/// they were first found and without duplicates. Box records are not listed.
pub record_types: Vec<&'static str>,
/// When the Crash Log is extracted from a CPER, this field stores the extra CPER sections that
/// could be read from the CPER structure.
pub extra_cper_sections: Vec<CperSectionBody>,
Expand All @@ -50,10 +53,38 @@ impl fmt::Display for Metadata {
sep = "-";
}

if !self.record_types.is_empty() {
write!(f, "{sep}{}", self.record_types.join("+"))?;
sep = "-";
}

if sep.is_empty() {
write!(f, "unnamed")?;
}

Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn display_with_record_types_and_time() {
let metadata = Metadata {
record_types: vec!["Punit", "MCA"],
time: Some(Time {
year: 2026,
month: 1,
day: 2,
hour: 3,
minute: 4,
second: 5,
millisecond: 6,
}),
..Metadata::default()
};
assert_eq!(metadata.to_string(), "20260102T030405.006Z-Punit+MCA");
}
}
14 changes: 4 additions & 10 deletions lib/src/metadata/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use alloc::fmt;
#[cfg(feature = "std")]
use std::fmt;

/// Crash Log Extraction Time, expressed in the local time of the system
/// Crash Log Extraction Time, expressed in UTC when read with [`Time::now`] on std targets
#[derive(Clone)]
pub struct Time {
pub year: u16,
Expand All @@ -22,7 +22,7 @@ impl fmt::Display for Time {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{:04}{:02}{:02}T{:02}{:02}{:02}.{:03}",
"{:04}{:02}{:02}T{:02}{:02}{:02}.{:03}Z",
self.year, self.month, self.day, self.hour, self.minute, self.second, self.millisecond,
)
}
Expand All @@ -34,19 +34,13 @@ impl Time {
/// The time is read from the operating system
#[cfg(feature = "std")]
pub fn now() -> Option<Self> {
use jiff::{Timestamp, tz};
use jiff::{Timestamp, tz::TimeZone};

let now = Timestamp::try_from(std::time::SystemTime::now())
.inspect_err(|err| log::info!("Cannot get the current time: {err}"))
.ok()?;

let tz = tz::TimeZone::system();

if tz == tz::TimeZone::unknown() {
log::warn!("Cannot determine the system time zone");
}

let local = now.to_zoned(tz).datetime();
let local = now.to_zoned(TimeZone::UTC).datetime();
Some(Time {
year: local.year() as u16,
month: local.month() as u8,
Expand Down
1 change: 1 addition & 0 deletions lib/src/source/acpi/efi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ pub(super) fn extract_crashlog() -> Result<CrashLog, Error> {
crashlog.metadata = metadata::Metadata {
computer: Some("efi".to_string()),
time: metadata::Time::now(),
record_types: core::mem::take(&mut crashlog.metadata.record_types),
..Default::default()
};

Expand Down
5 changes: 4 additions & 1 deletion lib/src/source/event_log/win.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,10 @@ impl EvtRecord {
})
.ok()?;

crashlog.metadata = self.metadata.clone();
crashlog.metadata = Metadata {
record_types: core::mem::take(&mut crashlog.metadata.record_types),
..self.metadata.clone()
};
Some(crashlog)
}
}
Expand Down
Loading