aboutsummaryrefslogtreecommitdiff
path: root/lib/std/fs/get_app_data_dir.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-09-26 01:54:45 -0400
committerGitHub <noreply@github.com>2019-09-26 01:54:45 -0400
commit68bb3945708c43109c48bda3664176307d45b62c (patch)
treeafb9731e10cef9d192560b52cd9ae2cf179775c4 /lib/std/fs/get_app_data_dir.zig
parent6128bc728d1e1024a178c16c2149f5b1a167a013 (diff)
parent4637e8f9699af9c3c6cf4df50ef5bb67c7a318a4 (diff)
downloadzig-68bb3945708c43109c48bda3664176307d45b62c.tar.gz
zig-68bb3945708c43109c48bda3664176307d45b62c.zip
Merge pull request #3315 from ziglang/mv-std-lib
Move std/ to lib/std/
Diffstat (limited to 'lib/std/fs/get_app_data_dir.zig')
-rw-r--r--lib/std/fs/get_app_data_dir.zig70
1 files changed, 70 insertions, 0 deletions
diff --git a/lib/std/fs/get_app_data_dir.zig b/lib/std/fs/get_app_data_dir.zig
new file mode 100644
index 0000000000..cdab7703f8
--- /dev/null
+++ b/lib/std/fs/get_app_data_dir.zig
@@ -0,0 +1,70 @@
+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) {
+ .windows => {
+ var dir_path_ptr: [*]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(@ptrCast(*c_void, dir_path_ptr));
+ const global_dir = unicode.utf16leToUtf8Alloc(allocator, utf16lePtrSlice(dir_path_ptr)) 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,
+ }
+ },
+ .macosx => {
+ 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 => {
+ 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 });
+ },
+ else => @compileError("Unsupported OS"),
+ }
+}
+
+fn utf16lePtrSlice(ptr: [*]const u16) []const u16 {
+ var index: usize = 0;
+ while (ptr[index] != 0) : (index += 1) {}
+ return ptr[0..index];
+}
+
+test "getAppDataDir" {
+ var buf: [512]u8 = undefined;
+ const allocator = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;
+
+ // We can't actually validate the result
+ _ = getAppDataDir(allocator, "zig") catch return;
+}