fix: preserve non-UTF-8 bytes in OS, config and CLI layers
Zig treats paths, arguments and environment values as byte slices; the port converted them lossily in many places. Now (final-Z1.md): - argv, env (incl. present non-UTF-8 values), HOME, PATH lookup, passwd, resources dir, TMPDIR, cgroup, config path canonicalization, +validate-config, +list-themes and Zig-string escapes (\xFF) keep raw bytes. String-based config values carry bytes via ghostty_os::osbytes, a bijective escape (noncharacter U+FDD0 + byte) that leaves all valid UTF-8 - including Nerd Font private-use icons - unchanged. - os/file rlimit fallbacks exist on all targets. - i18n locale canonicalization is an exact port of libintl's tables (e.g. pa-Guru -> pa_IN). - New ghostty-build-info crate is the single source of version, channel, commit and build mode for all consumers. Test Plan: - cargo test -p ghostty-os -p ghostty-config -p ghostty-cli (incl. randomized osbytes round-trip property tests)
This commit is contained in:
1 parent
e4cdd8e007
commit
395cff8981
32 files changed
+1464
-333
No files matched your search
@@ -70,19 +70,41 @@ pub fn restore_max_files(lim: Rlimit) {
|
||||
let _ = setrlimit(Resource::Nofile, lim);
|
||||
}
|
||||
|
||||
/// Return the recommended path for temporary files.
|
||||
pub fn alloc_tmp_dir() -> Option<String> {
|
||||
/// Resource limit placeholder on platforms without `rlimit` (Zig:
|
||||
/// `rlimit = if (@hasDecl(posix.system, "rlimit")) posix.rlimit else struct {}`).
|
||||
#[cfg(not(unix))]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
|
||||
pub struct Rlimit;
|
||||
|
||||
/// Unsupported-platform fallback: returns `None` like Zig.
|
||||
#[cfg(not(unix))]
|
||||
pub fn fix_max_files() -> Option<Rlimit> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Unsupported-platform fallback: no-op like Zig.
|
||||
#[cfg(not(unix))]
|
||||
pub fn restore_max_files(_lim: Rlimit) {}
|
||||
|
||||
/// Return the recommended path for temporary files (byte-preserving).
|
||||
pub fn alloc_tmp_dir_os() -> Option<std::path::PathBuf> {
|
||||
if cfg!(windows) {
|
||||
// TODO: what is a good fallback path on windows? (same as Zig)
|
||||
return std::env::var_os("TMP").map(|v| v.to_string_lossy().into_owned());
|
||||
return std::env::var_os("TMP").map(Into::into);
|
||||
}
|
||||
if let Some(v) = std::env::var_os("TMPDIR") {
|
||||
return Some(v.to_string_lossy().into_owned());
|
||||
return Some(v.into());
|
||||
}
|
||||
if let Some(v) = std::env::var_os("TMP") {
|
||||
return Some(v.to_string_lossy().into_owned());
|
||||
return Some(v.into());
|
||||
}
|
||||
Some("/tmp".to_owned())
|
||||
Some("/tmp".into())
|
||||
}
|
||||
|
||||
/// Return the recommended path for temporary files. Non-UTF-8 bytes are
|
||||
/// carried via [`crate::osbytes`]; see [`alloc_tmp_dir_os`].
|
||||
pub fn alloc_tmp_dir() -> Option<String> {
|
||||
alloc_tmp_dir_os().map(|p| crate::osbytes::os_to_config_string(p.as_os_str()))
|
||||
}
|
||||
|
||||
#[cfg(all(test, unix))]
|
||||
@@ -103,6 +125,18 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tmp_dir_non_utf8() {
|
||||
use std::os::unix::ffi::{OsStrExt, OsStringExt};
|
||||
let v = std::ffi::OsString::from_vec(b"/tmp/\xff".to_vec());
|
||||
temp_env::with_vars([("TMPDIR", Some(v.clone())), ("TMP", None)], || {
|
||||
assert_eq!(
|
||||
alloc_tmp_dir_os().unwrap().as_os_str().as_bytes(),
|
||||
b"/tmp/\xff"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn fix_and_restore_max_files() {
|
||||
|
||||
Reference in new issue
Block a user