Skip to main content

print_report

Function print_report 

Source
pub fn print_report(
    report: &SecurityReport,
    format: &OutputFormat,
    output_file: Option<&PathBuf>,
) -> Result<()>
Examples found in repository?
examples/simple_analysis.rs (line 39)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    // Analyze a single executable file
11    let file_path = PathBuf::from("/bin/ls");
12    
13    println!("Analyzing: {}", file_path.display());
14    
15    match analyze_file(&file_path) {
16        Ok(result) => {
17            println!("\n=== Analysis Results ===");
18            println!("File: {}", result.file_path);
19            println!("Type: {}", result.file_type);
20            println!("Status: {}", result.overall_status);
21            
22            println!("\n=== Security Checks ===");
23            for (check, value) in &result.checks {
24                println!("  {}: {}", check, value);
25            }
26            
27            // Create a report and print it in human-readable format
28            println!("\n=== Formatted Report ===");
29            let report = SecurityReport {
30                files: vec![result],
31                summary: ReportSummary {
32                    total_files: 1,
33                    secure_files: 1,
34                    insecure_files: 0,
35                    unsupported_files: 0,
36                },
37            };
38            
39            print_report(&report, &OutputFormat::Human, None)?;
40        }
41        Err(e) => {
42            eprintln!("Failed to analyze file: {}", e);
43            std::process::exit(1);
44        }
45    }
46    
47    Ok(())
48}
More examples
Hide additional examples
examples/json_output.rs (line 53)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    // Analyze multiple files
11    let files = vec![
12        PathBuf::from("/bin/ls"),
13        PathBuf::from("/bin/cat"),
14        PathBuf::from("/bin/echo"),
15    ];
16    
17    let mut results = Vec::new();
18    let mut secure_count = 0;
19    let mut insecure_count = 0;
20    let mut unsupported_count = 0;
21    
22    println!("Analyzing {} files...", files.len());
23    
24    for file_path in files {
25        match analyze_file(&file_path) {
26            Ok(result) => {
27                match result.overall_status.as_str() {
28                    "Secure" => secure_count += 1,
29                    "Mostly Secure" | "Insecure" => insecure_count += 1,
30                    _ => unsupported_count += 1,
31                }
32                results.push(result);
33            }
34            Err(e) => {
35                eprintln!("Warning: Failed to analyze {}: {}", file_path.display(), e);
36                unsupported_count += 1;
37            }
38        }
39    }
40    
41    // Create report
42    let report = SecurityReport {
43        files: results,
44        summary: ReportSummary {
45            total_files: secure_count + insecure_count + unsupported_count,
46            secure_files: secure_count,
47            insecure_files: insecure_count,
48            unsupported_files: unsupported_count,
49        },
50    };
51    
52    println!("\n=== JSON Output ===");
53    print_report(&report, &OutputFormat::Json, None)?;
54    
55    Ok(())
56}
examples/directory_scan.rs (line 33)
9fn main() -> Result<(), Box<dyn std::error::Error>> {
10    // Configure scan options
11    let options = ScanOptions {
12        recursive: false,        // Only scan top level
13        issues_only: true,       // Only show files with security issues
14        strict: false,          // Don't exit on issues
15        file_filter: FileFilter::All, // All executable types
16        one_filesystem: false,   // Allow crossing filesystem boundaries
17    };
18    
19    // Scan a directory (adjust path as needed)
20    let scan_path = PathBuf::from("/usr/bin");
21    println!("Scanning directory: {} (issues only)", scan_path.display());
22    
23    match scan_directory(&scan_path, &options) {
24        Ok(report) => {
25            println!("\n=== Scan Summary ===");
26            println!("Total files analyzed: {}", report.summary.total_files);
27            println!("Secure files: {}", report.summary.secure_files);
28            println!("Files with issues: {}", report.summary.insecure_files);
29            println!("Unsupported files: {}", report.summary.unsupported_files);
30            
31            if report.summary.insecure_files > 0 {
32                println!("\n=== Files with Security Issues ===");
33                print_report(&report, &OutputFormat::Human, None)?;
34            } else {
35                println!("\nAll analyzed files have good security posture! ✓");
36            }
37        }
38        Err(e) => {
39            eprintln!("Failed to scan directory: {}", e);
40            std::process::exit(1);
41        }
42    }
43    
44    Ok(())
45}
examples/fat_binary_analysis.rs (lines 71-79)
11fn main() -> Result<(), Box<dyn std::error::Error>> {
12    println!("=== ExeCheck Fat Binary Analysis Example ===");
13    println!();
14    
15    // Example fat binary paths (these may not exist on all systems)
16    let potential_fat_binaries = vec![
17        "/Applications/Xcode.app/Contents/MacOS/Xcode",
18        "/System/Applications/Calculator.app/Contents/MacOS/Calculator",
19        "/usr/bin/python3",
20        "/bin/bash",
21    ];
22    
23    println!("Searching for fat binaries on the system...");
24    println!();
25    
26    let mut found_examples = false;
27    
28    for binary_path in potential_fat_binaries {
29        let path = PathBuf::from(binary_path);
30        
31        if path.exists() {
32            println!("Analyzing: {}", binary_path);
33            
34            match analyze_file(&path) {
35                Ok(result) => {
36                    // Check if this is a fat binary
37                    if result.file_type.contains("Fat") {
38                        found_examples = true;
39                        
40                        println!("✅ Found fat binary!");
41                        println!("   File Type: {}", result.file_type);
42                        println!("   Status: {}", result.overall_status);
43                        
44                        if let Some(arch_count) = result.checks.get("architectures") {
45                            println!("   Architectures: {}", arch_count);
46                        }
47                        
48                        // Show per-architecture security details
49                        if let Some(total_archs) = result.checks.get("total_architectures") {
50                            println!("   Total Architectures: {}", total_archs);
51                        }
52                        if let Some(secure_archs) = result.checks.get("secure_architectures") {
53                            println!("   Secure Architectures: {}", secure_archs);
54                        }
55                        if let Some(arch_list) = result.checks.get("architectures") {
56                            println!("   Architecture List: {}", arch_list);
57                        }
58                        
59                        // Show individual architecture security checks
60                        println!("   Per-Architecture Security:");
61                        for (key, value) in &result.checks {
62                            if key.contains("_pie") || key.contains("_canary") || key.contains("_nx") {
63                                println!("     {}: {}", key, value);
64                            }
65                        }
66                        
67                        println!();
68                        
69                        // Show detailed report in JSON format
70                        println!("Detailed JSON Report:");
71                        print_report(&execheck::SecurityReport {
72                            files: vec![result],
73                            summary: execheck::ReportSummary {
74                                total_files: 1,
75                                secure_files: 0,
76                                insecure_files: 0,
77                                unsupported_files: 1,
78                            },
79                        }, &OutputFormat::Json, None)?;
80                        
81                        println!("\n{}\n", "=".repeat(60));
82                    } else {
83                        println!("   Not a fat binary ({})", result.file_type);
84                    }
85                }
86                Err(e) => {
87                    println!("   Error analyzing: {}", e);
88                }
89            }
90        } else {
91            println!("Skipping: {} (not found)", binary_path);
92        }
93    }
94    
95    if !found_examples {
96        // Create a demonstration with mock data
97        println!("No fat binaries found on system. Showing example output:");
98        println!();
99        
100        demonstrate_fat_binary_output()?;
101    }
102    
103    println!("=== Fat Binary Analysis Notes ===");
104    println!();
105    println!("Current Status:");
106    println!("• ✅ Fat binary detection and architecture counting");
107    println!("• ✅ Per-architecture security analysis"); 
108    println!("• ✅ Architecture-specific security checks (e.g., 'x86_64_pie', 'arm64_canary')");
109    println!("• ✅ Combined security status (Secure/Mixed/Insecure)");
110    println!();
111    println!("Fat binaries now show detailed architecture-specific security analysis,");
112    println!("allowing you to see security features for each architecture independently.");
113    
114    Ok(())
115}
116
117/// Demonstrate what fat binary output will look like when fully implemented
118fn demonstrate_fat_binary_output() -> Result<(), Box<dyn std::error::Error>> {
119    use std::collections::HashMap;
120    
121    println!("Example Fat Binary Analysis (Mock Data):");
122    println!();
123    
124    // Create a mock fat binary result showing the full implementation
125    let mut checks = HashMap::new();
126    checks.insert("total_architectures".to_string(), "2".to_string());
127    checks.insert("secure_architectures".to_string(), "1".to_string());
128    checks.insert("architectures".to_string(), "x86_64, arm64".to_string());
129    
130    // Per-architecture security checks
131    checks.insert("x86_64_pie".to_string(), "PIE Enabled".to_string());
132    checks.insert("arm64_pie".to_string(), "PIE Enabled".to_string());
133    checks.insert("x86_64_canary".to_string(), "Canary Found".to_string());
134    checks.insert("arm64_canary".to_string(), "No Canary Found".to_string());
135    checks.insert("x86_64_nx".to_string(), "NX enabled".to_string());
136    checks.insert("arm64_nx".to_string(), "NX enabled".to_string());
137    
138    let mock_result = execheck::SecurityCheck {
139        file_path: "/example/universal_app".to_string(),
140        file_type: "Mach-O Fat (2 archs)".to_string(),
141        checks,
142        overall_status: "Mixed".to_string(),
143    };
144    
145    let report = execheck::SecurityReport {
146        files: vec![mock_result],
147        summary: execheck::ReportSummary {
148            total_files: 1,
149            secure_files: 0,
150            insecure_files: 1,
151            unsupported_files: 0,
152        },
153    };
154    
155    // Show current output
156    println!("Current Output (Human Format):");
157    print_report(&report, &OutputFormat::Human, None)?;
158    
159    println!("\nFuture Enhanced Output (When Fully Implemented):");
160    println!("File: /example/universal_app");
161    println!("Type: Mach-O Fat (2 archs)");
162    println!("Status: ⚠ Mixed");
163    println!("Security Checks:");
164    println!("  X86_64 Architecture:");
165    println!("    PIE           : ✓ PIE Enabled");
166    println!("    Stack Canary  : ✓ Canary Found");
167    println!("    NX            : ✓ NX enabled");
168    println!();
169    println!("  ARM64 Architecture:");
170    println!("    PIE           : ✓ PIE Enabled");
171    println!("    Stack Canary  : ✗ No Canary Found");
172    println!("    NX            : ✓ NX enabled");
173    
174    Ok(())
175}
examples/advanced_filtering.rs (line 148)
12fn main() -> Result<(), Box<dyn std::error::Error>> {
13    println!("=== ExeCheck Advanced Filtering Example ===\n");
14
15    // Example 1: Filter only Windows executables (.exe)
16    println!("1. Scanning for Windows executables (.exe files only):");
17    let exe_options = ScanOptions {
18        recursive: false,
19        issues_only: false,
20        strict: false,
21        file_filter: FileFilter::WindowsExecutables,
22        one_filesystem: false,
23    };
24    
25    if let Ok(exe_files) = collect_executable_files(&PathBuf::from("."), &exe_options) {
26        println!("   Found {} .exe files", exe_files.len());
27        for file in exe_files.iter().take(3) {
28            println!("   - {}", file.display());
29        }
30    } else {
31        println!("   No .exe files found or error occurred");
32    }
33
34    // Example 2: Filter only Windows DLLs (.dll)
35    println!("\n2. Scanning for Windows DLLs (.dll files only):");
36    let dll_options = ScanOptions {
37        recursive: false,
38        issues_only: false,
39        strict: false,
40        file_filter: FileFilter::WindowsDlls,
41        one_filesystem: false,
42    };
43    
44    if let Ok(dll_files) = collect_executable_files(&PathBuf::from("."), &dll_options) {
45        println!("   Found {} .dll files", dll_files.len());
46        for file in dll_files.iter().take(3) {
47            println!("   - {}", file.display());
48        }
49    } else {
50        println!("   No .dll files found or error occurred");
51    }
52
53    // Example 3: Custom extension filtering
54    println!("\n3. Custom extension filtering (exe, dll, so, dylib):");
55    let custom_extensions = vec![
56        "exe".to_string(),
57        "dll".to_string(), 
58        "so".to_string(),
59        "dylib".to_string(),
60    ];
61    
62    let custom_options = ScanOptions {
63        recursive: true,
64        issues_only: false,
65        strict: false,
66        file_filter: FileFilter::Extensions(custom_extensions),
67        one_filesystem: false,
68    };
69    
70    if let Ok(custom_files) = collect_executable_files(&PathBuf::from("."), &custom_options) {
71        println!("   Found {} files with custom extensions", custom_files.len());
72        for file in custom_files.iter().take(5) {
73            println!("   - {}", file.display());
74        }
75    } else {
76        println!("   No files with custom extensions found or error occurred");
77    }
78
79    // Example 4: Custom predicate filtering
80    println!("\n4. Custom predicate filtering (files containing 'lib' in name):");
81    let lib_filter = |path: &std::path::Path| {
82        path.file_name()
83            .and_then(|name| name.to_str())
84            .map_or(false, |name| name.to_lowercase().contains("lib"))
85    };
86    
87    let predicate_options = ScanOptions {
88        recursive: true,
89        issues_only: false,
90        strict: false,
91        file_filter: FileFilter::Custom(lib_filter),
92        one_filesystem: false,
93    };
94    
95    if let Ok(lib_files) = collect_executable_files(&PathBuf::from("/usr/lib"), &predicate_options) {
96        println!("   Found {} library files", lib_files.len());
97        for file in lib_files.iter().take(5) {
98            println!("   - {}", file.display());
99        }
100    } else {
101        println!("   Error scanning /usr/lib or no library files found");
102    }
103
104    // Example 5: Filesystem boundary demonstration (Unix only)
105    #[cfg(unix)]
106    {
107        println!("\n5. Filesystem boundary scanning (Unix only):");
108        let boundary_options = ScanOptions {
109            recursive: true,
110            issues_only: false,
111            strict: false,
112            file_filter: FileFilter::All,
113            one_filesystem: true, // Stay within single filesystem
114        };
115        
116        if let Ok(boundary_files) = collect_executable_files(&PathBuf::from("/"), &boundary_options) {
117            println!("   Found {} files within root filesystem", boundary_files.len());
118            println!("   (This prevents crossing into /proc, /sys, mounted drives, etc.)");
119        } else {
120            println!("   Error scanning root filesystem with boundary restrictions");
121        }
122    }
123    
124    #[cfg(not(unix))]
125    {
126        println!("\n5. Filesystem boundary scanning:");
127        println!("   (Not supported on this platform - Unix-like systems only)");
128    }
129
130    // Example 6: Practical use case - analyze only PE files in a directory
131    println!("\n6. Practical example - Analyze Windows executables and DLLs with JSON output:");
132    
133    let analysis_options = ScanOptions {
134        recursive: true,
135        issues_only: true, // Only show files with security issues
136        strict: false,
137        file_filter: FileFilter::WindowsExecutablesAndDlls,
138        one_filesystem: false,
139    };
140    
141    // Try to analyze current directory for demo purposes
142    if let Ok(files) = collect_executable_files(&PathBuf::from("."), &analysis_options) {
143        if !files.is_empty() {
144            let report = analyze_files(files, &analysis_options)?;
145            
146            if !report.files.is_empty() {
147                println!("   Analysis results (JSON format):");
148                print_report(&report, &OutputFormat::Json, None)?;
149            } else {
150                println!("   No security issues found in Windows executables/DLLs!");
151            }
152        } else {
153            println!("   No Windows executables or DLLs found in current directory");
154        }
155    }
156
157    println!("\n=== Advanced Filtering Example Complete ===");
158    Ok(())
159}