meta data for this page
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| soc:irt:playbooks:windows_disk [2026/06/18 15:44] – titannet | soc:irt:playbooks:windows_disk [2026/06/18 16:51] (current) – [Prefetch on Linux] titannet | ||
|---|---|---|---|
| Line 106: | Line 106: | ||
| <code bash> | <code bash> | ||
| https:// | https:// | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | </ | ||
| + | |||
| + | ==== Prefetch on Linux ==== | ||
| + | |||
| + | <code bash> | ||
| curl --proto ' | curl --proto ' | ||
| Line 111: | Line 120: | ||
| rustup toolchain install 1.85.0 | rustup toolchain install 1.85.0 | ||
| rustup default 1.85.0 | rustup default 1.85.0 | ||
| + | </ | ||
| + | <code rust> | ||
| + | use chrono:: | ||
| + | use std::{env, fs}; | ||
| - | </code> | + | fn filetime_to_datetime(ft: |
| + | // FILETIME epoch (1601-01-01) -> Unix epoch (1970-01-01) | ||
| + | const EPOCH_DIFF_100NS: | ||
| + | let unix_100ns = ft - EPOCH_DIFF_100NS; | ||
| + | let secs = unix_100ns / 10_000_000; | ||
| + | let nanos = ((unix_100ns % 10_000_000) * 100) as u32; | ||
| - | <code rust> | + | DateTime::from_timestamp(secs, |
| - | use anyhow::Result; | + | |
| - | use prefetch_core:: | + | } |
| - | fn main() | + | fn main() { |
| - | let path = std::env::args() | + | let path = env::args() |
| .nth(1) | .nth(1) | ||
| - | .expect(" | + | .expect(" |
| - | let bytes = std::fs:: | + | let raw = fs::read(&path).expect(" |
| - | let pf = parse(&bytes)?; | + | let info = prefetch_core:: |
| + | .unwrap_or_else(|e| panic!(" | ||
| - | println!(" | + | println!(" |
| - | println!(" | + | println!(" |
| - | println!(" | + | println!(" |
| - | for ts in &pf.last_run_times { | + | for ft in &info.last_run_times { |
| - | println!(" | + | println!( |
| + | | ||
| + | filetime_to_datetime(*ft).to_rfc3339(), | ||
| + | ft | ||
| + | | ||
| } | } | ||
| - | | + | |
| + | for v in & | ||
| + | println!(" | ||
| + | |||
| + | let created = filetime_to_datetime(v.creation_time); | ||
| + | println!(" | ||
| + | |||
| + | println!(" | ||
| + | println!(); | ||
| + | } | ||
| } | } | ||
| </ | </ | ||
| + | |||
| <code rust> | <code rust> | ||
| - | use prefetch_core::parse; | + | # |
| + | use std:: | ||
| + | use std::fs; | ||
| + | use std:: | ||
| + | use chrono::{DateTime, Utc}; | ||
| - | fn main() | + | /// based on https:// |
| - | let dir = r" | + | |
| - | for entry in std:: | ||
| - | let path = entry? | ||
| - | if path.extension().and_then(|x| x.to_str()) != Some("pf" | + | fn filetime_to_datetime(ft: |
| - | | + | // FILETIME epoch (1601-01-01) -> Unix epoch (1970-01-01) |
| + | const EPOCH_DIFF_100NS: | ||
| + | |||
| + | let unix_100ns = ft - EPOCH_DIFF_100NS; | ||
| + | let secs = unix_100ns / 10_000_000; | ||
| + | let nanos = ((unix_100ns % 10_000_000) * 100) as u32; | ||
| + | |||
| + | DateTime:: | ||
| + | | ||
| + | } | ||
| + | |||
| + | fn csv_escape(s: | ||
| + | let mut out = String:: | ||
| + | out.push('"' | ||
| + | for c in s.chars() { | ||
| + | match c { | ||
| + | '"' | ||
| + | | ||
| } | } | ||
| + | } | ||
| + | out.push('"' | ||
| + | out | ||
| + | } | ||
| - | | + | fn main() { |
| + | | ||
| + | root.pop(); | ||
| + | let out_dir | ||
| + | .nth(1) | ||
| + | .unwrap_or_else(|| "/ | ||
| + | | ||
| - | match parse(&bytes) { | + | let dir = Path::new("/ |
| - | | + | |
| - | println!( | + | let files: Vec< |
| - | "{} | runs={} | last={:?}", | + | .unwrap() |
| - | | + | .filter_map(Result:: |
| - | | + | .map(|e| e.path()) |
| - | | + | .filter(|p| |
| - | ); | + | |
| - | } | + | .and_then(|ext| ext.to_str()) |
| - | | + | .map(|ext| ext == " |
| - | | + | |
| - | | + | }) |
| - | | + | .map(|p| p.to_string_lossy().to_string()) |
| + | .collect(); | ||
| + | |||
| + | // | ||
| + | | ||
| + | "file, | ||
| + | ); | ||
| + | for name in files { | ||
| + | let p = PathBuf:: | ||
| + | |||
| + | let raw = std:: | ||
| + | let scca = prefetch_core:: | ||
| + | |||
| + | std:: | ||
| + | .expect(" | ||
| + | |||
| + | let info = prefetch_core:: | ||
| + | |||
| + | let filenames = info | ||
| + | .filenames | ||
| + | .iter() | ||
| + | .map(|f| escape(f)) | ||
| + | .collect::< | ||
| + | .join(";" | ||
| + | |||
| + | let volumes | ||
| + | .volumes | ||
| + | .iter() | ||
| + | .map(|v| | ||
| + | format!( | ||
| + | " | ||
| + | | ||
| + | | ||
| + | | ||
| + | ) | ||
| + | }) | ||
| + | | ||
| + | .join(";" | ||
| + | |||
| + | let last_runs | ||
| + | .last_run_times | ||
| + | .iter() | ||
| + | .map(|t| filetime_to_datetime(*t).to_string()) | ||
| + | .collect::< | ||
| + | | ||
| + | |||
| + | println!( | ||
| + | | ||
| + | csv_escape(& | ||
| + | scca.len(), | ||
| + | info.version, | ||
| + | csv_escape(& | ||
| + | | ||
| + | csv_escape(& | ||
| + | info.filenames.len(), | ||
| + | csv_escape(& | ||
| + | csv_escape(& | ||
| + | | ||
| } | } | ||
| + | } | ||
| - | Ok(()) | + | fn escape(s: &str) -> String { |
| + | s.replace(' | ||
| } | } | ||