mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
85 lines
3.5 KiB
Zig
85 lines
3.5 KiB
Zig
const std = @import("../std.zig");
|
|
const builtin = @import("builtin");
|
|
const unicode = std.unicode;
|
|
const mem = std.mem;
|
|
const fs = std.fs;
|
|
const os = std.os;
|
|
|
|
pub const GetAppDataDirError = error{
|
|
OutOfMemory,
|
|
AppDataDirUnavailable,
|
|
};
|
|
|
|
/// Caller owns returned memory.
|
|
/// TODO determine if we can remove the allocator requirement
|
|
pub fn getAppDataDir(allocator: mem.Allocator, appname: []const u8) GetAppDataDirError![]u8 {
|
|
switch (builtin.os.tag) {
|
|
.windows => {
|
|
var dir_path_ptr: [*:0]u16 = undefined;
|
|
switch (os.windows.shell32.SHGetKnownFolderPath(
|
|
&os.windows.FOLDERID_LocalAppData,
|
|
os.windows.KF_FLAG_CREATE,
|
|
null,
|
|
&dir_path_ptr,
|
|
)) {
|
|
os.windows.S_OK => {
|
|
defer os.windows.ole32.CoTaskMemFree(dir_path_ptr);
|
|
const global_dir = unicode.utf16leToUtf8Alloc(allocator, mem.sliceTo(dir_path_ptr, 0)) catch |err| switch (err) {
|
|
error.UnexpectedSecondSurrogateHalf => return error.AppDataDirUnavailable,
|
|
error.ExpectedSecondSurrogateHalf => return error.AppDataDirUnavailable,
|
|
error.DanglingSurrogateHalf => return error.AppDataDirUnavailable,
|
|
error.OutOfMemory => return error.OutOfMemory,
|
|
};
|
|
defer allocator.free(global_dir);
|
|
return fs.path.join(allocator, &[_][]const u8{ global_dir, appname });
|
|
},
|
|
os.windows.E_OUTOFMEMORY => return error.OutOfMemory,
|
|
else => return error.AppDataDirUnavailable,
|
|
}
|
|
},
|
|
.macos => {
|
|
const home_dir = os.getenv("HOME") orelse {
|
|
// TODO look in /etc/passwd
|
|
return error.AppDataDirUnavailable;
|
|
};
|
|
return fs.path.join(allocator, &[_][]const u8{ home_dir, "Library", "Application Support", appname });
|
|
},
|
|
.linux, .freebsd, .netbsd, .dragonfly, .openbsd, .solaris, .illumos => {
|
|
if (os.getenv("XDG_DATA_HOME")) |xdg| {
|
|
return fs.path.join(allocator, &[_][]const u8{ xdg, appname });
|
|
}
|
|
|
|
const home_dir = os.getenv("HOME") orelse {
|
|
// TODO look in /etc/passwd
|
|
return error.AppDataDirUnavailable;
|
|
};
|
|
return fs.path.join(allocator, &[_][]const u8{ home_dir, ".local", "share", appname });
|
|
},
|
|
.haiku => {
|
|
var dir_path_ptr: [*:0]u8 = undefined;
|
|
if (true) {
|
|
_ = &dir_path_ptr;
|
|
@compileError("TODO: init dir_path_ptr");
|
|
}
|
|
// TODO look into directory_which
|
|
const be_user_settings = 0xbbe;
|
|
const rc = os.system.find_directory(be_user_settings, -1, true, dir_path_ptr, 1);
|
|
const settings_dir = try allocator.dupeZ(u8, mem.sliceTo(dir_path_ptr, 0));
|
|
defer allocator.free(settings_dir);
|
|
switch (rc) {
|
|
0 => return fs.path.join(allocator, &[_][]const u8{ settings_dir, appname }),
|
|
else => return error.AppDataDirUnavailable,
|
|
}
|
|
},
|
|
else => @compileError("Unsupported OS"),
|
|
}
|
|
}
|
|
|
|
test "getAppDataDir" {
|
|
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
|
|
|
// We can't actually validate the result
|
|
const dir = getAppDataDir(std.testing.allocator, "zig") catch return;
|
|
defer std.testing.allocator.free(dir);
|
|
}
|