diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-07 18:29:21 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-07 18:29:21 +0300 |
| commit | dcfe11a7588fcd42471159453810abc9b7720a57 (patch) | |
| tree | c32a77266028e73ca2382b96c96f8438a5fcd621 /vendor/libghostty-vt/src/os | |
| parent | 2dfed860103c4e4505ac7f25def9fe37da1e1e6a (diff) | |
build: update libghostty-vt vendor
vendor ghostty 063ac3e and remove the musl libc++ link workaround.
expose the new selection formatter and hyperlink uri apis for follow-up rendering work.
add manual artifact validation for static linux builds.
Diffstat (limited to 'vendor/libghostty-vt/src/os')
| -rw-r--r-- | vendor/libghostty-vt/src/os/TempDir.zig | 33 | ||||
| -rw-r--r-- | vendor/libghostty-vt/src/os/file.zig | 103 | ||||
| -rw-r--r-- | vendor/libghostty-vt/src/os/flatpak.zig | 15 | ||||
| -rw-r--r-- | vendor/libghostty-vt/src/os/i18n_locales.zig | 3 | ||||
| -rw-r--r-- | vendor/libghostty-vt/src/os/main.zig | 2 | ||||
| -rw-r--r-- | vendor/libghostty-vt/src/os/windows.zig | 6 |
6 files changed, 121 insertions, 41 deletions
diff --git a/vendor/libghostty-vt/src/os/TempDir.zig b/vendor/libghostty-vt/src/os/TempDir.zig index 2ddf18da..c3d344d9 100644 --- a/vendor/libghostty-vt/src/os/TempDir.zig +++ b/vendor/libghostty-vt/src/os/TempDir.zig @@ -3,10 +3,8 @@ const TempDir = @This(); const std = @import("std"); -const testing = std.testing; const Dir = std.fs.Dir; -const allocTmpDir = @import("file.zig").allocTmpDir; -const freeTmpDir = @import("file.zig").freeTmpDir; +const file = @import("file.zig"); const log = std.log.scoped(.tempdir); @@ -18,28 +16,26 @@ parent: Dir, /// Name buffer that name points into. Generally do not use. To get the /// name call the name() function. -name_buf: [TMP_PATH_LEN:0]u8, +name_buf: [file.random_basename_len:0]u8, /// Create the temporary directory. pub fn init() !TempDir { // Note: the tmp_path_buf sentinel is important because it ensures - // we actually always have TMP_PATH_LEN+1 bytes of available space. We - // need that so we can set the sentinel in the case we use all the - // possible length. - var tmp_path_buf: [TMP_PATH_LEN:0]u8 = undefined; - var rand_buf: [RANDOM_BYTES]u8 = undefined; + // we actually always have random_basename_len+1 bytes of available + // space. We need that so we can set the sentinel in the case we use + // all the possible length. + var tmp_path_buf: [file.random_basename_len:0]u8 = undefined; const dir = dir: { const cwd = std.fs.cwd(); - const tmp_dir = allocTmpDir(std.heap.page_allocator) orelse break :dir cwd; - defer freeTmpDir(std.heap.page_allocator, tmp_dir); + const tmp_dir = try file.allocTmpDir(std.heap.page_allocator); + defer file.freeTmpDir(std.heap.page_allocator, tmp_dir); break :dir try cwd.openDir(tmp_dir, .{}); }; // We now loop forever until we can find a directory that we can create. while (true) { - std.crypto.random.bytes(rand_buf[0..]); - const tmp_path = b64_encoder.encode(&tmp_path_buf, &rand_buf); + const tmp_path = try file.randomBasename(&tmp_path_buf); tmp_path_buf[tmp_path.len] = 0; dir.makeDir(tmp_path) catch |err| switch (err) { @@ -69,16 +65,9 @@ pub fn deinit(self: *TempDir) void { log.err("error deleting temp dir err={}", .{err}); } -// The amount of random bytes to get to determine our filename. -const RANDOM_BYTES = 16; -const TMP_PATH_LEN = b64_encoder.calcSize(RANDOM_BYTES); - -// Base64 encoder, replacing the standard `+/` with `-_` so that it can -// be used in a file name on any filesystem. -const b64_encoder = std.base64.Base64Encoder.init(b64_alphabet, null); -const b64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".*; - test { + const testing = std.testing; + var td = try init(); errdefer td.deinit(); diff --git a/vendor/libghostty-vt/src/os/file.zig b/vendor/libghostty-vt/src/os/file.zig index 240c936e..6007ae49 100644 --- a/vendor/libghostty-vt/src/os/file.zig +++ b/vendor/libghostty-vt/src/os/file.zig @@ -1,6 +1,7 @@ const std = @import("std"); const builtin = @import("builtin"); const posix = std.posix; +const windows = @import("windows.zig"); const log = std.log.scoped(.os); @@ -53,27 +54,95 @@ pub fn restoreMaxFiles(lim: rlimit) void { posix.setrlimit(.NOFILE, lim) catch {}; } -/// Return the recommended path for temporary files. -/// This may not actually allocate memory, use freeTmpDir to properly -/// free the memory when applicable. -pub fn allocTmpDir(allocator: std.mem.Allocator) ?[]const u8 { +/// Return the recommended path for temporary files. Any trailing +/// path separator is stripped so callers can safely join with their +/// own separator (e.g. `"{tmp}/{name}"`). +/// +/// On Windows this calls `GetTempPathW` and allocates a UTF-8 copy +/// (or duplicates a hard-fallback string if the syscall fails). On +/// POSIX this returns `$TMPDIR`/`$TMP` (or `"/tmp"` as a fallback) +/// without allocating. Always pair with `freeTmpDir` to release any +/// allocation. +pub fn allocTmpDir(allocator: std.mem.Allocator) std.mem.Allocator.Error![]const u8 { if (builtin.os.tag == .windows) { - // TODO: what is a good fallback path on windows? - const v = std.process.getenvW(std.unicode.utf8ToUtf16LeStringLiteral("TMP")) orelse return null; - return std.unicode.utf16LeToUtf8Alloc(allocator, v) catch |e| { - log.warn("failed to convert temp dir path from windows string: {}", .{e}); - return null; - }; + // GetTempPathW guarantees the result fits in MAX_PATH+1. + var buf: [windows.MAX_PATH + 1:0]u16 = undefined; + const len = windows.exp.kernel32.GetTempPathW(buf.len, &buf); + if (len > 0) { + // Trim the UTF-16 string before encoding as UT8-8 so that the + // returned slice's length matches its underlying allocation. + const trimmed = std.mem.trimEnd(u16, buf[0..len], &.{std.fs.path.sep}); + if (std.unicode.utf16LeToUtf8Alloc(allocator, trimmed)) |utf8| { + return utf8; + } else |e| switch (e) { + error.OutOfMemory => return error.OutOfMemory, + else => log.warn("failed to convert temp dir path from windows string: {}", .{e}), + } + } + return allocator.dupe(u8, "C:\\Windows\\Temp"); } - if (posix.getenv("TMPDIR")) |v| return v; - if (posix.getenv("TMP")) |v| return v; - return "/tmp"; + const tmpdir = posix.getenv("TMPDIR") orelse posix.getenv("TMP") orelse return "/tmp"; + return std.mem.trimEnd(u8, tmpdir, &.{std.fs.path.sep}); } -/// Free a path returned by tmpDir if it allocated memory. -/// This is a "no-op" for all platforms except windows. +/// Free a path returned by `allocTmpDir` if it allocated memory. +/// This is a no-op on POSIX. pub fn freeTmpDir(allocator: std.mem.Allocator, dir: []const u8) void { - if (builtin.os.tag == .windows) { - allocator.free(dir); + if (builtin.os.tag != .windows) return; + allocator.free(dir); +} + +const random_basename_bytes = 16; +const b64_encoder = std.base64.url_safe_no_pad.Encoder; + +pub const RandomBasenameError = error{BufferTooSmall}; + +/// Length of the basename produced by `randomBasename`. +pub const random_basename_len = b64_encoder.calcSize(random_basename_bytes); + +/// Write a random filesystem-safe base64 basename of length +/// `random_basename_len` into `buf` and return a slice over the +/// written bytes. Returns `error.BufferTooSmall` if `buf` is too +/// short. +pub fn randomBasename(buf: []u8) RandomBasenameError![]const u8 { + if (buf.len < random_basename_len) return error.BufferTooSmall; + var rand_buf: [random_basename_bytes]u8 = undefined; + std.crypto.random.bytes(&rand_buf); + return b64_encoder.encode(buf[0..random_basename_len], &rand_buf); +} + +/// Return a freshly-allocated path of the form `{TMPDIR}/{prefix}{random}`. +/// The caller owns the returned slice and must free it with `allocator`. +/// +/// Nothing is created on disk; this only builds the path string. Useful +/// for one-shot temporary file/socket paths where a full `TempDir` is +/// overkill. +pub fn randomTmpPath( + allocator: std.mem.Allocator, + prefix: []const u8, +) std.mem.Allocator.Error![]u8 { + const tmp_dir = try allocTmpDir(allocator); + defer freeTmpDir(allocator, tmp_dir); + var name_buf: [random_basename_len]u8 = undefined; + const basename = randomBasename(&name_buf) catch unreachable; + return std.fmt.allocPrint( + allocator, + "{s}{c}{s}{s}", + .{ tmp_dir, std.fs.path.sep, prefix, basename }, + ); +} + +test randomBasename { + const testing = std.testing; + + var buf: [random_basename_len]u8 = undefined; + const name = try randomBasename(&buf); + try testing.expectEqual(random_basename_len, name.len); + for (name) |c| { + const ok = std.ascii.isAlphanumeric(c) or c == '-' or c == '_'; + try testing.expect(ok); } + + var small: [random_basename_len - 1]u8 = undefined; + try testing.expectError(error.BufferTooSmall, randomBasename(&small)); } diff --git a/vendor/libghostty-vt/src/os/flatpak.zig b/vendor/libghostty-vt/src/os/flatpak.zig index 78692089..44f820ad 100644 --- a/vendor/libghostty-vt/src/os/flatpak.zig +++ b/vendor/libghostty-vt/src/os/flatpak.zig @@ -33,6 +33,16 @@ pub const FlatpakHostCommand = struct { @cInclude("gio/gio.h"); @cInclude("gio/gunixfdlist.h"); }); + /// Flags for HostCommand method + /// + /// Ref: https://docs.flatpak.org/en/latest/libflatpak-api-reference.html#gdbus-method-org-freedesktop-Flatpak-Development.HostCommand + const Flags = packed struct(c_uint) { + /// Clear the environment + clear_env: bool = false, + /// Kill the sandbox when the caller disappears from the session bus + watch_bus: bool = false, + _reserved: std.meta.Int(.unsigned, @bitSizeOf(c_uint) - 2) = 0, + }; /// Argv are the arguments to call on the host with argv[0] being /// the command to execute. @@ -366,6 +376,9 @@ pub const FlatpakHostCommand = struct { const g_cwd = c.g_get_current_dir(); defer c.g_free(g_cwd); + // Terminate session if Ghostty drops off the bus (e.g. due to crashes) + const flags: Flags = .{ .watch_bus = true }; + // The params for our RPC call const params = c.g_variant_new( "(^ay^aay@a{uh}@a{ss}u)", @@ -373,7 +386,7 @@ pub const FlatpakHostCommand = struct { args.ptr, c.g_variant_builder_end(fd_builder), c.g_variant_builder_end(env_builder), - @as(c_int, 0), + @as(c_uint, @bitCast(flags)), ); _ = c.g_variant_ref_sink(params); // take ownership defer c.g_variant_unref(params); diff --git a/vendor/libghostty-vt/src/os/i18n_locales.zig b/vendor/libghostty-vt/src/os/i18n_locales.zig index a044bfa4..45556952 100644 --- a/vendor/libghostty-vt/src/os/i18n_locales.zig +++ b/vendor/libghostty-vt/src/os/i18n_locales.zig @@ -4,7 +4,7 @@ /// Supported locales for the application. This must be kept up to date /// with the translations available in the `po/` directory; this is used -/// by our build process as well runtime libghostty APIs. +/// by our build process as well as runtime libghostty APIs. /// /// The order also matters. For incomplete locale information (i.e. only /// a language code available), the first match is used. For example, if @@ -57,4 +57,5 @@ pub const locales = [_][:0]const u8{ "lv", "vi", "kk", + "be", }; diff --git a/vendor/libghostty-vt/src/os/main.zig b/vendor/libghostty-vt/src/os/main.zig index 2aadabac..b3018274 100644 --- a/vendor/libghostty-vt/src/os/main.zig +++ b/vendor/libghostty-vt/src/os/main.zig @@ -52,6 +52,7 @@ pub const fixMaxFiles = file.fixMaxFiles; pub const restoreMaxFiles = file.restoreMaxFiles; pub const allocTmpDir = file.allocTmpDir; pub const freeTmpDir = file.freeTmpDir; +pub const randomTmpPath = file.randomTmpPath; pub const isFlatpak = flatpak.isFlatpak; pub const FlatpakHostCommand = flatpak.FlatpakHostCommand; pub const home = homedir.home; @@ -67,6 +68,7 @@ pub const ShellEscapeWriter = shell.ShellEscapeWriter; pub const getKernelInfo = kernel_info.getKernelInfo; test { + _ = file; _ = i18n; _ = path; _ = uri; diff --git a/vendor/libghostty-vt/src/os/windows.zig b/vendor/libghostty-vt/src/os/windows.zig index e92a5453..6e452fb7 100644 --- a/vendor/libghostty-vt/src/os/windows.zig +++ b/vendor/libghostty-vt/src/os/windows.zig @@ -18,6 +18,7 @@ pub const HANDLE = windows.HANDLE; pub const HANDLE_FLAG_INHERIT = windows.HANDLE_FLAG_INHERIT; pub const INFINITE = windows.INFINITE; pub const INVALID_HANDLE_VALUE = windows.INVALID_HANDLE_VALUE; +pub const MAX_PATH = windows.MAX_PATH; pub const OPEN_EXISTING = windows.OPEN_EXISTING; pub const PIPE_ACCESS_OUTBOUND = windows.PIPE_ACCESS_OUTBOUND; pub const PIPE_TYPE_BYTE = windows.PIPE_TYPE_BYTE; @@ -104,6 +105,11 @@ pub const exp = struct { lpBuffer: windows.LPSTR, nSize: *windows.DWORD, ) callconv(.winapi) windows.BOOL; + /// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppathw + pub extern "kernel32" fn GetTempPathW( + nBufferLength: windows.DWORD, + lpBuffer: windows.LPWSTR, + ) callconv(.winapi) windows.DWORD; }; pub const PROC_THREAD_ATTRIBUTE_NUMBER = 0x0000FFFF; |
