aboutsummaryrefslogtreecommitdiff
path: root/lib/std/os.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-02-16 13:25:30 -0500
committerAndrew Kelley <andrew@ziglang.org>2020-02-16 13:25:30 -0500
commit4b02a39aa93b0043f05de0d90443051c019643ab (patch)
tree12632d2e43bc6e13911d8e88d1f91e84b11106f6 /lib/std/os.zig
parent5e37fc0746a75ed319fc57ae62d8cc966382c592 (diff)
downloadzig-4b02a39aa93b0043f05de0d90443051c019643ab.tar.gz
zig-4b02a39aa93b0043f05de0d90443051c019643ab.zip
self-hosted libc detection
* libc_installation.cpp is deleted. src-self-hosted/libc_installation.zig is now used for both stage1 and stage2 compilers. * (breaking) move `std.fs.File.access` to `std.fs.Dir.access`. The API now encourages use with an open directory handle. * Add `std.os.faccessat` and related functions. * Deprecate the "C" suffix naming convention for null-terminated parameters. "C" should be used when it is related to libc. However null-terminated parameters often have to do with the native system ABI rather than libc. "Z" suffix is the new convention. For example, `std.os.openC` is deprecated in favor of `std.os.openZ`. * Add `std.mem.dupeZ` for using an allocator to copy memory and add a null terminator. * Remove dead struct field `std.ChildProcess.llnode`. * Introduce `std.event.Batch`. This API allows expressing concurrency without forcing code to be async. It requires no Allocator and does not introduce any failure conditions. However it is not thread-safe. * There is now an ongoing experiment to transition away from `std.event.Group` in favor of `std.event.Batch`. * `std.os.execvpeC` calls `getenvZ` rather than `getenv`. This is slightly more efficient on most systems, and works around a limitation of `getenv` lack of integration with libc. * (breaking) `std.os.AccessError` gains `FileBusy`, `SymLinkLoop`, and `ReadOnlyFileSystem`. Previously these error codes were all reported as `PermissionDenied`. * Add `std.Target.isDragonFlyBSD`. * stage2: access to the windows_sdk functions is done with a manually maintained .zig binding file instead of `@cImport`. * Update src-self-hosted/libc_installation.zig with all the improvements that stage1 has seen to src/libc_installation.cpp until now. In addition, it now takes advantage of Batch so that evented I/O mode takes advantage of concurrency, but it still works in blocking I/O mode, which is how it is used in stage1.
Diffstat (limited to 'lib/std/os.zig')
-rw-r--r--lib/std/os.zig65
1 files changed, 57 insertions, 8 deletions
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 73b6cbb302..fd85f8801b 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -950,7 +950,7 @@ pub fn execvpeC(file: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, e
const file_slice = mem.toSliceConst(u8, file);
if (mem.indexOfScalar(u8, file_slice, '/') != null) return execveC(file, child_argv, envp);
- const PATH = getenv("PATH") orelse "/usr/local/bin:/bin/:/usr/bin";
+ const PATH = getenvZ("PATH") orelse "/usr/local/bin:/bin/:/usr/bin";
var path_buf: [MAX_PATH_BYTES]u8 = undefined;
var it = mem.tokenize(PATH, ":");
var seen_eacces = false;
@@ -1038,7 +1038,7 @@ pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8)
}
/// Get an environment variable.
-/// See also `getenvC`.
+/// See also `getenvZ`.
/// TODO make this go through libc when we have it
pub fn getenv(key: []const u8) ?[]const u8 {
for (environ) |ptr| {
@@ -1056,9 +1056,12 @@ pub fn getenv(key: []const u8) ?[]const u8 {
return null;
}
+/// Deprecated in favor of `getenvZ`.
+pub const getenvC = getenvZ;
+
/// Get an environment variable with a null-terminated name.
/// See also `getenv`.
-pub fn getenvC(key: [*:0]const u8) ?[]const u8 {
+pub fn getenvZ(key: [*:0]const u8) ?[]const u8 {
if (builtin.link_libc) {
const value = system.getenv(key) orelse return null;
return mem.toSliceConst(u8, value);
@@ -2452,6 +2455,9 @@ pub const AccessError = error{
InputOutput,
SystemResources,
BadPathName,
+ FileBusy,
+ SymLinkLoop,
+ ReadOnlyFileSystem,
/// On Windows, file paths must be valid Unicode.
InvalidUtf8,
@@ -2469,8 +2475,11 @@ pub fn access(path: []const u8, mode: u32) AccessError!void {
return accessC(&path_c, mode);
}
+/// Deprecated in favor of `accessZ`.
+pub const accessC = accessZ;
+
/// Same as `access` except `path` is null-terminated.
-pub fn accessC(path: [*:0]const u8, mode: u32) AccessError!void {
+pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void {
if (builtin.os == .windows) {
const path_w = try windows.cStrToPrefixedFileW(path);
_ = try windows.GetFileAttributesW(&path_w);
@@ -2479,12 +2488,11 @@ pub fn accessC(path: [*:0]const u8, mode: u32) AccessError!void {
switch (errno(system.access(path, mode))) {
0 => return,
EACCES => return error.PermissionDenied,
- EROFS => return error.PermissionDenied,
- ELOOP => return error.PermissionDenied,
- ETXTBSY => return error.PermissionDenied,
+ EROFS => return error.ReadOnlyFileSystem,
+ ELOOP => return error.SymLinkLoop,
+ ETXTBSY => return error.FileBusy,
ENOTDIR => return error.FileNotFound,
ENOENT => return error.FileNotFound,
-
ENAMETOOLONG => return error.NameTooLong,
EINVAL => unreachable,
EFAULT => unreachable,
@@ -2510,6 +2518,47 @@ pub fn accessW(path: [*:0]const u16, mode: u32) windows.GetFileAttributesError!v
}
}
+/// Check user's permissions for a file, based on an open directory handle.
+/// TODO currently this ignores `mode` and `flags` on Windows.
+pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessError!void {
+ if (builtin.os == .windows) {
+ const path_w = try windows.sliceToPrefixedFileW(path);
+ return faccessatW(dirfd, &path_w, mode, flags);
+ }
+ const path_c = try toPosixPath(path);
+ return faccessatZ(dirfd, &path_c, mode, flags);
+}
+
+/// Same as `faccessat` except the path parameter is null-terminated.
+pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) AccessError!void {
+ if (builtin.os == .windows) {
+ const path_w = try windows.cStrToPrefixedFileW(path);
+ return faccessatW(dirfd, &path_w, mode, flags);
+ }
+ switch (errno(system.faccessat(dirfd, path, mode, flags))) {
+ 0 => return,
+ EACCES => return error.PermissionDenied,
+ EROFS => return error.ReadOnlyFileSystem,
+ ELOOP => return error.SymLinkLoop,
+ ETXTBSY => return error.FileBusy,
+ ENOTDIR => return error.FileNotFound,
+ ENOENT => return error.FileNotFound,
+ ENAMETOOLONG => return error.NameTooLong,
+ EINVAL => unreachable,
+ EFAULT => unreachable,
+ EIO => return error.InputOutput,
+ ENOMEM => return error.SystemResources,
+ else => |err| return unexpectedErrno(err),
+ }
+}
+
+/// Same as `faccessat` except asserts the target is Windows and the path parameter
+/// is null-terminated WTF-16 encoded.
+/// TODO currently this ignores `mode` and `flags`
+pub fn faccessatW(dirfd: fd_t, path: [*:0]const u16, mode: u32, flags: u32) AccessError!void {
+ @compileError("TODO implement faccessatW on Windows");
+}
+
pub const PipeError = error{
SystemFdQuotaExceeded,
ProcessFdQuotaExceeded,