diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-02-16 13:25:30 -0500 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2020-02-16 13:25:30 -0500 |
| commit | 4b02a39aa93b0043f05de0d90443051c019643ab (patch) | |
| tree | 12632d2e43bc6e13911d8e88d1f91e84b11106f6 /lib/std/os.zig | |
| parent | 5e37fc0746a75ed319fc57ae62d8cc966382c592 (diff) | |
| download | zig-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.zig | 65 |
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, |
