authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-17 18:36:47-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-18 17:43:36-04:00
log3e4a3fa5b7faadaae0a57088baa392e2bb52fe38
tree1d48d805c26c3551a88b865582e76cf25bc8ef23
parentfd3a41dadc92e7b69b409af5f747004996465032

self-hosted: find libc on linux


5 files changed, 326 insertions(+), 61 deletions(-)

src-self-hosted/compilation.zig+25-10
...@@ -28,6 +28,7 @@ const Span = errmsg.Span;...@@ -28,6 +28,7 @@ const Span = errmsg.Span;
28const codegen = @import("codegen.zig");28const codegen = @import("codegen.zig");
29const Package = @import("package.zig").Package;29const Package = @import("package.zig").Package;
30const link = @import("link.zig").link;30const link = @import("link.zig").link;
31const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
3132
32/// Data that is local to the event loop.33/// Data that is local to the event loop.
33pub const EventLoopLocal = struct {34pub const EventLoopLocal = struct {
...@@ -37,6 +38,8 @@ pub const EventLoopLocal = struct {...@@ -37,6 +38,8 @@ pub const EventLoopLocal = struct {
37 /// TODO pool these so that it doesn't have to lock38 /// TODO pool these so that it doesn't have to lock
38 prng: event.Locked(std.rand.DefaultPrng),39 prng: event.Locked(std.rand.DefaultPrng),
3940
41 native_libc: event.Future(LibCInstallation),
42
40 var lazy_init_targets = std.lazyInit(void);43 var lazy_init_targets = std.lazyInit(void);
4144
42 fn init(loop: *event.Loop) !EventLoopLocal {45 fn init(loop: *event.Loop) !EventLoopLocal {
...@@ -52,6 +55,7 @@ pub const EventLoopLocal = struct {...@@ -52,6 +55,7 @@ pub const EventLoopLocal = struct {
52 .loop = loop,55 .loop = loop,
53 .llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(),56 .llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(),
54 .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)),57 .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)),
58 .native_libc = event.Future(LibCInstallation).init(loop),
55 };59 };
56 }60 }
5761
...@@ -78,6 +82,13 @@ pub const EventLoopLocal = struct {...@@ -78,6 +82,13 @@ pub const EventLoopLocal = struct {
7882
79 return LlvmHandle{ .node = node };83 return LlvmHandle{ .node = node };
80 }84 }
85
86 pub async fn getNativeLibC(self: *EventLoopLocal) !*LibCInstallation {
87 if (await (async self.native_libc.start() catch unreachable)) |ptr| return ptr;
88 try await (async self.native_libc.data.findNative(self.loop) catch unreachable);
89 self.native_libc.resolve();
90 return &self.native_libc.data;
91 }
81};92};
8293
83pub const LlvmHandle = struct {94pub const LlvmHandle = struct {
...@@ -109,11 +120,6 @@ pub const Compilation = struct {...@@ -109,11 +120,6 @@ pub const Compilation = struct {
109120
110 linker_script: ?[]const u8,121 linker_script: ?[]const u8,
111 cache_dir: []const u8,122 cache_dir: []const u8,
112 libc_lib_dir: ?[]const u8,
113 libc_static_lib_dir: ?[]const u8,
114 libc_include_dir: ?[]const u8,
115 msvc_lib_dir: ?[]const u8,
116 kernel32_lib_dir: ?[]const u8,
117 dynamic_linker: ?[]const u8,123 dynamic_linker: ?[]const u8,
118 out_h_path: ?[]const u8,124 out_h_path: ?[]const u8,
119125
...@@ -318,11 +324,6 @@ pub const Compilation = struct {...@@ -318,11 +324,6 @@ pub const Compilation = struct {
318 .verbose_link = false,324 .verbose_link = false,
319325
320 .linker_script = null,326 .linker_script = null,
321 .libc_lib_dir = null,
322 .libc_static_lib_dir = null,
323 .libc_include_dir = null,
324 .msvc_lib_dir = null,
325 .kernel32_lib_dir = null,
326 .dynamic_linker = null,327 .dynamic_linker = null,
327 .out_h_path = null,328 .out_h_path = null,
328 .is_test = false,329 .is_test = false,
...@@ -762,10 +763,24 @@ pub const Compilation = struct {...@@ -762,10 +763,24 @@ pub const Compilation = struct {
762 try self.link_libs_list.append(link_lib);763 try self.link_libs_list.append(link_lib);
763 if (is_libc) {764 if (is_libc) {
764 self.libc_link_lib = link_lib;765 self.libc_link_lib = link_lib;
766
767 // get a head start on looking for the native libc
768 if (self.target == Target.Native) {
769 try async<self.loop.allocator> self.startFindingNativeLibC();
770 }
765 }771 }
766 return link_lib;772 return link_lib;
767 }773 }
768774
775 /// cancels itself so no need to await or cancel the promise.
776 async fn startFindingNativeLibC(self: *Compilation) void {
777 // we don't care if it fails, we're just trying to kick off the future resolution
778 _ = (await (async self.loop.call(EventLoopLocal.getNativeLibC, self.event_loop_local) catch unreachable)) catch {};
779 suspend |p| {
780 cancel p;
781 }
782 }
783
769 /// General Purpose Allocator. Must free when done.784 /// General Purpose Allocator. Must free when done.
770 fn gpa(self: Compilation) *mem.Allocator {785 fn gpa(self: Compilation) *mem.Allocator {
771 return self.loop.allocator;786 return self.loop.allocator;
src-self-hosted/libc_installation.zig created+234
...@@ -0,0 +1,234 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const event = std.event;
4
5pub const LibCInstallation = struct {
6 /// The directory that contains `stdlib.h`.
7 /// On Linux, can be found with: `cc -E -Wp,-v -xc /dev/null`
8 include_dir: []const u8,
9
10 /// The directory that contains `crt1.o`.
11 /// On Linux, can be found with `cc -print-file-name=crt1.o`.
12 /// Not needed when targeting MacOS.
13 lib_dir: ?[]const u8,
14
15 /// The directory that contains `crtbegin.o`.
16 /// On Linux, can be found with `cc -print-file-name=crt1.o`.
17 /// Not needed when targeting MacOS or Windows.
18 static_lib_dir: ?[]const u8,
19
20 /// The directory that contains `vcruntime.lib`.
21 /// Only needed when targeting Windows.
22 msvc_lib_dir: ?[]const u8,
23
24 /// The directory that contains `kernel32.lib`.
25 /// Only needed when targeting Windows.
26 kernel32_lib_dir: ?[]const u8,
27
28 pub const Error = error{
29 OutOfMemory,
30 FileSystem,
31 UnableToSpawnCCompiler,
32 CCompilerExitCode,
33 CCompilerCrashed,
34 CCompilerCannotFindHeaders,
35 CCompilerCannotFindCRuntime,
36 LibCStdLibHeaderNotFound,
37 };
38
39 /// Finds the default, native libc.
40 pub async fn findNative(self: *LibCInstallation, loop: *event.Loop) !void {
41 self.* = LibCInstallation{
42 .lib_dir = null,
43 .include_dir = ([*]const u8)(undefined)[0..0],
44 .static_lib_dir = null,
45 .msvc_lib_dir = null,
46 .kernel32_lib_dir = null,
47 };
48 var group = event.Group(Error!void).init(loop);
49 switch (builtin.os) {
50 builtin.Os.windows => {
51 try group.call(findNativeIncludeDirWindows, self, loop);
52 try group.call(findNativeLibDirWindows, self, loop);
53 try group.call(findNativeMsvcLibDir, self, loop);
54 try group.call(findNativeKernel32LibDir, self, loop);
55 },
56 builtin.Os.linux => {
57 try group.call(findNativeIncludeDirLinux, self, loop);
58 try group.call(findNativeLibDirLinux, self, loop);
59 try group.call(findNativeStaticLibDir, self, loop);
60 },
61 builtin.Os.macosx => {
62 try group.call(findNativeIncludeDirMacOS, self, loop);
63 },
64 else => @compileError("unimplemented: find libc for this OS"),
65 }
66 return await (async group.wait() catch unreachable);
67 }
68
69 async fn findNativeIncludeDirLinux(self: *LibCInstallation, loop: *event.Loop) !void {
70 const cc_exe = std.os.getEnvPosix("CC") orelse "cc";
71 const argv = []const []const u8{
72 cc_exe,
73 "-E",
74 "-Wp,-v",
75 "-xc",
76 "/dev/null",
77 };
78 // TODO make this use event loop
79 const errorable_result = std.os.ChildProcess.exec(loop.allocator, argv, null, null, 1024 * 1024);
80 const exec_result = if (std.debug.runtime_safety) blk: {
81 break :blk errorable_result catch unreachable;
82 } else blk: {
83 break :blk errorable_result catch |err| switch (err) {
84 error.OutOfMemory => return error.OutOfMemory,
85 else => return error.UnableToSpawnCCompiler,
86 };
87 };
88 defer {
89 loop.allocator.free(exec_result.stdout);
90 loop.allocator.free(exec_result.stderr);
91 }
92
93 switch (exec_result.term) {
94 std.os.ChildProcess.Term.Exited => |code| {
95 if (code != 0) return error.CCompilerExitCode;
96 },
97 else => {
98 return error.CCompilerCrashed;
99 },
100 }
101
102 var it = std.mem.split(exec_result.stderr, "\n\r");
103 var search_paths = std.ArrayList([]const u8).init(loop.allocator);
104 defer search_paths.deinit();
105 while (it.next()) |line| {
106 if (line.len != 0 and line[0] == ' ') {
107 try search_paths.append(line);
108 }
109 }
110 if (search_paths.len == 0) {
111 return error.CCompilerCannotFindHeaders;
112 }
113
114 // search in reverse order
115 var path_i: usize = 0;
116 while (path_i < search_paths.len) : (path_i += 1) {
117 const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1);
118 const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " ");
119 const stdlib_path = try std.os.path.join(loop.allocator, search_path, "stdlib.h");
120 defer loop.allocator.free(stdlib_path);
121
122 if (std.os.File.access(loop.allocator, stdlib_path)) |_| {
123 self.include_dir = try std.mem.dupe(loop.allocator, u8, search_path);
124 return;
125 } else |err| switch (err) {
126 error.NotFound, error.PermissionDenied => continue,
127 error.OutOfMemory => return error.OutOfMemory,
128 else => return error.FileSystem,
129 }
130 }
131
132 return error.LibCStdLibHeaderNotFound;
133 }
134
135 async fn findNativeIncludeDirWindows(self: *LibCInstallation, loop: *event.Loop) !void {
136 // TODO
137 //ZigWindowsSDK *sdk = get_windows_sdk(g);
138 //g->libc_include_dir = buf_alloc();
139 //if (os_get_win32_ucrt_include_path(sdk, g->libc_include_dir)) {
140 // fprintf(stderr, "Unable to determine libc include path. --libc-include-dir");
141 // exit(1);
142 //}
143 @panic("TODO");
144 }
145
146 async fn findNativeIncludeDirMacOS(self: *LibCInstallation, loop: *event.Loop) !void {
147 self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include");
148 }
149
150 async fn findNativeLibDirWindows(self: *LibCInstallation, loop: *event.Loop) Error!void {
151 // TODO
152 //ZigWindowsSDK *sdk = get_windows_sdk(g);
153
154 //if (g->msvc_lib_dir == nullptr) {
155 // Buf* vc_lib_dir = buf_alloc();
156 // if (os_get_win32_vcruntime_path(vc_lib_dir, g->zig_target.arch.arch)) {
157 // fprintf(stderr, "Unable to determine vcruntime path. --msvc-lib-dir");
158 // exit(1);
159 // }
160 // g->msvc_lib_dir = vc_lib_dir;
161 //}
162
163 //if (g->libc_lib_dir == nullptr) {
164 // Buf* ucrt_lib_path = buf_alloc();
165 // if (os_get_win32_ucrt_lib_path(sdk, ucrt_lib_path, g->zig_target.arch.arch)) {
166 // fprintf(stderr, "Unable to determine ucrt path. --libc-lib-dir");
167 // exit(1);
168 // }
169 // g->libc_lib_dir = ucrt_lib_path;
170 //}
171
172 //if (g->kernel32_lib_dir == nullptr) {
173 // Buf* kern_lib_path = buf_alloc();
174 // if (os_get_win32_kern32_path(sdk, kern_lib_path, g->zig_target.arch.arch)) {
175 // fprintf(stderr, "Unable to determine kernel32 path. --kernel32-lib-dir");
176 // exit(1);
177 // }
178 // g->kernel32_lib_dir = kern_lib_path;
179 //}
180 @panic("TODO");
181 }
182
183 async fn findNativeLibDirLinux(self: *LibCInstallation, loop: *event.Loop) Error!void {
184 self.lib_dir = try await (async ccPrintFileNameDir(loop, "crt1.o") catch unreachable);
185 }
186
187 async fn findNativeStaticLibDir(self: *LibCInstallation, loop: *event.Loop) Error!void {
188 self.static_lib_dir = try await (async ccPrintFileNameDir(loop, "crtbegin.o") catch unreachable);
189 }
190
191 async fn findNativeMsvcLibDir(self: *LibCInstallation, loop: *event.Loop) Error!void {
192 @panic("TODO");
193 }
194
195 async fn findNativeKernel32LibDir(self: *LibCInstallation, loop: *event.Loop) Error!void {
196 @panic("TODO");
197 }
198};
199
200/// caller owns returned memory
201async fn ccPrintFileNameDir(loop: *event.Loop, o_file: []const u8) ![]u8 {
202 const cc_exe = std.os.getEnvPosix("CC") orelse "cc";
203 const arg1 = try std.fmt.allocPrint(loop.allocator, "-print-file-name={}", o_file);
204 defer loop.allocator.free(arg1);
205 const argv = []const []const u8{ cc_exe, arg1 };
206
207 // TODO evented I/O
208 const errorable_result = std.os.ChildProcess.exec(loop.allocator, argv, null, null, 1024 * 1024);
209 const exec_result = if (std.debug.runtime_safety) blk: {
210 break :blk errorable_result catch unreachable;
211 } else blk: {
212 break :blk errorable_result catch |err| switch (err) {
213 error.OutOfMemory => return error.OutOfMemory,
214 else => return error.UnableToSpawnCCompiler,
215 };
216 };
217 defer {
218 loop.allocator.free(exec_result.stdout);
219 loop.allocator.free(exec_result.stderr);
220 }
221 switch (exec_result.term) {
222 std.os.ChildProcess.Term.Exited => |code| {
223 if (code != 0) return error.CCompilerExitCode;
224 },
225 else => {
226 return error.CCompilerCrashed;
227 },
228 }
229 var it = std.mem.split(exec_result.stdout, "\n\r");
230 const line = it.next() orelse return error.CCompilerCannotFindCRuntime;
231 const dirname = std.os.path.dirname(line) orelse return error.CCompilerCannotFindCRuntime;
232
233 return std.mem.dupe(loop.allocator, u8, dirname);
234}
src-self-hosted/main.zig+40-25
...@@ -31,6 +31,7 @@ const usage =...@@ -31,6 +31,7 @@ const usage =
31 \\ build-exe [source] Create executable from source or object files31 \\ build-exe [source] Create executable from source or object files
32 \\ build-lib [source] Create library from source or object files32 \\ build-lib [source] Create library from source or object files
33 \\ build-obj [source] Create object from source or assembly33 \\ build-obj [source] Create object from source or assembly
34 \\ find-libc Show native libc installation paths
34 \\ fmt [source] Parse file and render in canonical zig format35 \\ fmt [source] Parse file and render in canonical zig format
35 \\ targets List available compilation targets36 \\ targets List available compilation targets
36 \\ version Print version number and exit37 \\ version Print version number and exit
...@@ -81,6 +82,10 @@ pub fn main() !void {...@@ -81,6 +82,10 @@ pub fn main() !void {
81 .name = "build-obj",82 .name = "build-obj",
82 .exec = cmdBuildObj,83 .exec = cmdBuildObj,
83 },84 },
85 Command{
86 .name = "find-libc",
87 .exec = cmdFindLibc,
88 },
84 Command{89 Command{
85 .name = "fmt",90 .name = "fmt",
86 .exec = cmdFmt,91 .exec = cmdFmt,
...@@ -134,7 +139,6 @@ const usage_build_generic =...@@ -134,7 +139,6 @@ const usage_build_generic =
134 \\ --cache-dir [path] Override the cache directory139 \\ --cache-dir [path] Override the cache directory
135 \\ --emit [filetype] Emit a specific file format as compilation output140 \\ --emit [filetype] Emit a specific file format as compilation output
136 \\ --enable-timing-info Print timing diagnostics141 \\ --enable-timing-info Print timing diagnostics
137 \\ --libc-include-dir [path] Directory where libc stdlib.h resides
138 \\ --name [name] Override output name142 \\ --name [name] Override output name
139 \\ --output [file] Override destination path143 \\ --output [file] Override destination path
140 \\ --output-h [file] Override generated header file path144 \\ --output-h [file] Override generated header file path
...@@ -165,10 +169,6 @@ const usage_build_generic =...@@ -165,10 +169,6 @@ const usage_build_generic =
165 \\ --ar-path [path] Set the path to ar169 \\ --ar-path [path] Set the path to ar
166 \\ --dynamic-linker [path] Set the path to ld.so170 \\ --dynamic-linker [path] Set the path to ld.so
167 \\ --each-lib-rpath Add rpath for each used dynamic library171 \\ --each-lib-rpath Add rpath for each used dynamic library
168 \\ --libc-lib-dir [path] Directory where libc crt1.o resides
169 \\ --libc-static-lib-dir [path] Directory where libc crtbegin.o resides
170 \\ --msvc-lib-dir [path] (windows) directory where vcruntime.lib resides
171 \\ --kernel32-lib-dir [path] (windows) directory where kernel32.lib resides
172 \\ --library [lib] Link against lib172 \\ --library [lib] Link against lib
173 \\ --forbid-library [lib] Make it an error to link against lib173 \\ --forbid-library [lib] Make it an error to link against lib
174 \\ --library-path [dir] Add a directory to the library search path174 \\ --library-path [dir] Add a directory to the library search path
...@@ -210,7 +210,6 @@ const args_build_generic = []Flag{...@@ -210,7 +210,6 @@ const args_build_generic = []Flag{
210 "llvm-ir",210 "llvm-ir",
211 }),211 }),
212 Flag.Bool("--enable-timing-info"),212 Flag.Bool("--enable-timing-info"),
213 Flag.Arg1("--libc-include-dir"),
214 Flag.Arg1("--name"),213 Flag.Arg1("--name"),
215 Flag.Arg1("--output"),214 Flag.Arg1("--output"),
216 Flag.Arg1("--output-h"),215 Flag.Arg1("--output-h"),
...@@ -236,10 +235,6 @@ const args_build_generic = []Flag{...@@ -236,10 +235,6 @@ const args_build_generic = []Flag{
236 Flag.Arg1("--ar-path"),235 Flag.Arg1("--ar-path"),
237 Flag.Arg1("--dynamic-linker"),236 Flag.Arg1("--dynamic-linker"),
238 Flag.Bool("--each-lib-rpath"),237 Flag.Bool("--each-lib-rpath"),
239 Flag.Arg1("--libc-lib-dir"),
240 Flag.Arg1("--libc-static-lib-dir"),
241 Flag.Arg1("--msvc-lib-dir"),
242 Flag.Arg1("--kernel32-lib-dir"),
243 Flag.ArgMergeN("--library", 1),238 Flag.ArgMergeN("--library", 1),
244 Flag.ArgMergeN("--forbid-library", 1),239 Flag.ArgMergeN("--forbid-library", 1),
245 Flag.ArgMergeN("--library-path", 1),240 Flag.ArgMergeN("--library-path", 1),
...@@ -430,21 +425,6 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -430,21 +425,6 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
430425
431 comp.strip = flags.present("strip");426 comp.strip = flags.present("strip");
432427
433 if (flags.single("libc-lib-dir")) |libc_lib_dir| {
434 comp.libc_lib_dir = libc_lib_dir;
435 }
436 if (flags.single("libc-static-lib-dir")) |libc_static_lib_dir| {
437 comp.libc_static_lib_dir = libc_static_lib_dir;
438 }
439 if (flags.single("libc-include-dir")) |libc_include_dir| {
440 comp.libc_include_dir = libc_include_dir;
441 }
442 if (flags.single("msvc-lib-dir")) |msvc_lib_dir| {
443 comp.msvc_lib_dir = msvc_lib_dir;
444 }
445 if (flags.single("kernel32-lib-dir")) |kernel32_lib_dir| {
446 comp.kernel32_lib_dir = kernel32_lib_dir;
447 }
448 if (flags.single("dynamic-linker")) |dynamic_linker| {428 if (flags.single("dynamic-linker")) |dynamic_linker| {
449 comp.dynamic_linker = dynamic_linker;429 comp.dynamic_linker = dynamic_linker;
450 }430 }
...@@ -579,6 +559,41 @@ const Fmt = struct {...@@ -579,6 +559,41 @@ const Fmt = struct {
579 }559 }
580};560};
581561
562fn cmdFindLibc(allocator: *Allocator, args: []const []const u8) !void {
563 var loop: event.Loop = undefined;
564 try loop.initMultiThreaded(allocator);
565 defer loop.deinit();
566
567 var event_loop_local = try EventLoopLocal.init(&loop);
568 defer event_loop_local.deinit();
569
570 const handle = try async<loop.allocator> findLibCAsync(&event_loop_local);
571 defer cancel handle;
572
573 loop.run();
574}
575
576async fn findLibCAsync(event_loop_local: *EventLoopLocal) void {
577 const libc = (await (async event_loop_local.getNativeLibC() catch unreachable)) catch |err| {
578 stderr.print("unable to find libc: {}\n", @errorName(err)) catch os.exit(1);
579 os.exit(1);
580 };
581 stderr.print(
582 \\include_dir={}
583 \\lib_dir={}
584 \\static_lib_dir={}
585 \\msvc_lib_dir={}
586 \\kernel32_lib_dir={}
587 \\
588 ,
589 libc.include_dir,
590 libc.lib_dir,
591 libc.static_lib_dir orelse "",
592 libc.msvc_lib_dir orelse "",
593 libc.kernel32_lib_dir orelse "",
594 ) catch os.exit(1);
595}
596
582fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {597fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
583 var flags = try Args.parse(allocator, args_fmt_spec, args);598 var flags = try Args.parse(allocator, args_fmt_spec, args);
584 defer flags.deinit();599 defer flags.deinit();
std/fmt/index.zig+6-2
...@@ -785,11 +785,15 @@ pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) ![]u8 {...@@ -785,11 +785,15 @@ pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) ![]u8 {
785 return buf[0 .. buf.len - context.remaining.len];785 return buf[0 .. buf.len - context.remaining.len];
786}786}
787787
788pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: ...) ![]u8 {788pub const AllocPrintError = error{OutOfMemory};
789
790pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: ...) AllocPrintError![]u8 {
789 var size: usize = 0;791 var size: usize = 0;
790 format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {};792 format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {};
791 const buf = try allocator.alloc(u8, size);793 const buf = try allocator.alloc(u8, size);
792 return bufPrint(buf, fmt, args);794 return bufPrint(buf, fmt, args) catch |err| switch (err) {
795 error.BufferTooSmall => unreachable, // we just counted the size above
796 };
793}797}
794798
795fn countSize(size: *usize, bytes: []const u8) (error{}!void) {799fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
std/os/file.zig+21-24
...@@ -109,43 +109,40 @@ pub const File = struct {...@@ -109,43 +109,40 @@ pub const File = struct {
109 Unexpected,109 Unexpected,
110 };110 };
111111
112 pub fn access(allocator: *mem.Allocator, path: []const u8, file_mode: os.FileMode) AccessError!bool {112 pub fn access(allocator: *mem.Allocator, path: []const u8) AccessError!void {
113 const path_with_null = try std.cstr.addNullByte(allocator, path);113 const path_with_null = try std.cstr.addNullByte(allocator, path);
114 defer allocator.free(path_with_null);114 defer allocator.free(path_with_null);
115115
116 if (is_posix) {116 if (is_posix) {
117 // mode is ignored and is always F_OK for now
118 const result = posix.access(path_with_null.ptr, posix.F_OK);117 const result = posix.access(path_with_null.ptr, posix.F_OK);
119 const err = posix.getErrno(result);118 const err = posix.getErrno(result);
120 if (err > 0) {119 switch (err) {
121 return switch (err) {120 0 => return,
122 posix.EACCES => error.PermissionDenied,121 posix.EACCES => return error.PermissionDenied,
123 posix.EROFS => error.PermissionDenied,122 posix.EROFS => return error.PermissionDenied,
124 posix.ELOOP => error.PermissionDenied,123 posix.ELOOP => return error.PermissionDenied,
125 posix.ETXTBSY => error.PermissionDenied,124 posix.ETXTBSY => return error.PermissionDenied,
126 posix.ENOTDIR => error.NotFound,125 posix.ENOTDIR => return error.NotFound,
127 posix.ENOENT => error.NotFound,126 posix.ENOENT => return error.NotFound,
128127
129 posix.ENAMETOOLONG => error.NameTooLong,128 posix.ENAMETOOLONG => return error.NameTooLong,
130 posix.EINVAL => error.BadMode,129 posix.EINVAL => unreachable,
131 posix.EFAULT => error.BadPathName,130 posix.EFAULT => return error.BadPathName,
132 posix.EIO => error.Io,131 posix.EIO => return error.Io,
133 posix.ENOMEM => error.SystemResources,132 posix.ENOMEM => return error.SystemResources,
134 else => os.unexpectedErrorPosix(err),133 else => return os.unexpectedErrorPosix(err),
135 };
136 }134 }
137 return true;
138 } else if (is_windows) {135 } else if (is_windows) {
139 if (os.windows.GetFileAttributesA(path_with_null.ptr) != os.windows.INVALID_FILE_ATTRIBUTES) {136 if (os.windows.GetFileAttributesA(path_with_null.ptr) != os.windows.INVALID_FILE_ATTRIBUTES) {
140 return true;137 return;
141 }138 }
142139
143 const err = windows.GetLastError();140 const err = windows.GetLastError();
144 return switch (err) {141 switch (err) {
145 windows.ERROR.FILE_NOT_FOUND => error.NotFound,142 windows.ERROR.FILE_NOT_FOUND => return error.NotFound,
146 windows.ERROR.ACCESS_DENIED => error.PermissionDenied,143 windows.ERROR.ACCESS_DENIED => return error.PermissionDenied,
147 else => os.unexpectedErrorWindows(err),144 else => return os.unexpectedErrorWindows(err),
148 };145 }
149 } else {146 } else {
150 @compileError("TODO implement access for this OS");147 @compileError("TODO implement access for this OS");
151 }148 }