From dc4d978d52885c30fc12e52b3086fd65bb7b9a05 Mon Sep 17 00:00:00 2001 From: Will Chandler Date: Wed, 15 Oct 2025 13:29:18 -0400 Subject: [PATCH 1/5] Capture log file mtimes in support bundles Currently the mtime for log files captured in support bundles is always set as the default value of 1980-01-01T00:00. To more easily sort files by time, it would be convenient to capture their actual mtimes in the bundle zip. Attempt to get the mtime for logs captured by `sled-diagnostics`, falling back on the default if this fails, and copy the mtime into the final bundle zip in nexus. --- Cargo.lock | 2 + nexus/Cargo.toml | 2 +- .../tasks/support_bundle_collector.rs | 7 +++- sled-diagnostics/Cargo.toml | 3 +- sled-diagnostics/src/logs.rs | 42 ++++++++++++++++++- workspace-hack/Cargo.toml | 4 +- 6 files changed, 54 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 062824c006a..af19a7b61ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12721,6 +12721,7 @@ dependencies = [ "anyhow", "camino", "cfg-if", + "chrono", "fs-err 3.1.1", "futures", "illumos-utils", @@ -16500,6 +16501,7 @@ checksum = "95ab361742de920c5535880f89bbd611ee62002bf11341d16a5f057bb8ba6899" dependencies = [ "arbitrary", "bzip2 0.5.2", + "chrono", "crc32fast", "flate2", "indexmap 2.11.4", diff --git a/nexus/Cargo.toml b/nexus/Cargo.toml index 9b6b1bfe3c1..2a2a3ed4b8f 100644 --- a/nexus/Cargo.toml +++ b/nexus/Cargo.toml @@ -143,7 +143,7 @@ update-common.workspace = true update-engine.workspace = true omicron-workspace-hack.workspace = true omicron-uuid-kinds.workspace = true -zip.workspace = true +zip = { workspace = true, features = ["chrono"] } [dev-dependencies] async-bb8-diesel.workspace = true diff --git a/nexus/src/app/background/tasks/support_bundle_collector.rs b/nexus/src/app/background/tasks/support_bundle_collector.rs index fc32ce89153..a9a8fddd4db 100644 --- a/nexus/src/app/background/tasks/support_bundle_collector.rs +++ b/nexus/src/app/background/tasks/support_bundle_collector.rs @@ -1158,10 +1158,15 @@ fn recursively_add_directory_to_zipfile( let file_type = entry.file_type()?; if file_type.is_file() { + let src = entry.path(); + let mtime: chrono::DateTime = + src.metadata().and_then(|s| s.modified())?.into(); + let zip_time = zip::DateTime::try_from(mtime.naive_utc())?; + let opts = FullFileOptions::default() + .last_modified_time(zip_time) .compression_method(zip::CompressionMethod::Deflated) .large_file(true); - let src = entry.path(); zip.start_file_from_path(dst, opts)?; let mut file = std::fs::File::open(&src)?; diff --git a/sled-diagnostics/Cargo.toml b/sled-diagnostics/Cargo.toml index 3b254fcfd4e..b3f1853eb44 100644 --- a/sled-diagnostics/Cargo.toml +++ b/sled-diagnostics/Cargo.toml @@ -10,6 +10,7 @@ workspace = true anyhow.workspace = true camino.workspace = true cfg-if.workspace = true +chrono.workspace = true fs-err = { workspace = true, features = ["tokio"] } futures.workspace = true illumos-utils.workspace = true @@ -25,7 +26,7 @@ serde.workspace = true slog.workspace = true thiserror.workspace = true tokio = { workspace = true, features = ["full"] } -zip = { workspace = true, features = ["zstd"] } +zip = { workspace = true, features = ["chrono","zstd"] } [dev-dependencies] omicron-common.workspace = true diff --git a/sled-diagnostics/src/logs.rs b/sled-diagnostics/src/logs.rs index 9970e0433b3..89763d970b4 100644 --- a/sled-diagnostics/src/logs.rs +++ b/sled-diagnostics/src/logs.rs @@ -10,6 +10,7 @@ use std::{ sync::LazyLock, }; +use anyhow::Context; use camino::{Utf8Path, Utf8PathBuf}; use fs_err::File; use illumos_utils::zfs::{ @@ -715,10 +716,24 @@ fn write_log_to_zip( }; let mut src = File::open(&snapshot_logfile)?; + + let mtime = get_log_mtime(snapshot_logfile) + .inspect_err(|e| { + warn!( + logger, + "sled-diagnostics unable to get mtime for logfile"; + "error" => %e, + "logfile" => %snapshot_logfile, + ); + }) + .ok() + .unwrap_or_else(zip::DateTime::default_for_write); + let zip_path = format!("{service}/{logtype}/{log_name}"); zip.start_file_from_path( zip_path, FullFileOptions::default() + .last_modified_time(mtime) .compression_method(zip::CompressionMethod::Zstd) .compression_level(Some(3)) // NB: From the docs @@ -746,6 +761,17 @@ fn write_log_to_zip( Ok(()) } +fn get_log_mtime(log_path: &Utf8Path) -> anyhow::Result { + let mtime = log_path + .metadata() + .and_then(|s| s.modified()) + .context("failed to stat path")?; + + let datetime: chrono::DateTime = mtime.into(); + zip::DateTime::try_from(datetime.naive_utc()) + .context("failed to convert file mtime to zip-compatible time") +} + /// A log file that is found in oxlog's "extra" bucket of service logs. #[derive(Debug, PartialEq)] enum ExtraLogKind<'a> { @@ -1202,6 +1228,12 @@ mod illumos_tests { let mut logfile_handle = fs_err::tokio::File::create_new(&logfile).await.unwrap(); logfile_handle.write_all(data.as_bytes()).await.unwrap(); + + // 2025-10-15T00:00:00 + let mtime = std::time::SystemTime::UNIX_EPOCH + + std::time::Duration::from_secs(1760486400); + let std_file = logfile_handle.into_std().await.into_file(); + std_file.set_modified(mtime).unwrap(); } // Populate some file with similar names that should be skipped over @@ -1237,12 +1269,20 @@ mod illumos_tests { zip.finish().unwrap(); - // Confirm the zip has our file and data + let expected_zip_mtime = + zip::DateTime::from_date_and_time(2025, 10, 15, 0, 0, 0) + .unwrap(); + + // Confirm the zip has our file and data with the right mtime let mut archive = ZipArchive::new(File::open(zipfile_path).unwrap()).unwrap(); for (name, data) in logfile_to_data { let mut file_in_zip = archive.by_name(&format!("mg-ddm/current/{name}")).unwrap(); + + let mtime = file_in_zip.last_modified().unwrap(); + assert_eq!(mtime, expected_zip_mtime, "file mtime matches"); + let mut contents = String::new(); file_in_zip.read_to_string(&mut contents).unwrap(); diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index b0d9d2f87d8..a48cb3bf67f 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -150,7 +150,7 @@ x509-cert = { version = "0.2.5" } zerocopy-c38e5c1d305a1b54 = { package = "zerocopy", version = "0.8.27", default-features = false, features = ["derive", "simd"] } zerocopy-ca01ad9e24f5d932 = { package = "zerocopy", version = "0.7.35", features = ["derive", "simd"] } zeroize = { version = "1.8.1", features = ["std", "zeroize_derive"] } -zip-164d15cefe24d7eb = { package = "zip", version = "4.2.0", default-features = false, features = ["bzip2", "deflate", "zstd"] } +zip-164d15cefe24d7eb = { package = "zip", version = "4.2.0", default-features = false, features = ["bzip2", "chrono", "deflate", "zstd"] } zip-3b31131e45eafb45 = { package = "zip", version = "0.6.6", default-features = false, features = ["bzip2", "deflate"] } [build-dependencies] @@ -291,7 +291,7 @@ x509-cert = { version = "0.2.5" } zerocopy-c38e5c1d305a1b54 = { package = "zerocopy", version = "0.8.27", default-features = false, features = ["derive", "simd"] } zerocopy-ca01ad9e24f5d932 = { package = "zerocopy", version = "0.7.35", features = ["derive", "simd"] } zeroize = { version = "1.8.1", features = ["std", "zeroize_derive"] } -zip-164d15cefe24d7eb = { package = "zip", version = "4.2.0", default-features = false, features = ["bzip2", "deflate", "zstd"] } +zip-164d15cefe24d7eb = { package = "zip", version = "4.2.0", default-features = false, features = ["bzip2", "chrono", "deflate", "zstd"] } zip-3b31131e45eafb45 = { package = "zip", version = "0.6.6", default-features = false, features = ["bzip2", "deflate"] } [target.x86_64-unknown-linux-gnu.dependencies] From 80681cb869f1decb7a2353ffe2a6c34a475c76e0 Mon Sep 17 00:00:00 2001 From: Will Chandler Date: Thu, 16 Oct 2025 16:33:53 -0400 Subject: [PATCH 2/5] Avoid getting mtime twice Oxlog is already collecting the file mtime for us when it find the logs. Avoid `stat`ing the files a second time and pass the cached time to the zip archive. --- Cargo.lock | 4 +- nexus/Cargo.toml | 3 +- .../tasks/support_bundle_collector.rs | 7 +- sled-diagnostics/Cargo.toml | 3 +- sled-diagnostics/src/logs.rs | 126 ++++++++---------- workspace-hack/Cargo.toml | 4 +- 6 files changed, 66 insertions(+), 81 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index af19a7b61ef..7b88baf6155 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8123,6 +8123,7 @@ dependencies = [ "internal-dns-types", "ipnetwork", "itertools 0.14.0", + "jiff", "lldpd-client", "macaddr", "maplit", @@ -12725,6 +12726,7 @@ dependencies = [ "fs-err 3.1.1", "futures", "illumos-utils", + "jiff", "libc", "omicron-common", "omicron-test-utils", @@ -16501,10 +16503,10 @@ checksum = "95ab361742de920c5535880f89bbd611ee62002bf11341d16a5f057bb8ba6899" dependencies = [ "arbitrary", "bzip2 0.5.2", - "chrono", "crc32fast", "flate2", "indexmap 2.11.4", + "jiff", "memchr", "zopfli", "zstd", diff --git a/nexus/Cargo.toml b/nexus/Cargo.toml index 2a2a3ed4b8f..feb09f1ef76 100644 --- a/nexus/Cargo.toml +++ b/nexus/Cargo.toml @@ -52,6 +52,7 @@ internal-dns-resolver.workspace = true internal-dns-types.workspace = true ipnetwork.workspace = true itertools.workspace = true +jiff.workspace = true lldpd_client.workspace = true macaddr.workspace = true maplit.workspace = true @@ -143,7 +144,7 @@ update-common.workspace = true update-engine.workspace = true omicron-workspace-hack.workspace = true omicron-uuid-kinds.workspace = true -zip = { workspace = true, features = ["chrono"] } +zip = { workspace = true, features = ["jiff-02"] } [dev-dependencies] async-bb8-diesel.workspace = true diff --git a/nexus/src/app/background/tasks/support_bundle_collector.rs b/nexus/src/app/background/tasks/support_bundle_collector.rs index a9a8fddd4db..8d7f375a42b 100644 --- a/nexus/src/app/background/tasks/support_bundle_collector.rs +++ b/nexus/src/app/background/tasks/support_bundle_collector.rs @@ -1159,9 +1159,10 @@ fn recursively_add_directory_to_zipfile( let file_type = entry.file_type()?; if file_type.is_file() { let src = entry.path(); - let mtime: chrono::DateTime = - src.metadata().and_then(|s| s.modified())?.into(); - let zip_time = zip::DateTime::try_from(mtime.naive_utc())?; + + let system_mtime = entry.metadata().and_then(|m| m.modified())?; + let zoned = jiff::Zoned::try_from(system_mtime)?; + let zip_time = zip::DateTime::try_from(zoned.datetime())?; let opts = FullFileOptions::default() .last_modified_time(zip_time) diff --git a/sled-diagnostics/Cargo.toml b/sled-diagnostics/Cargo.toml index b3f1853eb44..ed3ee713d55 100644 --- a/sled-diagnostics/Cargo.toml +++ b/sled-diagnostics/Cargo.toml @@ -14,6 +14,7 @@ chrono.workspace = true fs-err = { workspace = true, features = ["tokio"] } futures.workspace = true illumos-utils.workspace = true +jiff.workspace = true libc.workspace = true omicron-workspace-hack.workspace = true once_cell.workspace = true @@ -26,7 +27,7 @@ serde.workspace = true slog.workspace = true thiserror.workspace = true tokio = { workspace = true, features = ["full"] } -zip = { workspace = true, features = ["chrono","zstd"] } +zip = { workspace = true, features = ["jiff-02","zstd"] } [dev-dependencies] omicron-common.workspace = true diff --git a/sled-diagnostics/src/logs.rs b/sled-diagnostics/src/logs.rs index 89763d970b4..4cc39914f43 100644 --- a/sled-diagnostics/src/logs.rs +++ b/sled-diagnostics/src/logs.rs @@ -10,7 +10,6 @@ use std::{ sync::LazyLock, }; -use anyhow::Context; use camino::{Utf8Path, Utf8PathBuf}; use fs_err::File; use illumos_utils::zfs::{ @@ -452,11 +451,11 @@ impl LogsHandle { service: &str, zip: &mut zip::ZipWriter, log_snapshots: &mut LogSnapshots, - logfile: &Utf8Path, + logfile: &LogFile, logtype: LogType, ) -> Result<(), LogError> { let snapshot_logfile = - self.find_log_in_snapshot(log_snapshots, logfile).await?; + self.find_log_in_snapshot(log_snapshots, &logfile.path).await?; if logtype == LogType::Current { // Since we are processing the current log files in a zone we need @@ -502,6 +501,16 @@ impl LogsHandle { .filter(|f| is_log_file(f.path(), filename)) { let logfile = f.path(); + let system_mtime = + f.metadata().and_then(|m| m.modified()).inspect_err(|e| { + warn!(&self.log, "sled-diagnostic failed to get mtime of logfile"; + "error" => %e, + "logfile" => %logfile, + ); + }).ok(); + let mtime = system_mtime + .and_then(|m| jiff::Timestamp::try_from(m).ok()); + if logfile.is_file() { write_log_to_zip( &self.log, @@ -509,6 +518,7 @@ impl LogsHandle { zip, LogType::Current, logfile, + mtime, )?; } } @@ -523,6 +533,7 @@ impl LogsHandle { zip, logtype, &snapshot_logfile, + logfile.modified, )?; } false => { @@ -613,7 +624,7 @@ impl LogsHandle { &service, &mut zip, &mut log_snapshots, - ¤t.path, + ¤t, LogType::Current, ) .await?; @@ -629,13 +640,13 @@ impl LogsHandle { .archived .into_iter() .filter(|log| log.path.as_str().contains("crypt/debug")) - .map(|log| log.path) .collect(); // Since these logs can be spread out across multiple U.2 devices // we need to sort them by timestamp. archived.sort_by_key(|log| { - log.as_str() + log.path + .as_str() .rsplit_once(".") .and_then(|(_, date)| date.parse::().ok()) .unwrap_or(0) @@ -704,6 +715,7 @@ fn write_log_to_zip( zip: &mut zip::ZipWriter, logtype: LogType, snapshot_logfile: &Utf8Path, + mtime: Option, ) -> Result<(), LogError> { let Some(log_name) = snapshot_logfile.file_name() else { warn!( @@ -717,23 +729,18 @@ fn write_log_to_zip( let mut src = File::open(&snapshot_logfile)?; - let mtime = get_log_mtime(snapshot_logfile) - .inspect_err(|e| { - warn!( - logger, - "sled-diagnostics unable to get mtime for logfile"; - "error" => %e, - "logfile" => %snapshot_logfile, - ); + let zip_mtime = mtime + .and_then(|ts| { + let zoned = ts.in_tz("UTC").ok()?; + zip::DateTime::try_from(zoned.datetime()).ok() }) - .ok() - .unwrap_or_else(zip::DateTime::default_for_write); + .unwrap_or_else(zip::DateTime::default); let zip_path = format!("{service}/{logtype}/{log_name}"); zip.start_file_from_path( zip_path, FullFileOptions::default() - .last_modified_time(mtime) + .last_modified_time(zip_mtime) .compression_method(zip::CompressionMethod::Zstd) .compression_level(Some(3)) // NB: From the docs @@ -761,17 +768,6 @@ fn write_log_to_zip( Ok(()) } -fn get_log_mtime(log_path: &Utf8Path) -> anyhow::Result { - let mtime = log_path - .metadata() - .and_then(|s| s.modified()) - .context("failed to stat path")?; - - let datetime: chrono::DateTime = mtime.into(); - zip::DateTime::try_from(datetime.naive_utc()) - .context("failed to convert file mtime to zip-compatible time") -} - /// A log file that is found in oxlog's "extra" bucket of service logs. #[derive(Debug, PartialEq)] enum ExtraLogKind<'a> { @@ -783,8 +779,8 @@ enum ExtraLogKind<'a> { #[derive(Debug, Default, PartialEq)] struct ExtraLogs<'a> { - current: Option<&'a Utf8Path>, - rotated: Vec<&'a Utf8Path>, + current: Option<&'a LogFile>, + rotated: Vec<&'a LogFile>, } fn sort_extra_logs<'a>( @@ -806,15 +802,15 @@ fn sort_extra_logs<'a>( warn!( logger, "found multiple current log files for {name}"; - "old" => %old_path, + "old" => %old_path.path, "new" => %log.path, ); } - entry.current = Some(&log.path); + entry.current = Some(&log); } ExtraLogKind::Rotated { name, log } => { let entry = res.entry(name).or_default(); - entry.rotated.push(&log.path); + entry.rotated.push(&log); } } } @@ -864,9 +860,9 @@ fn sort_cockroach_extra_logs(logs: &[LogFile]) -> HashMap<&str, ExtraLogs<'_>> { let entry = interested.entry(prefix).or_default(); if file_name == format!("{prefix}.log") { - entry.current = Some(log.path.as_path()); + entry.current = Some(log); } else { - entry.rotated.push(log.path.as_path()); + entry.rotated.push(log); } } } @@ -943,52 +939,30 @@ mod test { "bogus.log", "some/dir" ].into_iter().map(|l| { - oxlog::LogFile { path: Utf8PathBuf::from(l), size: None, modified: None } - }).collect(); + oxlog::LogFile { path: Utf8PathBuf::from(l), size: None, modified: None } + }).collect(); + let logs_map: HashMap<_, _> = + logs.iter().map(|l| (l.path.as_str(), l)).collect(); let mut expected: HashMap<&str, ExtraLogs<'_>> = HashMap::new(); // cockroach expected.entry("cockroach").or_default().current = - Some(Utf8Path::new("cockroach.log")); - expected - .entry("cockroach") - .or_default() - .rotated - .push(Utf8Path::new("cockroach.oxzcockroachdba3628a56-6f85-43b5-be50-71d8f0e04877.root.2025-01-31T17_11_45Z.011435.log")); - expected - .entry("cockroach") - .or_default() - .rotated - .push(Utf8Path::new("cockroach.oxzcockroachdba3628a56-6f85-43b5-be50-71d8f0e04877.root.2025-02-01T01_51_51Z.011486.log")); + Some(&logs_map["cockroach.log"]); + expected.entry("cockroach").or_default().rotated.push(&logs_map["cockroach.oxzcockroachdba3628a56-6f85-43b5-be50-71d8f0e04877.root.2025-01-31T17_11_45Z.011435.log"]); + expected.entry("cockroach").or_default().rotated.push(&logs_map["cockroach.oxzcockroachdba3628a56-6f85-43b5-be50-71d8f0e04877.root.2025-02-01T01_51_51Z.011486.log"]); // cockroach-health expected.entry("cockroach-health").or_default().current = - Some(Utf8Path::new("cockroach-health.log")); - expected - .entry("cockroach-health") - .or_default() - .rotated - .push(Utf8Path::new("cockroach-health.oxzcockroachdba3628a56-6f85-43b5-be50-71d8f0e04877.root.2025-01-31T21_43_26Z.011435.log")); - expected - .entry("cockroach-health") - .or_default() - .rotated - .push(Utf8Path::new("cockroach-health.oxzcockroachdba3628a56-6f85-43b5-be50-71d8f0e04877.root.2025-02-01T01_51_53Z.011486.log")); + Some(&logs_map["cockroach-health.log"]); + expected.entry("cockroach-health").or_default().rotated.push(&logs_map["cockroach-health.oxzcockroachdba3628a56-6f85-43b5-be50-71d8f0e04877.root.2025-01-31T21_43_26Z.011435.log"]); + expected.entry("cockroach-health").or_default().rotated.push(&logs_map["cockroach-health.oxzcockroachdba3628a56-6f85-43b5-be50-71d8f0e04877.root.2025-02-01T01_51_53Z.011486.log"]); // cockroach-stderr expected.entry("cockroach-stderr").or_default().current = - Some(Utf8Path::new("cockroach-stderr.log")); - expected - .entry("cockroach-stderr") - .or_default() - .rotated - .push(Utf8Path::new("cockroach-stderr.oxzcockroachdba3628a56-6f85-43b5-be50-71d8f0e04877.root.2023-08-30T18_56_19Z.011950.log")); - expected - .entry("cockroach-stderr") - .or_default() - .rotated - .push(Utf8Path::new("cockroach-stderr.oxzcockroachdba3628a56-6f85-43b5-be50-71d8f0e04877.root.2023-08-31T02_59_24Z.010479.log")); + Some(&logs_map["cockroach-stderr.log"]); + expected.entry("cockroach-stderr").or_default().rotated.push(&logs_map["cockroach-stderr.oxzcockroachdba3628a56-6f85-43b5-be50-71d8f0e04877.root.2023-08-30T18_56_19Z.011950.log"]); + expected.entry("cockroach-stderr").or_default().rotated.push(&logs_map["cockroach-stderr.oxzcockroachdba3628a56-6f85-43b5-be50-71d8f0e04877.root.2023-08-31T02_59_24Z.010479.log"]); let extra = sort_cockroach_extra_logs(logs.as_slice()); assert_eq!( @@ -1254,14 +1228,19 @@ mod illumos_tests { let zipfile_path = mountpoint.join("test.zip"); let zipfile = File::create_new(&zipfile_path).unwrap(); let mut zip = ZipWriter::new(zipfile); + let log = LogFile { + path: mountpoint + .join(format!("var/svc/log/{}", logfile_to_data[0].0)), + size: None, + modified: None, + }; loghandle .process_logs( "mg-ddm", &mut zip, &mut log_snapshots, - &mountpoint - .join(format!("var/svc/log/{}", logfile_to_data[0].0)), + &log, LogType::Current, ) .await @@ -1348,13 +1327,14 @@ mod illumos_tests { let zipfile_path = mountpoint.join("test.zip"); let zipfile = File::create_new(&zipfile_path).unwrap(); let mut zip = ZipWriter::new(zipfile); + let log = LogFile { path: logfile, size: None, modified: None }; loghandle .process_logs( "mg-ddm", &mut zip, &mut log_snapshots, - &logfile, + &log, LogType::Current, ) .await diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index a48cb3bf67f..40174440059 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -150,7 +150,7 @@ x509-cert = { version = "0.2.5" } zerocopy-c38e5c1d305a1b54 = { package = "zerocopy", version = "0.8.27", default-features = false, features = ["derive", "simd"] } zerocopy-ca01ad9e24f5d932 = { package = "zerocopy", version = "0.7.35", features = ["derive", "simd"] } zeroize = { version = "1.8.1", features = ["std", "zeroize_derive"] } -zip-164d15cefe24d7eb = { package = "zip", version = "4.2.0", default-features = false, features = ["bzip2", "chrono", "deflate", "zstd"] } +zip-164d15cefe24d7eb = { package = "zip", version = "4.2.0", default-features = false, features = ["bzip2", "deflate", "jiff-02", "zstd"] } zip-3b31131e45eafb45 = { package = "zip", version = "0.6.6", default-features = false, features = ["bzip2", "deflate"] } [build-dependencies] @@ -291,7 +291,7 @@ x509-cert = { version = "0.2.5" } zerocopy-c38e5c1d305a1b54 = { package = "zerocopy", version = "0.8.27", default-features = false, features = ["derive", "simd"] } zerocopy-ca01ad9e24f5d932 = { package = "zerocopy", version = "0.7.35", features = ["derive", "simd"] } zeroize = { version = "1.8.1", features = ["std", "zeroize_derive"] } -zip-164d15cefe24d7eb = { package = "zip", version = "4.2.0", default-features = false, features = ["bzip2", "chrono", "deflate", "zstd"] } +zip-164d15cefe24d7eb = { package = "zip", version = "4.2.0", default-features = false, features = ["bzip2", "deflate", "jiff-02", "zstd"] } zip-3b31131e45eafb45 = { package = "zip", version = "0.6.6", default-features = false, features = ["bzip2", "deflate"] } [target.x86_64-unknown-linux-gnu.dependencies] From 72d5f8436b3579e1ca1dce6423c66d766e0a3ef5 Mon Sep 17 00:00:00 2001 From: Will Chandler Date: Mon, 20 Oct 2025 22:07:21 -0400 Subject: [PATCH 3/5] Don't error out on mtime failure mtime is a nice to have, just default to 1980 if any part of getting it fails. --- .../app/background/tasks/support_bundle_collector.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/nexus/src/app/background/tasks/support_bundle_collector.rs b/nexus/src/app/background/tasks/support_bundle_collector.rs index 1f91bc63084..6c22e9f3809 100644 --- a/nexus/src/app/background/tasks/support_bundle_collector.rs +++ b/nexus/src/app/background/tasks/support_bundle_collector.rs @@ -1243,9 +1243,15 @@ fn recursively_add_directory_to_zipfile( if file_type.is_file() { let src = entry.path(); - let system_mtime = entry.metadata().and_then(|m| m.modified())?; - let zoned = jiff::Zoned::try_from(system_mtime)?; - let zip_time = zip::DateTime::try_from(zoned.datetime())?; + let zip_time = entry + .metadata() + .and_then(|m| m.modified()) + .ok() + .and_then(|sys_time| jiff::Zoned::try_from(sys_time).ok()) + .and_then(|zoned| { + zip::DateTime::try_from(zoned.datetime()).ok() + }) + .unwrap_or_else(zip::DateTime::default); let opts = FullFileOptions::default() .last_modified_time(zip_time) From fa07354f2fd7b16310611423e5a1fbd6d117c9eb Mon Sep 17 00:00:00 2001 From: Will Chandler Date: Mon, 20 Oct 2025 22:31:13 -0400 Subject: [PATCH 4/5] Traverse potential symlinks for mtime Handle getting mtime for symlinks by calling `metadata` on the dirent's path. --- nexus/src/app/background/tasks/support_bundle_collector.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/nexus/src/app/background/tasks/support_bundle_collector.rs b/nexus/src/app/background/tasks/support_bundle_collector.rs index 6c22e9f3809..8c35cc0395d 100644 --- a/nexus/src/app/background/tasks/support_bundle_collector.rs +++ b/nexus/src/app/background/tasks/support_bundle_collector.rs @@ -1244,6 +1244,7 @@ fn recursively_add_directory_to_zipfile( let src = entry.path(); let zip_time = entry + .path() .metadata() .and_then(|m| m.modified()) .ok() From 756d1de027f4e8363d9f4b3b38f8fa11e6b9d50a Mon Sep 17 00:00:00 2001 From: Will Chandler Date: Mon, 10 Nov 2025 22:15:32 -0500 Subject: [PATCH 5/5] Update cargo lock --- workspace-hack/Cargo.toml | 64 ++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index 40174440059..3f16c51cfb6 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -35,6 +35,7 @@ chrono = { version = "0.4.42", features = ["serde"] } cipher = { version = "0.4.4", default-features = false, features = ["block-padding", "zeroize"] } clap = { version = "4.5.48", features = ["cargo", "derive", "env", "wrap_help"] } clap_builder = { version = "4.5.48", default-features = false, features = ["cargo", "color", "env", "std", "suggestions", "usage", "wrap_help"] } +const-oid = { version = "0.9.6", default-features = false, features = ["db", "std"] } crossbeam-epoch = { version = "0.9.18" } crossbeam-utils = { version = "0.8.21" } crossterm = { version = "0.28.1", features = ["event-stream", "serde"] } @@ -42,12 +43,13 @@ crypto-common = { version = "0.1.6", default-features = false, features = ["getr curve25519-dalek = { version = "4.1.3", features = ["digest", "legacy_compatibility", "rand_core"] } daft = { version = "0.1.4", features = ["derive", "newtype-uuid1", "oxnet01", "uuid1"] } data-encoding = { version = "2.9.0" } +der = { version = "0.7.10", default-features = false, features = ["derive", "flagset", "oid", "pem", "std"] } digest = { version = "0.10.7", features = ["mac", "oid", "std"] } ecdsa = { version = "0.16.9", features = ["pem", "signing", "std", "verifying"] } -ed25519-dalek = { version = "2.1.1", features = ["digest", "pkcs8", "rand_core"] } +ed25519-dalek = { version = "2.1.1", features = ["digest", "pem", "rand_core"] } either = { version = "1.15.0", features = ["use_std"] } elliptic-curve = { version = "0.13.8", features = ["ecdh", "hazmat", "pem", "std"] } -env_logger = { version = "0.11.5", default-features = false, features = ["auto-color"] } +env_logger = { version = "0.11.8", default-features = false, features = ["auto-color"] } ff = { version = "0.13.0", default-features = false, features = ["alloc"] } flate2 = { version = "1.1.2", features = ["zlib-rs"] } form_urlencoded = { version = "1.2.2" } @@ -58,13 +60,13 @@ futures-io = { version = "0.3.31" } futures-sink = { version = "0.3.31" } futures-task = { version = "0.3.31", default-features = false, features = ["std"] } futures-util = { version = "0.3.31", features = ["channel", "io", "sink"] } -gateway-ereport-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "6bd2660d651332f38949cdfd3d23d751ca54b120", default-features = false, features = ["debug-impls", "serde"] } -gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "6bd2660d651332f38949cdfd3d23d751ca54b120", features = ["std"] } +gateway-ereport-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "669fe557b66f44aed3c622bd17bc092f08797e0c", default-features = false, features = ["debug-impls", "serde"] } +gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "669fe557b66f44aed3c622bd17bc092f08797e0c", features = ["std"] } generic-array = { version = "0.14.7", default-features = false, features = ["more_lengths", "zeroize"] } getrandom-6f8ce4dd05d13bba = { package = "getrandom", version = "0.2.15", default-features = false, features = ["js", "rdrand", "std"] } group = { version = "0.13.0", default-features = false, features = ["alloc"] } hashbrown = { version = "0.16.0", default-features = false, features = ["allocator-api2", "inline-more"] } -heck = { version = "0.4.1" } +heck = { version = "0.4.1", features = ["unicode"] } hickory-proto = { version = "0.25.2", features = ["serde", "text-parsing"] } hmac = { version = "0.12.1", default-features = false, features = ["reset"] } hyper = { version = "1.7.0", features = ["full"] } @@ -108,8 +110,8 @@ rand_chacha-468e82937335b1c9 = { package = "rand_chacha", version = "0.3.1", def regex = { version = "1.11.3" } regex-automata = { version = "0.4.11", default-features = false, features = ["dfa", "hybrid", "meta", "nfa", "perf", "std", "unicode"] } regex-syntax = { version = "0.8.5" } -reqwest = { version = "0.12.22", features = ["blocking", "cookies", "json", "rustls-tls", "stream"] } -rsa = { version = "0.9.6", features = ["serde", "sha2"] } +reqwest = { version = "0.12.24", features = ["blocking", "cookies", "json", "rustls-tls", "stream"] } +rsa = { version = "0.9.8", features = ["serde", "sha2"] } rustc-hash = { version = "2.1.1" } rustls = { version = "0.23.19", features = ["ring"] } rustls-webpki = { version = "0.102.8", default-features = false, features = ["aws_lc_rs", "ring", "std"] } @@ -118,9 +120,11 @@ scopeguard = { version = "1.2.0" } semver = { version = "1.0.27", features = ["serde"] } serde = { version = "1.0.226", features = ["alloc", "derive", "rc"] } serde_core = { version = "1.0.226", features = ["alloc", "rc"] } -serde_json = { version = "1.0.145", features = ["raw_value", "unbounded_depth"] } +serde_json = { version = "1.0.145", features = ["alloc", "raw_value", "unbounded_depth"] } +serde_with = { version = "3.14.0" } sha1 = { version = "0.10.6", features = ["oid"] } sha2 = { version = "0.10.9", features = ["oid"] } +sha3 = { version = "0.10.8", features = ["oid"] } similar = { version = "2.7.0", features = ["bytes", "inline", "unicode"] } slog = { version = "2.7.0", features = ["dynamic-keys", "max_level_trace", "release_max_level_debug", "release_max_level_trace"] } smallvec = { version = "1.15.1", default-features = false, features = ["const_new"] } @@ -172,6 +176,7 @@ chrono = { version = "0.4.42", features = ["serde"] } cipher = { version = "0.4.4", default-features = false, features = ["block-padding", "zeroize"] } clap = { version = "4.5.48", features = ["cargo", "derive", "env", "wrap_help"] } clap_builder = { version = "4.5.48", default-features = false, features = ["cargo", "color", "env", "std", "suggestions", "usage", "wrap_help"] } +const-oid = { version = "0.9.6", default-features = false, features = ["db", "std"] } crossbeam-epoch = { version = "0.9.18" } crossbeam-utils = { version = "0.8.21" } crossterm = { version = "0.28.1", features = ["event-stream", "serde"] } @@ -179,12 +184,13 @@ crypto-common = { version = "0.1.6", default-features = false, features = ["getr curve25519-dalek = { version = "4.1.3", features = ["digest", "legacy_compatibility", "rand_core"] } daft = { version = "0.1.4", features = ["derive", "newtype-uuid1", "oxnet01", "uuid1"] } data-encoding = { version = "2.9.0" } +der = { version = "0.7.10", default-features = false, features = ["derive", "flagset", "oid", "pem", "std"] } digest = { version = "0.10.7", features = ["mac", "oid", "std"] } ecdsa = { version = "0.16.9", features = ["pem", "signing", "std", "verifying"] } -ed25519-dalek = { version = "2.1.1", features = ["digest", "pkcs8", "rand_core"] } +ed25519-dalek = { version = "2.1.1", features = ["digest", "pem", "rand_core"] } either = { version = "1.15.0", features = ["use_std"] } elliptic-curve = { version = "0.13.8", features = ["ecdh", "hazmat", "pem", "std"] } -env_logger = { version = "0.11.5", default-features = false, features = ["auto-color"] } +env_logger = { version = "0.11.8", default-features = false, features = ["auto-color"] } ff = { version = "0.13.0", default-features = false, features = ["alloc"] } flate2 = { version = "1.1.2", features = ["zlib-rs"] } form_urlencoded = { version = "1.2.2" } @@ -195,13 +201,13 @@ futures-io = { version = "0.3.31" } futures-sink = { version = "0.3.31" } futures-task = { version = "0.3.31", default-features = false, features = ["std"] } futures-util = { version = "0.3.31", features = ["channel", "io", "sink"] } -gateway-ereport-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "6bd2660d651332f38949cdfd3d23d751ca54b120", default-features = false, features = ["debug-impls", "serde"] } -gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "6bd2660d651332f38949cdfd3d23d751ca54b120", features = ["std"] } +gateway-ereport-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "669fe557b66f44aed3c622bd17bc092f08797e0c", default-features = false, features = ["debug-impls", "serde"] } +gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "669fe557b66f44aed3c622bd17bc092f08797e0c", features = ["std"] } generic-array = { version = "0.14.7", default-features = false, features = ["more_lengths", "zeroize"] } getrandom-6f8ce4dd05d13bba = { package = "getrandom", version = "0.2.15", default-features = false, features = ["js", "rdrand", "std"] } group = { version = "0.13.0", default-features = false, features = ["alloc"] } hashbrown = { version = "0.16.0", default-features = false, features = ["allocator-api2", "inline-more"] } -heck = { version = "0.4.1" } +heck = { version = "0.4.1", features = ["unicode"] } hickory-proto = { version = "0.25.2", features = ["serde", "text-parsing"] } hmac = { version = "0.12.1", default-features = false, features = ["reset"] } hyper = { version = "1.7.0", features = ["full"] } @@ -245,8 +251,8 @@ rand_chacha-468e82937335b1c9 = { package = "rand_chacha", version = "0.3.1", def regex = { version = "1.11.3" } regex-automata = { version = "0.4.11", default-features = false, features = ["dfa", "hybrid", "meta", "nfa", "perf", "std", "unicode"] } regex-syntax = { version = "0.8.5" } -reqwest = { version = "0.12.22", features = ["blocking", "cookies", "json", "rustls-tls", "stream"] } -rsa = { version = "0.9.6", features = ["serde", "sha2"] } +reqwest = { version = "0.12.24", features = ["blocking", "cookies", "json", "rustls-tls", "stream"] } +rsa = { version = "0.9.8", features = ["serde", "sha2"] } rustc-hash = { version = "2.1.1" } rustls = { version = "0.23.19", features = ["ring"] } rustls-webpki = { version = "0.102.8", default-features = false, features = ["aws_lc_rs", "ring", "std"] } @@ -255,9 +261,11 @@ scopeguard = { version = "1.2.0" } semver = { version = "1.0.27", features = ["serde"] } serde = { version = "1.0.226", features = ["alloc", "derive", "rc"] } serde_core = { version = "1.0.226", features = ["alloc", "rc"] } -serde_json = { version = "1.0.145", features = ["raw_value", "unbounded_depth"] } +serde_json = { version = "1.0.145", features = ["alloc", "raw_value", "unbounded_depth"] } +serde_with = { version = "3.14.0" } sha1 = { version = "0.10.6", features = ["oid"] } sha2 = { version = "0.10.9", features = ["oid"] } +sha3 = { version = "0.10.8", features = ["oid"] } similar = { version = "2.7.0", features = ["bytes", "inline", "unicode"] } slog = { version = "2.7.0", features = ["dynamic-keys", "max_level_trace", "release_max_level_debug", "release_max_level_trace"] } smallvec = { version = "1.15.1", default-features = false, features = ["const_new"] } @@ -299,10 +307,11 @@ bitflags-f595c2ba2a3f28df = { package = "bitflags", version = "2.9.4", default-f cookie = { version = "0.18.1", default-features = false, features = ["percent-encode"] } dof-468e82937335b1c9 = { package = "dof", version = "0.3.0", default-features = false, features = ["des"] } dof-9fbad63c4bcf4a8f = { package = "dof", version = "0.4.0", default-features = false, features = ["des"] } -getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.1", default-features = false, features = ["std"] } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2", "ring", "webpki-tokio"] } hyper-util = { version = "0.1.17", features = ["full"] } linux-raw-sys = { version = "0.4.14", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "std", "system", "xdp"] } +miniz_oxide = { version = "0.8.5", default-features = false, features = ["with-alloc"] } mio = { version = "1.0.2", features = ["net", "os-ext"] } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = ["fs", "stdio", "termios"] } @@ -312,10 +321,11 @@ bitflags-f595c2ba2a3f28df = { package = "bitflags", version = "2.9.4", default-f cookie = { version = "0.18.1", default-features = false, features = ["percent-encode"] } dof-468e82937335b1c9 = { package = "dof", version = "0.3.0", default-features = false, features = ["des"] } dof-9fbad63c4bcf4a8f = { package = "dof", version = "0.4.0", default-features = false, features = ["des"] } -getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.1", default-features = false, features = ["std"] } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2", "ring", "webpki-tokio"] } hyper-util = { version = "0.1.17", features = ["full"] } linux-raw-sys = { version = "0.4.14", default-features = false, features = ["elf", "errno", "general", "if_ether", "ioctl", "net", "netlink", "no_std", "prctl", "std", "system", "xdp"] } +miniz_oxide = { version = "0.8.5", default-features = false, features = ["with-alloc"] } mio = { version = "1.0.2", features = ["net", "os-ext"] } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = ["fs", "stdio", "termios"] } @@ -323,9 +333,10 @@ rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = [" [target.x86_64-apple-darwin.dependencies] bitflags-f595c2ba2a3f28df = { package = "bitflags", version = "2.9.4", default-features = false, features = ["std"] } cookie = { version = "0.18.1", default-features = false, features = ["percent-encode"] } -getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.1", default-features = false, features = ["std"] } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2", "ring", "webpki-tokio"] } hyper-util = { version = "0.1.17", features = ["full"] } +miniz_oxide = { version = "0.8.5", default-features = false, features = ["with-alloc"] } mio = { version = "1.0.2", features = ["net", "os-ext"] } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = ["fs", "stdio", "termios"] } @@ -333,9 +344,10 @@ rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = [" [target.x86_64-apple-darwin.build-dependencies] bitflags-f595c2ba2a3f28df = { package = "bitflags", version = "2.9.4", default-features = false, features = ["std"] } cookie = { version = "0.18.1", default-features = false, features = ["percent-encode"] } -getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.1", default-features = false, features = ["std"] } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2", "ring", "webpki-tokio"] } hyper-util = { version = "0.1.17", features = ["full"] } +miniz_oxide = { version = "0.8.5", default-features = false, features = ["with-alloc"] } mio = { version = "1.0.2", features = ["net", "os-ext"] } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = ["fs", "stdio", "termios"] } @@ -343,9 +355,10 @@ rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = [" [target.aarch64-apple-darwin.dependencies] bitflags-f595c2ba2a3f28df = { package = "bitflags", version = "2.9.4", default-features = false, features = ["std"] } cookie = { version = "0.18.1", default-features = false, features = ["percent-encode"] } -getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.1", default-features = false, features = ["std"] } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2", "ring", "webpki-tokio"] } hyper-util = { version = "0.1.17", features = ["full"] } +miniz_oxide = { version = "0.8.5", default-features = false, features = ["with-alloc"] } mio = { version = "1.0.2", features = ["net", "os-ext"] } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = ["fs", "stdio", "termios"] } @@ -353,9 +366,10 @@ rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = [" [target.aarch64-apple-darwin.build-dependencies] bitflags-f595c2ba2a3f28df = { package = "bitflags", version = "2.9.4", default-features = false, features = ["std"] } cookie = { version = "0.18.1", default-features = false, features = ["percent-encode"] } -getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.1", default-features = false, features = ["std"] } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2", "ring", "webpki-tokio"] } hyper-util = { version = "0.1.17", features = ["full"] } +miniz_oxide = { version = "0.8.5", default-features = false, features = ["with-alloc"] } mio = { version = "1.0.2", features = ["net", "os-ext"] } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } rustix-dff4ba8e3ae991db = { package = "rustix", version = "1.0.7", features = ["fs", "stdio", "termios"] } @@ -365,11 +379,12 @@ bitflags-f595c2ba2a3f28df = { package = "bitflags", version = "2.9.4", default-f cookie = { version = "0.18.1", default-features = false, features = ["percent-encode"] } dof-468e82937335b1c9 = { package = "dof", version = "0.3.0", default-features = false, features = ["des"] } dof-9fbad63c4bcf4a8f = { package = "dof", version = "0.4.0", default-features = false, features = ["des"] } -getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.1", default-features = false, features = ["std"] } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2", "ring", "webpki-tokio"] } hyper-util = { version = "0.1.17", features = ["full"] } itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12.1" } itertools-93f6ce9d446188ac = { package = "itertools", version = "0.10.5" } +miniz_oxide = { version = "0.8.5", default-features = false, features = ["with-alloc"] } mio = { version = "1.0.2", features = ["net", "os-ext"] } nom = { version = "7.1.3" } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } @@ -383,11 +398,12 @@ clang-sys = { version = "1.8.1", default-features = false, features = ["clang_11 cookie = { version = "0.18.1", default-features = false, features = ["percent-encode"] } dof-468e82937335b1c9 = { package = "dof", version = "0.3.0", default-features = false, features = ["des"] } dof-9fbad63c4bcf4a8f = { package = "dof", version = "0.4.0", default-features = false, features = ["des"] } -getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.1", default-features = false, features = ["std"] } +getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.4", default-features = false, features = ["std"] } hyper-rustls = { version = "0.27.7", features = ["http2", "ring", "webpki-tokio"] } hyper-util = { version = "0.1.17", features = ["full"] } itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12.1" } itertools-93f6ce9d446188ac = { package = "itertools", version = "0.10.5" } +miniz_oxide = { version = "0.8.5", default-features = false, features = ["with-alloc"] } mio = { version = "1.0.2", features = ["net", "os-ext"] } nom = { version = "7.1.3" } rustix-d585fab2519d2d1 = { package = "rustix", version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] }