Repository navigation
Expand file tree
/
Copy pathsystem.rs
More file actions
166 lines (144 loc) · 4.94 KB
/
Copy pathsystem.rs
File metadata and controls
166 lines (144 loc) · 4.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//! System utilities for the Cortex CLI.
//!
//! Provides system-level checks and utilities including:
//! - File descriptor limit checking
//! - PATH validation
//! - Locale detection
use anyhow::{Result, bail};
/// Minimum recommended file descriptor limit for Cortex operations.
pub const MIN_RECOMMENDED_FD_LIMIT: u64 = 256;
/// Check file descriptor limits and provide helpful error message if too low.
///
/// This prevents cryptic "Too many open files" errors during operation.
///
/// # Returns
/// `Ok(())` if limits are acceptable, or an error with remediation instructions.
pub fn check_file_descriptor_limits() -> Result<()> {
#[cfg(unix)]
{
let (soft_limit, _hard_limit) = match get_fd_limits() {
Ok(limits) => limits,
Err(e) => {
// If we can't check limits, log a warning but don't fail
tracing::debug!("Could not check file descriptor limits: {}", e);
return Ok(());
}
};
if soft_limit < MIN_RECOMMENDED_FD_LIMIT {
bail!(
"File descriptor limit too low: {} (recommended minimum: {})\n\n\
This may cause 'Too many open files' errors during operation.\n\n\
To increase the limit, run:\n\
\x20 ulimit -n 4096\n\n\
Or add to your shell profile (~/.bashrc or ~/.zshrc):\n\
\x20 ulimit -n 4096",
soft_limit,
MIN_RECOMMENDED_FD_LIMIT
);
}
}
Ok(())
}
/// Get the current soft and hard file descriptor limits.
#[cfg(unix)]
pub fn get_fd_limits() -> Result<(u64, u64)> {
use std::io;
let mut rlim = libc::rlimit {
rlim_cur: 0,
rlim_max: 0,
};
let result = unsafe { libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) };
if result != 0 {
return Err(anyhow::anyhow!(
"getrlimit failed: {}",
io::Error::last_os_error()
));
}
Ok((rlim.rlim_cur, rlim.rlim_max))
}
/// Validate PATH environment variable and return warnings.
///
/// Checks for:
/// - Empty PATH
/// - Non-existent directories in PATH
/// - Unquoted entries with spaces
///
/// # Returns
/// A list of warning messages (empty if no issues found).
pub fn validate_path_environment() -> Vec<String> {
let mut warnings = Vec::new();
if let Ok(path_var) = std::env::var("PATH") {
if path_var.is_empty() {
warnings.push(
"Warning: PATH environment variable is empty. Commands may not be found."
.to_string(),
);
return warnings;
}
let separator = if cfg!(windows) { ';' } else { ':' };
for entry in path_var.split(separator) {
if entry.is_empty() {
continue;
}
// Check for non-existent directories
if !std::path::Path::new(entry).exists() {
warnings.push(format!(
"Warning: PATH contains non-existent directory: {}",
entry
));
}
// Check for entries with spaces (potential issues on some systems)
if entry.contains(' ') && !entry.starts_with('"') {
warnings.push(format!(
"Warning: PATH contains unquoted entry with spaces: {}",
entry
));
}
}
} else {
warnings.push(
"Warning: PATH environment variable is not set. Commands may not be found.".to_string(),
);
}
warnings
}
/// Check if the current locale supports UTF-8.
///
/// Returns `true` if the locale appears to be problematic (C or POSIX locale).
pub fn is_problematic_locale() -> bool {
let lang = std::env::var("LANG").unwrap_or_default();
let lc_all = std::env::var("LC_ALL").unwrap_or_default();
lang == "C" || lang == "POSIX" || lang.is_empty() || lc_all == "C" || lc_all == "POSIX"
}
/// Warn about locale issues that may affect UTF-8 handling.
///
/// # Returns
/// `true` if a warning was emitted.
pub fn warn_about_locale() -> bool {
if is_problematic_locale() {
eprintln!("Warning: Detected C/POSIX locale which may cause UTF-8 encoding issues.");
eprintln!(
"Recommendation: Set LANG=en_US.UTF-8 before running cortex for proper UTF-8 support."
);
return true;
}
false
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_check_fd_limits() {
// Should not error on systems with reasonable limits
let result = check_file_descriptor_limits();
// On CI systems, this might fail, so we just check it doesn't panic
let _ = result;
}
#[test]
fn test_validate_path() {
// Should return a list (possibly empty)
let warnings = validate_path_environment();
// We can't assert on content since it depends on the system
assert!(warnings.len() < 1000); // Sanity check
}
}