aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/src/os
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-05-07 18:29:21 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-05-07 18:29:21 +0300
commitdcfe11a7588fcd42471159453810abc9b7720a57 (patch)
treec32a77266028e73ca2382b96c96f8438a5fcd621 /vendor/libghostty-vt/src/os
parent2dfed860103c4e4505ac7f25def9fe37da1e1e6a (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.zig33
-rw-r--r--vendor/libghostty-vt/src/os/file.zig103
-rw-r--r--vendor/libghostty-vt/src/os/flatpak.zig15
-rw-r--r--vendor/libghostty-vt/src/os/i18n_locales.zig3
-rw-r--r--vendor/libghostty-vt/src/os/main.zig2
-rw-r--r--vendor/libghostty-vt/src/os/windows.zig6
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;