| author | |
| committer | |
| log | c3eb592a343d25bbb0f79b80104d7890877c7af6 |
| tree | 48d0295374ad0b69edb164e7e9ec61a1a1e01253 |
| parent | 320c4d68f5f40794ae31d5535de9c3a8ff5cb471 |
| parent | 616f74ba2098297fbe430651930f9e784909263f |
| signature |
some API work on std.c, std.os, std.os.wasi47 files changed, 1809 insertions(+), 1992 deletions(-)
ci/aarch64-linux-debug.sh+1-1| ... | @@ -12,7 +12,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.12.0-dev.203+d3bc1cfc4" | ... | @@ -12,7 +12,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.12.0-dev.203+d3bc1cfc4" |
| 12 | PREFIX="$HOME/deps/$CACHE_BASENAME" | 12 | PREFIX="$HOME/deps/$CACHE_BASENAME" |
| 13 | ZIG="$PREFIX/bin/zig" | 13 | ZIG="$PREFIX/bin/zig" |
| 14 | 14 | ||
| 15 | export PATH="$HOME/deps/wasmtime-v2.0.2-$ARCH-linux:$PATH" | 15 | export PATH="$HOME/deps/wasmtime-v10.0.2-$ARCH-linux:$PATH" |
| 16 | 16 | ||
| 17 | # Make the `zig version` number consistent. | 17 | # Make the `zig version` number consistent. |
| 18 | # This will affect the cmake command below. | 18 | # This will affect the cmake command below. |
ci/aarch64-linux-release.sh+1-1| ... | @@ -12,7 +12,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.12.0-dev.203+d3bc1cfc4" | ... | @@ -12,7 +12,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.12.0-dev.203+d3bc1cfc4" |
| 12 | PREFIX="$HOME/deps/$CACHE_BASENAME" | 12 | PREFIX="$HOME/deps/$CACHE_BASENAME" |
| 13 | ZIG="$PREFIX/bin/zig" | 13 | ZIG="$PREFIX/bin/zig" |
| 14 | 14 | ||
| 15 | export PATH="$HOME/deps/wasmtime-v2.0.2-$ARCH-linux:$PATH" | 15 | export PATH="$HOME/deps/wasmtime-v10.0.2-$ARCH-linux:$PATH" |
| 16 | 16 | ||
| 17 | # Make the `zig version` number consistent. | 17 | # Make the `zig version` number consistent. |
| 18 | # This will affect the cmake command below. | 18 | # This will affect the cmake command below. |
ci/x86_64-linux-debug.sh+1-1| ... | @@ -12,7 +12,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.12.0-dev.203+d3bc1cfc4" | ... | @@ -12,7 +12,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.12.0-dev.203+d3bc1cfc4" |
| 12 | PREFIX="$HOME/deps/$CACHE_BASENAME" | 12 | PREFIX="$HOME/deps/$CACHE_BASENAME" |
| 13 | ZIG="$PREFIX/bin/zig" | 13 | ZIG="$PREFIX/bin/zig" |
| 14 | 14 | ||
| 15 | export PATH="$HOME/deps/wasmtime-v2.0.2-$ARCH-linux:$HOME/deps/qemu-linux-x86_64-6.1.0.1/bin:$PATH" | 15 | export PATH="$HOME/deps/wasmtime-v10.0.2-$ARCH-linux:$HOME/deps/qemu-linux-x86_64-6.1.0.1/bin:$PATH" |
| 16 | 16 | ||
| 17 | # Make the `zig version` number consistent. | 17 | # Make the `zig version` number consistent. |
| 18 | # This will affect the cmake command below. | 18 | # This will affect the cmake command below. |
ci/x86_64-linux-release.sh+1-1| ... | @@ -12,7 +12,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.12.0-dev.203+d3bc1cfc4" | ... | @@ -12,7 +12,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.12.0-dev.203+d3bc1cfc4" |
| 12 | PREFIX="$HOME/deps/$CACHE_BASENAME" | 12 | PREFIX="$HOME/deps/$CACHE_BASENAME" |
| 13 | ZIG="$PREFIX/bin/zig" | 13 | ZIG="$PREFIX/bin/zig" |
| 14 | 14 | ||
| 15 | export PATH="$HOME/deps/wasmtime-v2.0.2-$ARCH-linux:$HOME/deps/qemu-linux-x86_64-6.1.0.1/bin:$PATH" | 15 | export PATH="$HOME/deps/wasmtime-v10.0.2-$ARCH-linux:$HOME/deps/qemu-linux-x86_64-6.1.0.1/bin:$PATH" |
| 16 | 16 | ||
| 17 | # Make the `zig version` number consistent. | 17 | # Make the `zig version` number consistent. |
| 18 | # This will affect the cmake command below. | 18 | # This will affect the cmake command below. |
lib/std/c.zig+567-38| ... | @@ -4,6 +4,10 @@ const c = @This(); | ... | @@ -4,6 +4,10 @@ const c = @This(); |
| 4 | const page_size = std.mem.page_size; | 4 | const page_size = std.mem.page_size; |
| 5 | const iovec = std.os.iovec; | 5 | const iovec = std.os.iovec; |
| 6 | const iovec_const = std.os.iovec_const; | 6 | const iovec_const = std.os.iovec_const; |
| 7 | const wasi = @import("c/wasi.zig"); | ||
| 8 | const native_abi = builtin.abi; | ||
| 9 | const native_arch = builtin.cpu.arch; | ||
| 10 | const native_os = builtin.os.tag; | ||
| 7 | 11 | ||
| 8 | /// If not linking libc, returns false. | 12 | /// If not linking libc, returns false. |
| 9 | /// If linking musl libc, returns true. | 13 | /// If linking musl libc, returns true. |
| ... | @@ -13,7 +17,7 @@ const iovec_const = std.os.iovec_const; | ... | @@ -13,7 +17,7 @@ const iovec_const = std.os.iovec_const; |
| 13 | pub inline fn versionCheck(comptime glibc_version: std.SemanticVersion) bool { | 17 | pub inline fn versionCheck(comptime glibc_version: std.SemanticVersion) bool { |
| 14 | return comptime blk: { | 18 | return comptime blk: { |
| 15 | if (!builtin.link_libc) break :blk false; | 19 | if (!builtin.link_libc) break :blk false; |
| 16 | if (builtin.abi.isMusl()) break :blk true; | 20 | if (native_abi.isMusl()) break :blk true; |
| 17 | if (builtin.target.isGnuLibC()) { | 21 | if (builtin.target.isGnuLibC()) { |
| 18 | const ver = builtin.os.version_range.linux.glibc; | 22 | const ver = builtin.os.version_range.linux.glibc; |
| 19 | const order = ver.order(glibc_version); | 23 | const order = ver.order(glibc_version); |
| ... | @@ -27,7 +31,7 @@ pub inline fn versionCheck(comptime glibc_version: std.SemanticVersion) bool { | ... | @@ -27,7 +31,7 @@ pub inline fn versionCheck(comptime glibc_version: std.SemanticVersion) bool { |
| 27 | }; | 31 | }; |
| 28 | } | 32 | } |
| 29 | 33 | ||
| 30 | pub usingnamespace switch (builtin.os.tag) { | 34 | pub usingnamespace switch (native_os) { |
| 31 | .linux => @import("c/linux.zig"), | 35 | .linux => @import("c/linux.zig"), |
| 32 | .windows => @import("c/windows.zig"), | 36 | .windows => @import("c/windows.zig"), |
| 33 | .macos, .ios, .tvos, .watchos => @import("c/darwin.zig"), | 37 | .macos, .ios, .tvos, .watchos => @import("c/darwin.zig"), |
| ... | @@ -36,16 +40,504 @@ pub usingnamespace switch (builtin.os.tag) { | ... | @@ -36,16 +40,504 @@ pub usingnamespace switch (builtin.os.tag) { |
| 36 | .dragonfly => @import("c/dragonfly.zig"), | 40 | .dragonfly => @import("c/dragonfly.zig"), |
| 37 | .openbsd => @import("c/openbsd.zig"), | 41 | .openbsd => @import("c/openbsd.zig"), |
| 38 | .haiku => @import("c/haiku.zig"), | 42 | .haiku => @import("c/haiku.zig"), |
| 39 | .hermit => @import("c/hermit.zig"), | ||
| 40 | .solaris, .illumos => @import("c/solaris.zig"), | 43 | .solaris, .illumos => @import("c/solaris.zig"), |
| 41 | .fuchsia => @import("c/fuchsia.zig"), | ||
| 42 | .minix => @import("c/minix.zig"), | ||
| 43 | .emscripten => @import("c/emscripten.zig"), | 44 | .emscripten => @import("c/emscripten.zig"), |
| 44 | .wasi => @import("c/wasi.zig"), | 45 | .wasi => wasi, |
| 45 | else => struct {}, | 46 | else => struct {}, |
| 46 | }; | 47 | }; |
| 47 | 48 | ||
| 48 | pub const MAP = switch (builtin.os.tag) { | 49 | pub const pthread_mutex_t = switch (native_os) { |
| 50 | .linux, .minix => extern struct { | ||
| 51 | data: [data_len]u8 align(@alignOf(usize)) = [_]u8{0} ** data_len, | ||
| 52 | |||
| 53 | const data_len = switch (native_abi) { | ||
| 54 | .musl, .musleabi, .musleabihf => if (@sizeOf(usize) == 8) 40 else 24, | ||
| 55 | .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => switch (native_arch) { | ||
| 56 | .aarch64 => 48, | ||
| 57 | .x86_64 => if (native_abi == .gnux32) 40 else 32, | ||
| 58 | .mips64, .powerpc64, .powerpc64le, .sparc64 => 40, | ||
| 59 | else => if (@sizeOf(usize) == 8) 40 else 24, | ||
| 60 | }, | ||
| 61 | .android => if (@sizeOf(usize) == 8) 40 else 4, | ||
| 62 | else => @compileError("unsupported ABI"), | ||
| 63 | }; | ||
| 64 | }, | ||
| 65 | .macos, .ios, .tvos, .watchos => extern struct { | ||
| 66 | sig: c_long = 0x32AAABA7, | ||
| 67 | data: [data_len]u8 = [_]u8{0} ** data_len, | ||
| 68 | |||
| 69 | const data_len = if (@sizeOf(usize) == 8) 56 else 40; | ||
| 70 | }, | ||
| 71 | .freebsd, .kfreebsd, .dragonfly, .openbsd => extern struct { | ||
| 72 | inner: ?*anyopaque = null, | ||
| 73 | }, | ||
| 74 | .hermit => extern struct { | ||
| 75 | ptr: usize = std.math.maxInt(usize), | ||
| 76 | }, | ||
| 77 | .netbsd => extern struct { | ||
| 78 | magic: u32 = 0x33330003, | ||
| 79 | errorcheck: c.padded_pthread_spin_t = 0, | ||
| 80 | ceiling: c.padded_pthread_spin_t = 0, | ||
| 81 | owner: usize = 0, | ||
| 82 | waiters: ?*u8 = null, | ||
| 83 | recursed: u32 = 0, | ||
| 84 | spare2: ?*anyopaque = null, | ||
| 85 | }, | ||
| 86 | .haiku => extern struct { | ||
| 87 | flags: u32 = 0, | ||
| 88 | lock: i32 = 0, | ||
| 89 | unused: i32 = -42, | ||
| 90 | owner: i32 = -1, | ||
| 91 | owner_count: i32 = 0, | ||
| 92 | }, | ||
| 93 | .solaris, .illumos => extern struct { | ||
| 94 | flag1: u16 = 0, | ||
| 95 | flag2: u8 = 0, | ||
| 96 | ceiling: u8 = 0, | ||
| 97 | type: u16 = 0, | ||
| 98 | magic: u16 = 0x4d58, | ||
| 99 | lock: u64 = 0, | ||
| 100 | data: u64 = 0, | ||
| 101 | }, | ||
| 102 | .fuchsia => extern struct { | ||
| 103 | data: [40]u8 align(@alignOf(usize)) = [_]u8{0} ** 40, | ||
| 104 | }, | ||
| 105 | .emscripten => extern struct { | ||
| 106 | data: [24]u8 align(4) = [_]u8{0} ** 24, | ||
| 107 | }, | ||
| 108 | else => @compileError("target libc does not have pthread_mutex_t"), | ||
| 109 | }; | ||
| 110 | |||
| 111 | pub const pthread_cond_t = switch (native_os) { | ||
| 112 | .linux => extern struct { | ||
| 113 | data: [48]u8 align(@alignOf(usize)) = [_]u8{0} ** 48, | ||
| 114 | }, | ||
| 115 | .macos, .ios, .tvos, .watchos => extern struct { | ||
| 116 | sig: c_long = 0x3CB0B1BB, | ||
| 117 | data: [data_len]u8 = [_]u8{0} ** data_len, | ||
| 118 | const data_len = if (@sizeOf(usize) == 8) 40 else 24; | ||
| 119 | }, | ||
| 120 | .freebsd, .kfreebsd, .dragonfly, .openbsd => extern struct { | ||
| 121 | inner: ?*anyopaque = null, | ||
| 122 | }, | ||
| 123 | .hermit => extern struct { | ||
| 124 | ptr: usize = std.math.maxInt(usize), | ||
| 125 | }, | ||
| 126 | .netbsd => extern struct { | ||
| 127 | magic: u32 = 0x55550005, | ||
| 128 | lock: c.pthread_spin_t = 0, | ||
| 129 | waiters_first: ?*u8 = null, | ||
| 130 | waiters_last: ?*u8 = null, | ||
| 131 | mutex: ?*pthread_mutex_t = null, | ||
| 132 | private: ?*anyopaque = null, | ||
| 133 | }, | ||
| 134 | .haiku => extern struct { | ||
| 135 | flags: u32 = 0, | ||
| 136 | unused: i32 = -42, | ||
| 137 | mutex: ?*anyopaque = null, | ||
| 138 | waiter_count: i32 = 0, | ||
| 139 | lock: i32 = 0, | ||
| 140 | }, | ||
| 141 | .solaris, .illumos => extern struct { | ||
| 142 | flag: [4]u8 = [_]u8{0} ** 4, | ||
| 143 | type: u16 = 0, | ||
| 144 | magic: u16 = 0x4356, | ||
| 145 | data: u64 = 0, | ||
| 146 | }, | ||
| 147 | .fuchsia, .minix, .emscripten => extern struct { | ||
| 148 | data: [48]u8 align(@alignOf(usize)) = [_]u8{0} ** 48, | ||
| 149 | }, | ||
| 150 | else => @compileError("target libc does not have pthread_cond_t"), | ||
| 151 | }; | ||
| 152 | |||
| 153 | pub const pthread_rwlock_t = switch (native_os) { | ||
| 154 | .linux => switch (native_abi) { | ||
| 155 | .android => switch (@sizeOf(usize)) { | ||
| 156 | 4 => extern struct { | ||
| 157 | data: [40]u8 align(@alignOf(usize)) = [_]u8{0} ** 40, | ||
| 158 | }, | ||
| 159 | 8 => extern struct { | ||
| 160 | data: [56]u8 align(@alignOf(usize)) = [_]u8{0} ** 56, | ||
| 161 | }, | ||
| 162 | else => @compileError("impossible pointer size"), | ||
| 163 | }, | ||
| 164 | else => extern struct { | ||
| 165 | data: [56]u8 align(@alignOf(usize)) = [_]u8{0} ** 56, | ||
| 166 | }, | ||
| 167 | }, | ||
| 168 | .macos, .ios, .tvos, .watchos => extern struct { | ||
| 169 | sig: c_long = 0x2DA8B3B4, | ||
| 170 | data: [192]u8 = [_]u8{0} ** 192, | ||
| 171 | }, | ||
| 172 | .freebsd, .kfreebsd, .dragonfly, .openbsd => extern struct { | ||
| 173 | ptr: ?*anyopaque = null, | ||
| 174 | }, | ||
| 175 | .hermit => extern struct { | ||
| 176 | ptr: usize = std.math.maxInt(usize), | ||
| 177 | }, | ||
| 178 | .netbsd => extern struct { | ||
| 179 | magic: c_uint = 0x99990009, | ||
| 180 | interlock: switch (builtin.cpu.arch) { | ||
| 181 | .aarch64, .sparc, .x86_64, .x86 => u8, | ||
| 182 | .arm, .powerpc => c_int, | ||
| 183 | else => unreachable, | ||
| 184 | } = 0, | ||
| 185 | rblocked_first: ?*u8 = null, | ||
| 186 | rblocked_last: ?*u8 = null, | ||
| 187 | wblocked_first: ?*u8 = null, | ||
| 188 | wblocked_last: ?*u8 = null, | ||
| 189 | nreaders: c_uint = 0, | ||
| 190 | owner: ?pthread_t = null, | ||
| 191 | private: ?*anyopaque = null, | ||
| 192 | }, | ||
| 193 | .solaris, .illumos => extern struct { | ||
| 194 | readers: i32 = 0, | ||
| 195 | type: u16 = 0, | ||
| 196 | magic: u16 = 0x5257, | ||
| 197 | mutex: pthread_mutex_t = .{}, | ||
| 198 | readercv: pthread_cond_t = .{}, | ||
| 199 | writercv: pthread_cond_t = .{}, | ||
| 200 | }, | ||
| 201 | .fuchsia => extern struct { | ||
| 202 | size: [56]u8 align(@alignOf(usize)) = [_]u8{0} ** 56, | ||
| 203 | }, | ||
| 204 | .emscripten => extern struct { | ||
| 205 | size: [32]u8 align(4) = [_]u8{0} ** 32, | ||
| 206 | }, | ||
| 207 | else => @compileError("target libc does not have pthread_rwlock_t"), | ||
| 208 | }; | ||
| 209 | |||
| 210 | pub const AT = switch (native_os) { | ||
| 211 | .linux => std.os.linux.AT, | ||
| 212 | .windows => struct { | ||
| 213 | /// Remove directory instead of unlinking file | ||
| 214 | pub const REMOVEDIR = 0x200; | ||
| 215 | }, | ||
| 216 | .macos, .ios, .tvos, .watchos => struct { | ||
| 217 | pub const FDCWD = -2; | ||
| 218 | /// Use effective ids in access check | ||
| 219 | pub const EACCESS = 0x0010; | ||
| 220 | /// Act on the symlink itself not the target | ||
| 221 | pub const SYMLINK_NOFOLLOW = 0x0020; | ||
| 222 | /// Act on target of symlink | ||
| 223 | pub const SYMLINK_FOLLOW = 0x0040; | ||
| 224 | /// Path refers to directory | ||
| 225 | pub const REMOVEDIR = 0x0080; | ||
| 226 | }, | ||
| 227 | .freebsd, .kfreebsd => struct { | ||
| 228 | /// Magic value that specify the use of the current working directory | ||
| 229 | /// to determine the target of relative file paths in the openat() and | ||
| 230 | /// similar syscalls. | ||
| 231 | pub const FDCWD = -100; | ||
| 232 | /// Check access using effective user and group ID | ||
| 233 | pub const EACCESS = 0x0100; | ||
| 234 | /// Do not follow symbolic links | ||
| 235 | pub const SYMLINK_NOFOLLOW = 0x0200; | ||
| 236 | /// Follow symbolic link | ||
| 237 | pub const SYMLINK_FOLLOW = 0x0400; | ||
| 238 | /// Remove directory instead of file | ||
| 239 | pub const REMOVEDIR = 0x0800; | ||
| 240 | /// Fail if not under dirfd | ||
| 241 | pub const BENEATH = 0x1000; | ||
| 242 | }, | ||
| 243 | .netbsd => struct { | ||
| 244 | /// Magic value that specify the use of the current working directory | ||
| 245 | /// to determine the target of relative file paths in the openat() and | ||
| 246 | /// similar syscalls. | ||
| 247 | pub const FDCWD = -100; | ||
| 248 | /// Check access using effective user and group ID | ||
| 249 | pub const EACCESS = 0x0100; | ||
| 250 | /// Do not follow symbolic links | ||
| 251 | pub const SYMLINK_NOFOLLOW = 0x0200; | ||
| 252 | /// Follow symbolic link | ||
| 253 | pub const SYMLINK_FOLLOW = 0x0400; | ||
| 254 | /// Remove directory instead of file | ||
| 255 | pub const REMOVEDIR = 0x0800; | ||
| 256 | }, | ||
| 257 | .dragonfly => struct { | ||
| 258 | pub const FDCWD = -328243; | ||
| 259 | pub const SYMLINK_NOFOLLOW = 1; | ||
| 260 | pub const REMOVEDIR = 2; | ||
| 261 | pub const EACCESS = 4; | ||
| 262 | pub const SYMLINK_FOLLOW = 8; | ||
| 263 | }, | ||
| 264 | .openbsd => struct { | ||
| 265 | /// Magic value that specify the use of the current working directory | ||
| 266 | /// to determine the target of relative file paths in the openat() and | ||
| 267 | /// similar syscalls. | ||
| 268 | pub const FDCWD = -100; | ||
| 269 | /// Check access using effective user and group ID | ||
| 270 | pub const EACCESS = 0x01; | ||
| 271 | /// Do not follow symbolic links | ||
| 272 | pub const SYMLINK_NOFOLLOW = 0x02; | ||
| 273 | /// Follow symbolic link | ||
| 274 | pub const SYMLINK_FOLLOW = 0x04; | ||
| 275 | /// Remove directory instead of file | ||
| 276 | pub const REMOVEDIR = 0x08; | ||
| 277 | }, | ||
| 278 | .haiku => struct { | ||
| 279 | pub const FDCWD = -1; | ||
| 280 | pub const SYMLINK_NOFOLLOW = 0x01; | ||
| 281 | pub const SYMLINK_FOLLOW = 0x02; | ||
| 282 | pub const REMOVEDIR = 0x04; | ||
| 283 | pub const EACCESS = 0x08; | ||
| 284 | }, | ||
| 285 | .solaris, .illumos => struct { | ||
| 286 | /// Magic value that specify the use of the current working directory | ||
| 287 | /// to determine the target of relative file paths in the openat() and | ||
| 288 | /// similar syscalls. | ||
| 289 | pub const FDCWD: c.fd_t = @bitCast(@as(u32, 0xffd19553)); | ||
| 290 | /// Do not follow symbolic links | ||
| 291 | pub const SYMLINK_NOFOLLOW = 0x1000; | ||
| 292 | /// Follow symbolic link | ||
| 293 | pub const SYMLINK_FOLLOW = 0x2000; | ||
| 294 | /// Remove directory instead of file | ||
| 295 | pub const REMOVEDIR = 0x1; | ||
| 296 | pub const TRIGGER = 0x2; | ||
| 297 | /// Check access using effective user and group ID | ||
| 298 | pub const EACCESS = 0x4; | ||
| 299 | }, | ||
| 300 | .emscripten => struct { | ||
| 301 | pub const FDCWD = -100; | ||
| 302 | pub const SYMLINK_NOFOLLOW = 0x100; | ||
| 303 | pub const REMOVEDIR = 0x200; | ||
| 304 | pub const SYMLINK_FOLLOW = 0x400; | ||
| 305 | pub const NO_AUTOMOUNT = 0x800; | ||
| 306 | pub const EMPTY_PATH = 0x1000; | ||
| 307 | pub const STATX_SYNC_TYPE = 0x6000; | ||
| 308 | pub const STATX_SYNC_AS_STAT = 0x0000; | ||
| 309 | pub const STATX_FORCE_SYNC = 0x2000; | ||
| 310 | pub const STATX_DONT_SYNC = 0x4000; | ||
| 311 | pub const RECURSIVE = 0x8000; | ||
| 312 | }, | ||
| 313 | .wasi => struct { | ||
| 314 | pub const SYMLINK_NOFOLLOW = 0x100; | ||
| 315 | pub const SYMLINK_FOLLOW = 0x400; | ||
| 316 | pub const REMOVEDIR: u32 = 0x4; | ||
| 317 | /// When linking libc, we follow their convention and use -2 for current working directory. | ||
| 318 | /// However, without libc, Zig does a different convention: it assumes the | ||
| 319 | /// current working directory is the first preopen. This behavior can be | ||
| 320 | /// overridden with a public function called `wasi_cwd` in the root source | ||
| 321 | /// file. | ||
| 322 | pub const FDCWD: c.fd_t = if (builtin.link_libc) -2 else 3; | ||
| 323 | }, | ||
| 324 | |||
| 325 | else => @compileError("target libc does not have AT"), | ||
| 326 | }; | ||
| 327 | |||
| 328 | pub const O = switch (native_os) { | ||
| 329 | .linux => std.os.linux.O, | ||
| 330 | .emscripten => packed struct(u32) { | ||
| 331 | ACCMODE: std.os.ACCMODE = .RDONLY, | ||
| 332 | _2: u4 = 0, | ||
| 333 | CREAT: bool = false, | ||
| 334 | EXCL: bool = false, | ||
| 335 | NOCTTY: bool = false, | ||
| 336 | TRUNC: bool = false, | ||
| 337 | APPEND: bool = false, | ||
| 338 | NONBLOCK: bool = false, | ||
| 339 | DSYNC: bool = false, | ||
| 340 | ASYNC: bool = false, | ||
| 341 | DIRECT: bool = false, | ||
| 342 | LARGEFILE: bool = false, | ||
| 343 | DIRECTORY: bool = false, | ||
| 344 | NOFOLLOW: bool = false, | ||
| 345 | NOATIME: bool = false, | ||
| 346 | CLOEXEC: bool = false, | ||
| 347 | SYNC: bool = false, | ||
| 348 | PATH: bool = false, | ||
| 349 | TMPFILE: bool = false, | ||
| 350 | _: u9 = 0, | ||
| 351 | }, | ||
| 352 | .wasi => packed struct(u32) { | ||
| 353 | APPEND: bool = false, | ||
| 354 | DSYNC: bool = false, | ||
| 355 | NONBLOCK: bool = false, | ||
| 356 | RSYNC: bool = false, | ||
| 357 | SYNC: bool = false, | ||
| 358 | _5: u7 = 0, | ||
| 359 | CREAT: bool = false, | ||
| 360 | DIRECTORY: bool = false, | ||
| 361 | EXCL: bool = false, | ||
| 362 | TRUNC: bool = false, | ||
| 363 | _16: u8 = 0, | ||
| 364 | NOFOLLOW: bool = false, | ||
| 365 | EXEC: bool = false, | ||
| 366 | read: bool = false, | ||
| 367 | SEARCH: bool = false, | ||
| 368 | write: bool = false, | ||
| 369 | _: u3 = 0, | ||
| 370 | }, | ||
| 371 | .solaris => packed struct(u32) { | ||
| 372 | ACCMODE: std.os.ACCMODE = .RDONLY, | ||
| 373 | NDELAY: bool = false, | ||
| 374 | APPEND: bool = false, | ||
| 375 | SYNC: bool = false, | ||
| 376 | _5: u1 = 0, | ||
| 377 | DSYNC: bool = false, | ||
| 378 | NONBLOCK: bool = false, | ||
| 379 | CREAT: bool = false, | ||
| 380 | TRUNC: bool = false, | ||
| 381 | EXCL: bool = false, | ||
| 382 | NOCTTY: bool = false, | ||
| 383 | _12: u1 = 0, | ||
| 384 | LARGEFILE: bool = false, | ||
| 385 | XATTR: bool = false, | ||
| 386 | RSYNC: bool = false, | ||
| 387 | _16: u1 = 0, | ||
| 388 | NOFOLLOW: bool = false, | ||
| 389 | NOLINKS: bool = false, | ||
| 390 | _19: u2 = 0, | ||
| 391 | SEARCH: bool = false, | ||
| 392 | EXEC: bool = false, | ||
| 393 | CLOEXEC: bool = false, | ||
| 394 | DIRECTORY: bool = false, | ||
| 395 | DIRECT: bool = false, | ||
| 396 | _: u6 = 0, | ||
| 397 | }, | ||
| 398 | .netbsd => packed struct(u32) { | ||
| 399 | ACCMODE: std.os.ACCMODE = .RDONLY, | ||
| 400 | NONBLOCK: bool = false, | ||
| 401 | APPEND: bool = false, | ||
| 402 | SHLOCK: bool = false, | ||
| 403 | EXLOCK: bool = false, | ||
| 404 | ASYNC: bool = false, | ||
| 405 | SYNC: bool = false, | ||
| 406 | NOFOLLOW: bool = false, | ||
| 407 | CREAT: bool = false, | ||
| 408 | TRUNC: bool = false, | ||
| 409 | EXCL: bool = false, | ||
| 410 | _12: u3 = 0, | ||
| 411 | NOCTTY: bool = false, | ||
| 412 | DSYNC: bool = false, | ||
| 413 | RSYNC: bool = false, | ||
| 414 | ALT_IO: bool = false, | ||
| 415 | DIRECT: bool = false, | ||
| 416 | _20: u1 = 0, | ||
| 417 | DIRECTORY: bool = false, | ||
| 418 | CLOEXEC: bool = false, | ||
| 419 | SEARCH: bool = false, | ||
| 420 | _: u8 = 0, | ||
| 421 | }, | ||
| 422 | .openbsd => packed struct(u32) { | ||
| 423 | ACCMODE: std.os.ACCMODE = .RDONLY, | ||
| 424 | NONBLOCK: bool = false, | ||
| 425 | APPEND: bool = false, | ||
| 426 | SHLOCK: bool = false, | ||
| 427 | EXLOCK: bool = false, | ||
| 428 | ASYNC: bool = false, | ||
| 429 | SYNC: bool = false, | ||
| 430 | NOFOLLOW: bool = false, | ||
| 431 | CREAT: bool = false, | ||
| 432 | TRUNC: bool = false, | ||
| 433 | EXCL: bool = false, | ||
| 434 | _12: u3 = 0, | ||
| 435 | NOCTTY: bool = false, | ||
| 436 | CLOEXEC: bool = false, | ||
| 437 | DIRECTORY: bool = false, | ||
| 438 | _: u14 = 0, | ||
| 439 | }, | ||
| 440 | .haiku => packed struct(u32) { | ||
| 441 | ACCMODE: std.os.ACCMODE = .RDONLY, | ||
| 442 | _2: u4 = 0, | ||
| 443 | CLOEXEC: bool = false, | ||
| 444 | NONBLOCK: bool = false, | ||
| 445 | EXCL: bool = false, | ||
| 446 | CREAT: bool = false, | ||
| 447 | TRUNC: bool = false, | ||
| 448 | APPEND: bool = false, | ||
| 449 | NOCTTY: bool = false, | ||
| 450 | NOTRAVERSE: bool = false, | ||
| 451 | _14: u2 = 0, | ||
| 452 | SYNC: bool = false, | ||
| 453 | RSYNC: bool = false, | ||
| 454 | DSYNC: bool = false, | ||
| 455 | NOFOLLOW: bool = false, | ||
| 456 | DIRECT: bool = false, | ||
| 457 | DIRECTORY: bool = false, | ||
| 458 | _: u10 = 0, | ||
| 459 | }, | ||
| 460 | .macos, .ios, .tvos, .watchos => packed struct(u32) { | ||
| 461 | ACCMODE: std.os.ACCMODE = .RDONLY, | ||
| 462 | NONBLOCK: bool = false, | ||
| 463 | APPEND: bool = false, | ||
| 464 | SHLOCK: bool = false, | ||
| 465 | EXLOCK: bool = false, | ||
| 466 | ASYNC: bool = false, | ||
| 467 | SYNC: bool = false, | ||
| 468 | NOFOLLOW: bool = false, | ||
| 469 | CREAT: bool = false, | ||
| 470 | TRUNC: bool = false, | ||
| 471 | EXCL: bool = false, | ||
| 472 | _12: u3 = 0, | ||
| 473 | EVTONLY: bool = false, | ||
| 474 | _16: u1 = 0, | ||
| 475 | NOCTTY: bool = false, | ||
| 476 | _18: u2 = 0, | ||
| 477 | DIRECTORY: bool = false, | ||
| 478 | SYMLINK: bool = false, | ||
| 479 | DSYNC: bool = false, | ||
| 480 | _23: u1 = 0, | ||
| 481 | CLOEXEC: bool = false, | ||
| 482 | _25: u4 = 0, | ||
| 483 | ALERT: bool = false, | ||
| 484 | _30: u1 = 0, | ||
| 485 | POPUP: bool = false, | ||
| 486 | }, | ||
| 487 | .dragonfly => packed struct(u32) { | ||
| 488 | ACCMODE: std.os.ACCMODE = .RDONLY, | ||
| 489 | NONBLOCK: bool = false, | ||
| 490 | APPEND: bool = false, | ||
| 491 | SHLOCK: bool = false, | ||
| 492 | EXLOCK: bool = false, | ||
| 493 | ASYNC: bool = false, | ||
| 494 | SYNC: bool = false, | ||
| 495 | NOFOLLOW: bool = false, | ||
| 496 | CREAT: bool = false, | ||
| 497 | TRUNC: bool = false, | ||
| 498 | EXCL: bool = false, | ||
| 499 | _12: u3 = 0, | ||
| 500 | NOCTTY: bool = false, | ||
| 501 | DIRECT: bool = false, | ||
| 502 | CLOEXEC: bool = false, | ||
| 503 | FBLOCKING: bool = false, | ||
| 504 | FNONBLOCKING: bool = false, | ||
| 505 | FAPPEND: bool = false, | ||
| 506 | FOFFSET: bool = false, | ||
| 507 | FSYNCWRITE: bool = false, | ||
| 508 | FASYNCWRITE: bool = false, | ||
| 509 | _24: u3 = 0, | ||
| 510 | DIRECTORY: bool = false, | ||
| 511 | _: u4 = 0, | ||
| 512 | }, | ||
| 513 | .freebsd => packed struct(u32) { | ||
| 514 | ACCMODE: std.os.ACCMODE = .RDONLY, | ||
| 515 | NONBLOCK: bool = false, | ||
| 516 | APPEND: bool = false, | ||
| 517 | SHLOCK: bool = false, | ||
| 518 | EXLOCK: bool = false, | ||
| 519 | ASYNC: bool = false, | ||
| 520 | SYNC: bool = false, | ||
| 521 | NOFOLLOW: bool = false, | ||
| 522 | CREAT: bool = false, | ||
| 523 | TRUNC: bool = false, | ||
| 524 | EXCL: bool = false, | ||
| 525 | DSYNC: bool = false, | ||
| 526 | _13: u2 = 0, | ||
| 527 | NOCTTY: bool = false, | ||
| 528 | DIRECT: bool = false, | ||
| 529 | DIRECTORY: bool = false, | ||
| 530 | NOATIME: bool = false, | ||
| 531 | _19: u1 = 0, | ||
| 532 | CLOEXEC: bool = false, | ||
| 533 | PATH: bool = false, | ||
| 534 | TMPFILE: bool = false, | ||
| 535 | _: u9 = 0, | ||
| 536 | }, | ||
| 537 | else => @compileError("target libc does not have O"), | ||
| 538 | }; | ||
| 539 | |||
| 540 | pub const MAP = switch (native_os) { | ||
| 49 | .linux => std.os.linux.MAP, | 541 | .linux => std.os.linux.MAP, |
| 50 | .emscripten => packed struct(u32) { | 542 | .emscripten => packed struct(u32) { |
| 51 | TYPE: enum(u4) { | 543 | TYPE: enum(u4) { |
| ... | @@ -187,10 +679,10 @@ pub const MAP = switch (builtin.os.tag) { | ... | @@ -187,10 +679,10 @@ pub const MAP = switch (builtin.os.tag) { |
| 187 | /// Used by libc to communicate failure. Not actually part of the underlying syscall. | 679 | /// Used by libc to communicate failure. Not actually part of the underlying syscall. |
| 188 | pub const MAP_FAILED: *anyopaque = @ptrFromInt(std.math.maxInt(usize)); | 680 | pub const MAP_FAILED: *anyopaque = @ptrFromInt(std.math.maxInt(usize)); |
| 189 | 681 | ||
| 190 | pub const whence_t = if (builtin.os.tag == .wasi) std.os.wasi.whence_t else c_int; | 682 | pub const whence_t = if (native_os == .wasi) std.os.wasi.whence_t else c_int; |
| 191 | 683 | ||
| 192 | // Unix-like systems | 684 | // Unix-like systems |
| 193 | pub usingnamespace switch (builtin.os.tag) { | 685 | pub usingnamespace switch (native_os) { |
| 194 | .netbsd, .windows => struct {}, | 686 | .netbsd, .windows => struct {}, |
| 195 | else => struct { | 687 | else => struct { |
| 196 | pub const DIR = opaque {}; | 688 | pub const DIR = opaque {}; |
| ... | @@ -225,25 +717,40 @@ pub usingnamespace switch (builtin.os.tag) { | ... | @@ -225,25 +717,40 @@ pub usingnamespace switch (builtin.os.tag) { |
| 225 | }, | 717 | }, |
| 226 | }; | 718 | }; |
| 227 | 719 | ||
| 228 | pub usingnamespace switch (builtin.os.tag) { | 720 | pub const fstat = switch (native_os) { |
| 229 | .netbsd, .macos, .ios, .watchos, .tvos, .windows => struct {}, | 721 | .netbsd => private.__fstat50, |
| 230 | else => struct { | 722 | .macos, .ios, .watchos, .tvos => switch (native_arch) { |
| 231 | pub extern "c" fn fstat(fd: c.fd_t, buf: *c.Stat) c_int; | 723 | .aarch64 => private.fstat, |
| 232 | pub extern "c" fn readdir(dp: *c.DIR) ?*c.dirent; | 724 | else => private.@"fstat$INODE64", |
| 233 | }, | 725 | }, |
| 726 | else => private.fstat, | ||
| 234 | }; | 727 | }; |
| 235 | 728 | ||
| 236 | pub usingnamespace switch (builtin.os.tag) { | 729 | pub const fstatat = switch (native_os) { |
| 237 | .macos, .ios, .watchos, .tvos => struct {}, | 730 | .macos, .ios, .watchos, .tvos => switch (native_arch) { |
| 238 | else => struct { | 731 | .aarch64 => private.fstatat, |
| 239 | pub extern "c" fn realpath(noalias file_name: [*:0]const u8, noalias resolved_name: [*]u8) ?[*:0]u8; | 732 | else => private.@"fstatat$INODE64", |
| 240 | pub extern "c" fn fstatat(dirfd: c.fd_t, path: [*:0]const u8, stat_buf: *c.Stat, flags: u32) c_int; | ||
| 241 | }, | 733 | }, |
| 734 | else => private.fstatat, | ||
| 735 | }; | ||
| 736 | |||
| 737 | pub const readdir = switch (native_os) { | ||
| 738 | .macos, .ios, .watchos, .tvos => switch (native_arch) { | ||
| 739 | .aarch64 => private.readdir, | ||
| 740 | else => private.@"readdir$INODE64", | ||
| 741 | }, | ||
| 742 | .windows => @compileError("not available"), | ||
| 743 | else => private.readdir, | ||
| 744 | }; | ||
| 745 | |||
| 746 | pub const realpath = switch (native_os) { | ||
| 747 | .macos, .ios, .watchos, .tvos => private.@"realpath$DARWIN_EXTSN", | ||
| 748 | else => private.realpath, | ||
| 242 | }; | 749 | }; |
| 243 | 750 | ||
| 244 | pub fn getErrno(rc: anytype) c.E { | 751 | pub fn getErrno(rc: anytype) c.E { |
| 245 | if (rc == -1) { | 752 | if (rc == -1) { |
| 246 | return @as(c.E, @enumFromInt(c._errno().*)); | 753 | return @enumFromInt(c._errno().*); |
| 247 | } else { | 754 | } else { |
| 248 | return .SUCCESS; | 755 | return .SUCCESS; |
| 249 | } | 756 | } |
| ... | @@ -263,8 +770,8 @@ pub extern "c" fn _exit(code: c_int) noreturn; | ... | @@ -263,8 +770,8 @@ pub extern "c" fn _exit(code: c_int) noreturn; |
| 263 | pub extern "c" fn isatty(fd: c.fd_t) c_int; | 770 | pub extern "c" fn isatty(fd: c.fd_t) c_int; |
| 264 | pub extern "c" fn close(fd: c.fd_t) c_int; | 771 | pub extern "c" fn close(fd: c.fd_t) c_int; |
| 265 | pub extern "c" fn lseek(fd: c.fd_t, offset: c.off_t, whence: whence_t) c.off_t; | 772 | pub extern "c" fn lseek(fd: c.fd_t, offset: c.off_t, whence: whence_t) c.off_t; |
| 266 | pub extern "c" fn open(path: [*:0]const u8, oflag: c_uint, ...) c_int; | 773 | pub extern "c" fn open(path: [*:0]const u8, oflag: O, ...) c_int; |
| 267 | pub extern "c" fn openat(fd: c_int, path: [*:0]const u8, oflag: c_uint, ...) c_int; | 774 | pub extern "c" fn openat(fd: c_int, path: [*:0]const u8, oflag: O, ...) c_int; |
| 268 | pub extern "c" fn ftruncate(fd: c_int, length: c.off_t) c_int; | 775 | pub extern "c" fn ftruncate(fd: c_int, length: c.off_t) c_int; |
| 269 | pub extern "c" fn raise(sig: c_int) c_int; | 776 | pub extern "c" fn raise(sig: c_int) c_int; |
| 270 | pub extern "c" fn read(fd: c.fd_t, buf: [*]u8, nbyte: usize) isize; | 777 | pub extern "c" fn read(fd: c.fd_t, buf: [*]u8, nbyte: usize) isize; |
| ... | @@ -275,7 +782,7 @@ pub extern "c" fn writev(fd: c_int, iov: [*]const iovec_const, iovcnt: c_uint) i | ... | @@ -275,7 +782,7 @@ pub extern "c" fn writev(fd: c_int, iov: [*]const iovec_const, iovcnt: c_uint) i |
| 275 | pub extern "c" fn pwritev(fd: c_int, iov: [*]const iovec_const, iovcnt: c_uint, offset: c.off_t) isize; | 782 | pub extern "c" fn pwritev(fd: c_int, iov: [*]const iovec_const, iovcnt: c_uint, offset: c.off_t) isize; |
| 276 | pub extern "c" fn write(fd: c.fd_t, buf: [*]const u8, nbyte: usize) isize; | 783 | pub extern "c" fn write(fd: c.fd_t, buf: [*]const u8, nbyte: usize) isize; |
| 277 | pub extern "c" fn pwrite(fd: c.fd_t, buf: [*]const u8, nbyte: usize, offset: c.off_t) isize; | 784 | pub extern "c" fn pwrite(fd: c.fd_t, buf: [*]const u8, nbyte: usize, offset: c.off_t) isize; |
| 278 | pub extern "c" fn mmap(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: c_uint, fd: c.fd_t, offset: c.off_t) *anyopaque; | 785 | pub extern "c" fn mmap(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: MAP, fd: c.fd_t, offset: c.off_t) *anyopaque; |
| 279 | pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_int; | 786 | pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_int; |
| 280 | pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int; | 787 | pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int; |
| 281 | pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: c_int) c_int; | 788 | pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: c_int) c_int; |
| ... | @@ -348,7 +855,7 @@ pub extern "c" fn recv( | ... | @@ -348,7 +855,7 @@ pub extern "c" fn recv( |
| 348 | arg1: ?*anyopaque, | 855 | arg1: ?*anyopaque, |
| 349 | arg2: usize, | 856 | arg2: usize, |
| 350 | arg3: c_int, | 857 | arg3: c_int, |
| 351 | ) if (builtin.os.tag == .windows) c_int else isize; | 858 | ) if (native_os == .windows) c_int else isize; |
| 352 | pub extern "c" fn recvfrom( | 859 | pub extern "c" fn recvfrom( |
| 353 | sockfd: c.fd_t, | 860 | sockfd: c.fd_t, |
| 354 | noalias buf: *anyopaque, | 861 | noalias buf: *anyopaque, |
| ... | @@ -356,7 +863,7 @@ pub extern "c" fn recvfrom( | ... | @@ -356,7 +863,7 @@ pub extern "c" fn recvfrom( |
| 356 | flags: u32, | 863 | flags: u32, |
| 357 | noalias src_addr: ?*c.sockaddr, | 864 | noalias src_addr: ?*c.sockaddr, |
| 358 | noalias addrlen: ?*c.socklen_t, | 865 | noalias addrlen: ?*c.socklen_t, |
| 359 | ) if (builtin.os.tag == .windows) c_int else isize; | 866 | ) if (native_os == .windows) c_int else isize; |
| 360 | pub extern "c" fn recvmsg(sockfd: c.fd_t, msg: *c.msghdr, flags: u32) isize; | 867 | pub extern "c" fn recvmsg(sockfd: c.fd_t, msg: *c.msghdr, flags: u32) isize; |
| 361 | 868 | ||
| 362 | pub extern "c" fn kill(pid: c.pid_t, sig: c_int) c_int; | 869 | pub extern "c" fn kill(pid: c.pid_t, sig: c_int) c_int; |
| ... | @@ -492,18 +999,18 @@ pub extern "c" fn dn_expand( | ... | @@ -492,18 +999,18 @@ pub extern "c" fn dn_expand( |
| 492 | length: c_int, | 999 | length: c_int, |
| 493 | ) c_int; | 1000 | ) c_int; |
| 494 | 1001 | ||
| 495 | pub const PTHREAD_MUTEX_INITIALIZER = c.pthread_mutex_t{}; | 1002 | pub const PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t{}; |
| 496 | pub extern "c" fn pthread_mutex_lock(mutex: *c.pthread_mutex_t) c.E; | 1003 | pub extern "c" fn pthread_mutex_lock(mutex: *pthread_mutex_t) c.E; |
| 497 | pub extern "c" fn pthread_mutex_unlock(mutex: *c.pthread_mutex_t) c.E; | 1004 | pub extern "c" fn pthread_mutex_unlock(mutex: *pthread_mutex_t) c.E; |
| 498 | pub extern "c" fn pthread_mutex_trylock(mutex: *c.pthread_mutex_t) c.E; | 1005 | pub extern "c" fn pthread_mutex_trylock(mutex: *pthread_mutex_t) c.E; |
| 499 | pub extern "c" fn pthread_mutex_destroy(mutex: *c.pthread_mutex_t) c.E; | 1006 | pub extern "c" fn pthread_mutex_destroy(mutex: *pthread_mutex_t) c.E; |
| 500 | 1007 | ||
| 501 | pub const PTHREAD_COND_INITIALIZER = c.pthread_cond_t{}; | 1008 | pub const PTHREAD_COND_INITIALIZER = pthread_cond_t{}; |
| 502 | pub extern "c" fn pthread_cond_wait(noalias cond: *c.pthread_cond_t, noalias mutex: *c.pthread_mutex_t) c.E; | 1009 | pub extern "c" fn pthread_cond_wait(noalias cond: *pthread_cond_t, noalias mutex: *pthread_mutex_t) c.E; |
| 503 | pub extern "c" fn pthread_cond_timedwait(noalias cond: *c.pthread_cond_t, noalias mutex: *c.pthread_mutex_t, noalias abstime: *const c.timespec) c.E; | 1010 | pub extern "c" fn pthread_cond_timedwait(noalias cond: *pthread_cond_t, noalias mutex: *pthread_mutex_t, noalias abstime: *const c.timespec) c.E; |
| 504 | pub extern "c" fn pthread_cond_signal(cond: *c.pthread_cond_t) c.E; | 1011 | pub extern "c" fn pthread_cond_signal(cond: *pthread_cond_t) c.E; |
| 505 | pub extern "c" fn pthread_cond_broadcast(cond: *c.pthread_cond_t) c.E; | 1012 | pub extern "c" fn pthread_cond_broadcast(cond: *pthread_cond_t) c.E; |
| 506 | pub extern "c" fn pthread_cond_destroy(cond: *c.pthread_cond_t) c.E; | 1013 | pub extern "c" fn pthread_cond_destroy(cond: *pthread_cond_t) c.E; |
| 507 | 1014 | ||
| 508 | pub extern "c" fn pthread_rwlock_destroy(rwl: *c.pthread_rwlock_t) callconv(.C) c.E; | 1015 | pub extern "c" fn pthread_rwlock_destroy(rwl: *c.pthread_rwlock_t) callconv(.C) c.E; |
| 509 | pub extern "c" fn pthread_rwlock_rdlock(rwl: *c.pthread_rwlock_t) callconv(.C) c.E; | 1016 | pub extern "c" fn pthread_rwlock_rdlock(rwl: *c.pthread_rwlock_t) callconv(.C) c.E; |
| ... | @@ -542,14 +1049,14 @@ pub usingnamespace if (builtin.target.isAndroid()) struct { | ... | @@ -542,14 +1049,14 @@ pub usingnamespace if (builtin.target.isAndroid()) struct { |
| 542 | // android bionic libc does not implement getcontext, | 1049 | // android bionic libc does not implement getcontext, |
| 543 | // and std.os.linux.getcontext also cannot be built for | 1050 | // and std.os.linux.getcontext also cannot be built for |
| 544 | // bionic libc currently. | 1051 | // bionic libc currently. |
| 545 | } else if (builtin.os.tag == .linux and builtin.target.isMusl()) struct { | 1052 | } else if (native_os == .linux and builtin.target.isMusl()) struct { |
| 546 | // musl does not implement getcontext | 1053 | // musl does not implement getcontext |
| 547 | pub const getcontext = std.os.linux.getcontext; | 1054 | pub const getcontext = std.os.linux.getcontext; |
| 548 | } else struct { | 1055 | } else struct { |
| 549 | pub extern "c" fn getcontext(ucp: *std.os.ucontext_t) c_int; | 1056 | pub extern "c" fn getcontext(ucp: *std.os.ucontext_t) c_int; |
| 550 | }; | 1057 | }; |
| 551 | 1058 | ||
| 552 | pub const max_align_t = if (builtin.abi == .msvc) | 1059 | pub const max_align_t = if (native_abi == .msvc) |
| 553 | f64 | 1060 | f64 |
| 554 | else if (builtin.target.isDarwin()) | 1061 | else if (builtin.target.isDarwin()) |
| 555 | c_longdouble | 1062 | c_longdouble |
| ... | @@ -558,3 +1065,25 @@ else | ... | @@ -558,3 +1065,25 @@ else |
| 558 | a: c_longlong, | 1065 | a: c_longlong, |
| 559 | b: c_longdouble, | 1066 | b: c_longdouble, |
| 560 | }; | 1067 | }; |
| 1068 | |||
| 1069 | const private = struct { | ||
| 1070 | extern "c" fn fstat(fd: c.fd_t, buf: *c.Stat) c_int; | ||
| 1071 | /// On x86_64 Darwin, fstat has to be manually linked with $INODE64 suffix to | ||
| 1072 | /// force 64bit version. | ||
| 1073 | /// Note that this is fixed on aarch64 and no longer necessary. | ||
| 1074 | extern "c" fn @"fstat$INODE64"(fd: c.fd_t, buf: *c.Stat) c_int; | ||
| 1075 | |||
| 1076 | extern "c" fn fstatat(dirfd: c.fd_t, path: [*:0]const u8, stat_buf: *c.Stat, flags: u32) c_int; | ||
| 1077 | /// On x86_64 Darwin, fstatat has to be manually linked with $INODE64 suffix to | ||
| 1078 | /// force 64bit version. | ||
| 1079 | /// Note that this is fixed on aarch64 and no longer necessary. | ||
| 1080 | extern "c" fn @"fstatat$INODE64"(dirfd: c.fd_t, path_name: [*:0]const u8, buf: *c.Stat, flags: u32) c_int; | ||
| 1081 | |||
| 1082 | extern "c" fn __fstat50(fd: c.fd_t, buf: *c.Stat) c_int; | ||
| 1083 | |||
| 1084 | extern "c" fn readdir(dir: *c.DIR) ?*c.dirent; | ||
| 1085 | extern "c" fn @"readdir$INODE64"(dir: *c.DIR) ?*c.dirent; | ||
| 1086 | |||
| 1087 | extern "c" fn realpath(noalias file_name: [*:0]const u8, noalias resolved_name: [*]u8) ?[*:0]u8; | ||
| 1088 | extern "c" fn @"realpath$DARWIN_EXTSN"(noalias file_name: [*:0]const u8, noalias resolved_name: [*]u8) ?[*:0]u8; | ||
| 1089 | }; |
lib/std/c/darwin.zig+6-102| ... | @@ -169,31 +169,8 @@ pub const COPYFILE_DATA = 1 << 3; | ... | @@ -169,31 +169,8 @@ pub const COPYFILE_DATA = 1 << 3; |
| 169 | pub const copyfile_state_t = *opaque {}; | 169 | pub const copyfile_state_t = *opaque {}; |
| 170 | pub extern "c" fn fcopyfile(from: fd_t, to: fd_t, state: ?copyfile_state_t, flags: u32) c_int; | 170 | pub extern "c" fn fcopyfile(from: fd_t, to: fd_t, state: ?copyfile_state_t, flags: u32) c_int; |
| 171 | 171 | ||
| 172 | pub extern "c" fn @"realpath$DARWIN_EXTSN"(noalias file_name: [*:0]const u8, noalias resolved_name: [*]u8) ?[*:0]u8; | ||
| 173 | pub const realpath = @"realpath$DARWIN_EXTSN"; | ||
| 174 | |||
| 175 | pub extern "c" fn __getdirentries64(fd: c_int, buf_ptr: [*]u8, buf_len: usize, basep: *i64) isize; | 172 | pub extern "c" fn __getdirentries64(fd: c_int, buf_ptr: [*]u8, buf_len: usize, basep: *i64) isize; |
| 176 | 173 | ||
| 177 | const private = struct { | ||
| 178 | extern "c" fn fstat(fd: fd_t, buf: *Stat) c_int; | ||
| 179 | /// On x86_64 Darwin, fstat has to be manually linked with $INODE64 suffix to | ||
| 180 | /// force 64bit version. | ||
| 181 | /// Note that this is fixed on aarch64 and no longer necessary. | ||
| 182 | extern "c" fn @"fstat$INODE64"(fd: fd_t, buf: *Stat) c_int; | ||
| 183 | |||
| 184 | extern "c" fn fstatat(dirfd: fd_t, path: [*:0]const u8, stat_buf: *Stat, flags: u32) c_int; | ||
| 185 | /// On x86_64 Darwin, fstatat has to be manually linked with $INODE64 suffix to | ||
| 186 | /// force 64bit version. | ||
| 187 | /// Note that this is fixed on aarch64 and no longer necessary. | ||
| 188 | extern "c" fn @"fstatat$INODE64"(dirfd: fd_t, path_name: [*:0]const u8, buf: *Stat, flags: u32) c_int; | ||
| 189 | |||
| 190 | extern "c" fn readdir(dir: *std.c.DIR) ?*dirent; | ||
| 191 | extern "c" fn @"readdir$INODE64"(dir: *std.c.DIR) ?*dirent; | ||
| 192 | }; | ||
| 193 | pub const fstat = if (native_arch == .aarch64) private.fstat else private.@"fstat$INODE64"; | ||
| 194 | pub const fstatat = if (native_arch == .aarch64) private.fstatat else private.@"fstatat$INODE64"; | ||
| 195 | pub const readdir = if (native_arch == .aarch64) private.readdir else private.@"readdir$INODE64"; | ||
| 196 | |||
| 197 | pub extern "c" fn mach_absolute_time() u64; | 174 | pub extern "c" fn mach_absolute_time() u64; |
| 198 | pub extern "c" fn mach_continuous_time() u64; | 175 | pub extern "c" fn mach_continuous_time() u64; |
| 199 | pub extern "c" fn mach_timebase_info(tinfo: ?*mach_timebase_info_data) kern_return_t; | 176 | pub extern "c" fn mach_timebase_info(tinfo: ?*mach_timebase_info_data) kern_return_t; |
| ... | @@ -866,21 +843,7 @@ pub const qos_class_t = enum(c_uint) { | ... | @@ -866,21 +843,7 @@ pub const qos_class_t = enum(c_uint) { |
| 866 | QOS_CLASS_UNSPECIFIED = 0x00, | 843 | QOS_CLASS_UNSPECIFIED = 0x00, |
| 867 | }; | 844 | }; |
| 868 | 845 | ||
| 869 | pub const pthread_mutex_t = extern struct { | ||
| 870 | __sig: c_long = 0x32AAABA7, | ||
| 871 | __opaque: [__PTHREAD_MUTEX_SIZE__]u8 = [_]u8{0} ** __PTHREAD_MUTEX_SIZE__, | ||
| 872 | }; | ||
| 873 | pub const pthread_cond_t = extern struct { | ||
| 874 | __sig: c_long = 0x3CB0B1BB, | ||
| 875 | __opaque: [__PTHREAD_COND_SIZE__]u8 = [_]u8{0} ** __PTHREAD_COND_SIZE__, | ||
| 876 | }; | ||
| 877 | pub const pthread_rwlock_t = extern struct { | ||
| 878 | __sig: c_long = 0x2DA8B3B4, | ||
| 879 | __opaque: [192]u8 = [_]u8{0} ** 192, | ||
| 880 | }; | ||
| 881 | pub const sem_t = c_int; | 846 | pub const sem_t = c_int; |
| 882 | const __PTHREAD_MUTEX_SIZE__ = if (@sizeOf(usize) == 8) 56 else 40; | ||
| 883 | const __PTHREAD_COND_SIZE__ = if (@sizeOf(usize) == 8) 40 else 24; | ||
| 884 | 847 | ||
| 885 | pub const pthread_attr_t = extern struct { | 848 | pub const pthread_attr_t = extern struct { |
| 886 | __sig: c_long, | 849 | __sig: c_long, |
| ... | @@ -1202,16 +1165,12 @@ pub const Sigaction = extern struct { | ... | @@ -1202,16 +1165,12 @@ pub const Sigaction = extern struct { |
| 1202 | }; | 1165 | }; |
| 1203 | 1166 | ||
| 1204 | pub const dirent = extern struct { | 1167 | pub const dirent = extern struct { |
| 1205 | d_ino: u64, | 1168 | ino: u64, |
| 1206 | d_seekoff: u64, | 1169 | seekoff: u64, |
| 1207 | d_reclen: u16, | 1170 | reclen: u16, |
| 1208 | d_namlen: u16, | 1171 | namlen: u16, |
| 1209 | d_type: u8, | 1172 | type: u8, |
| 1210 | d_name: [1024]u8, | 1173 | name: [1024]u8, |
| 1211 | |||
| 1212 | pub fn reclen(self: dirent) u16 { | ||
| 1213 | return self.d_reclen; | ||
| 1214 | } | ||
| 1215 | }; | 1174 | }; |
| 1216 | 1175 | ||
| 1217 | /// Renamed from `kevent` to `Kevent` to avoid conflict with function name. | 1176 | /// Renamed from `kevent` to `Kevent` to avoid conflict with function name. |
| ... | @@ -1346,49 +1305,6 @@ pub const X_OK = 1; | ... | @@ -1346,49 +1305,6 @@ pub const X_OK = 1; |
| 1346 | pub const W_OK = 2; | 1305 | pub const W_OK = 2; |
| 1347 | pub const R_OK = 4; | 1306 | pub const R_OK = 4; |
| 1348 | 1307 | ||
| 1349 | pub const O = struct { | ||
| 1350 | pub const PATH = 0x0000; | ||
| 1351 | /// open for reading only | ||
| 1352 | pub const RDONLY = 0x0000; | ||
| 1353 | /// open for writing only | ||
| 1354 | pub const WRONLY = 0x0001; | ||
| 1355 | /// open for reading and writing | ||
| 1356 | pub const RDWR = 0x0002; | ||
| 1357 | /// do not block on open or for data to become available | ||
| 1358 | pub const NONBLOCK = 0x0004; | ||
| 1359 | /// append on each write | ||
| 1360 | pub const APPEND = 0x0008; | ||
| 1361 | /// create file if it does not exist | ||
| 1362 | pub const CREAT = 0x0200; | ||
| 1363 | /// truncate size to 0 | ||
| 1364 | pub const TRUNC = 0x0400; | ||
| 1365 | /// error if CREAT and the file exists | ||
| 1366 | pub const EXCL = 0x0800; | ||
| 1367 | /// atomically obtain a shared lock | ||
| 1368 | pub const SHLOCK = 0x0010; | ||
| 1369 | /// atomically obtain an exclusive lock | ||
| 1370 | pub const EXLOCK = 0x0020; | ||
| 1371 | /// do not follow symlinks | ||
| 1372 | pub const NOFOLLOW = 0x0100; | ||
| 1373 | /// allow open of symlinks | ||
| 1374 | pub const SYMLINK = 0x200000; | ||
| 1375 | /// descriptor requested for event notifications only | ||
| 1376 | pub const EVTONLY = 0x8000; | ||
| 1377 | /// mark as close-on-exec | ||
| 1378 | pub const CLOEXEC = 0x1000000; | ||
| 1379 | pub const ACCMODE = 3; | ||
| 1380 | pub const ALERT = 536870912; | ||
| 1381 | pub const ASYNC = 64; | ||
| 1382 | pub const DIRECTORY = 1048576; | ||
| 1383 | pub const DP_GETRAWENCRYPTED = 1; | ||
| 1384 | pub const DP_GETRAWUNENCRYPTED = 2; | ||
| 1385 | pub const DSYNC = 4194304; | ||
| 1386 | pub const FSYNC = SYNC; | ||
| 1387 | pub const NOCTTY = 131072; | ||
| 1388 | pub const POPUP = 2147483648; | ||
| 1389 | pub const SYNC = 128; | ||
| 1390 | }; | ||
| 1391 | |||
| 1392 | pub const SEEK = struct { | 1308 | pub const SEEK = struct { |
| 1393 | pub const SET = 0x0; | 1309 | pub const SET = 0x0; |
| 1394 | pub const CUR = 0x1; | 1310 | pub const CUR = 0x1; |
| ... | @@ -2529,18 +2445,6 @@ pub const S = struct { | ... | @@ -2529,18 +2445,6 @@ pub const S = struct { |
| 2529 | 2445 | ||
| 2530 | pub const HOST_NAME_MAX = 72; | 2446 | pub const HOST_NAME_MAX = 72; |
| 2531 | 2447 | ||
| 2532 | pub const AT = struct { | ||
| 2533 | pub const FDCWD = -2; | ||
| 2534 | /// Use effective ids in access check | ||
| 2535 | pub const EACCESS = 0x0010; | ||
| 2536 | /// Act on the symlink itself not the target | ||
| 2537 | pub const SYMLINK_NOFOLLOW = 0x0020; | ||
| 2538 | /// Act on target of symlink | ||
| 2539 | pub const SYMLINK_FOLLOW = 0x0040; | ||
| 2540 | /// Path refers to directory | ||
| 2541 | pub const REMOVEDIR = 0x0080; | ||
| 2542 | }; | ||
| 2543 | |||
| 2544 | pub const addrinfo = extern struct { | 2448 | pub const addrinfo = extern struct { |
| 2545 | flags: i32, | 2449 | flags: i32, |
| 2546 | family: i32, | 2450 | family: i32, |
lib/std/c/dragonfly.zig+7-55| ... | @@ -22,22 +22,11 @@ pub extern "c" fn lwp_gettid() c_int; | ... | @@ -22,22 +22,11 @@ pub extern "c" fn lwp_gettid() c_int; |
| 22 | 22 | ||
| 23 | pub extern "c" fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: usize) c_int; | 23 | pub extern "c" fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: usize) c_int; |
| 24 | 24 | ||
| 25 | pub const pthread_mutex_t = extern struct { | ||
| 26 | inner: ?*anyopaque = null, | ||
| 27 | }; | ||
| 28 | pub const pthread_cond_t = extern struct { | ||
| 29 | inner: ?*anyopaque = null, | ||
| 30 | }; | ||
| 31 | |||
| 32 | pub const pthread_attr_t = extern struct { // copied from freebsd | 25 | pub const pthread_attr_t = extern struct { // copied from freebsd |
| 33 | __size: [56]u8, | 26 | __size: [56]u8, |
| 34 | __align: c_long, | 27 | __align: c_long, |
| 35 | }; | 28 | }; |
| 36 | 29 | ||
| 37 | pub const pthread_rwlock_t = extern struct { | ||
| 38 | ptr: ?*anyopaque = null, | ||
| 39 | }; | ||
| 40 | |||
| 41 | pub const sem_t = ?*opaque {}; | 30 | pub const sem_t = ?*opaque {}; |
| 42 | 31 | ||
| 43 | pub extern "c" fn pthread_setname_np(thread: std.c.pthread_t, name: [*:0]const u8) E; | 32 | pub extern "c" fn pthread_setname_np(thread: std.c.pthread_t, name: [*:0]const u8) E; |
| ... | @@ -394,35 +383,6 @@ pub const X_OK = 1; // test for execute or search permission | ... | @@ -394,35 +383,6 @@ pub const X_OK = 1; // test for execute or search permission |
| 394 | pub const W_OK = 2; // test for write permission | 383 | pub const W_OK = 2; // test for write permission |
| 395 | pub const R_OK = 4; // test for read permission | 384 | pub const R_OK = 4; // test for read permission |
| 396 | 385 | ||
| 397 | pub const O = struct { | ||
| 398 | pub const RDONLY = 0; | ||
| 399 | pub const NDELAY = NONBLOCK; | ||
| 400 | pub const WRONLY = 1; | ||
| 401 | pub const RDWR = 2; | ||
| 402 | pub const ACCMODE = 3; | ||
| 403 | pub const NONBLOCK = 4; | ||
| 404 | pub const APPEND = 8; | ||
| 405 | pub const SHLOCK = 16; | ||
| 406 | pub const EXLOCK = 32; | ||
| 407 | pub const ASYNC = 64; | ||
| 408 | pub const FSYNC = 128; | ||
| 409 | pub const SYNC = 128; | ||
| 410 | pub const NOFOLLOW = 256; | ||
| 411 | pub const CREAT = 512; | ||
| 412 | pub const TRUNC = 1024; | ||
| 413 | pub const EXCL = 2048; | ||
| 414 | pub const NOCTTY = 32768; | ||
| 415 | pub const DIRECT = 65536; | ||
| 416 | pub const CLOEXEC = 131072; | ||
| 417 | pub const FBLOCKING = 262144; | ||
| 418 | pub const FNONBLOCKING = 524288; | ||
| 419 | pub const FAPPEND = 1048576; | ||
| 420 | pub const FOFFSET = 2097152; | ||
| 421 | pub const FSYNCWRITE = 4194304; | ||
| 422 | pub const FASYNCWRITE = 8388608; | ||
| 423 | pub const DIRECTORY = 134217728; | ||
| 424 | }; | ||
| 425 | |||
| 426 | pub const SEEK = struct { | 386 | pub const SEEK = struct { |
| 427 | pub const SET = 0; | 387 | pub const SET = 0; |
| 428 | pub const CUR = 1; | 388 | pub const CUR = 1; |
| ... | @@ -458,24 +418,16 @@ pub const F = struct { | ... | @@ -458,24 +418,16 @@ pub const F = struct { |
| 458 | 418 | ||
| 459 | pub const FD_CLOEXEC = 1; | 419 | pub const FD_CLOEXEC = 1; |
| 460 | 420 | ||
| 461 | pub const AT = struct { | ||
| 462 | pub const FDCWD = -328243; | ||
| 463 | pub const SYMLINK_NOFOLLOW = 1; | ||
| 464 | pub const REMOVEDIR = 2; | ||
| 465 | pub const EACCESS = 4; | ||
| 466 | pub const SYMLINK_FOLLOW = 8; | ||
| 467 | }; | ||
| 468 | |||
| 469 | pub const dirent = extern struct { | 421 | pub const dirent = extern struct { |
| 470 | d_fileno: c_ulong, | 422 | fileno: c_ulong, |
| 471 | d_namlen: u16, | 423 | namlen: u16, |
| 472 | d_type: u8, | 424 | type: u8, |
| 473 | d_unused1: u8, | 425 | unused1: u8, |
| 474 | d_unused2: u32, | 426 | unused2: u32, |
| 475 | d_name: [256]u8, | 427 | name: [256]u8, |
| 476 | 428 | ||
| 477 | pub fn reclen(self: dirent) u16 { | 429 | pub fn reclen(self: dirent) u16 { |
| 478 | return (@offsetOf(dirent, "d_name") + self.d_namlen + 1 + 7) & ~@as(u16, 7); | 430 | return (@offsetOf(dirent, "name") + self.namlen + 1 + 7) & ~@as(u16, 7); |
| 479 | } | 431 | } |
| 480 | }; | 432 | }; |
| 481 | 433 |
lib/std/c/emscripten.zig+5-20| ... | @@ -3,7 +3,6 @@ const maxInt = std.math.maxInt; | ... | @@ -3,7 +3,6 @@ const maxInt = std.math.maxInt; |
| 3 | const emscripten = std.os.emscripten; | 3 | const emscripten = std.os.emscripten; |
| 4 | 4 | ||
| 5 | pub const AF = emscripten.AF; | 5 | pub const AF = emscripten.AF; |
| 6 | pub const AT = emscripten.AT; | ||
| 7 | pub const CLOCK = emscripten.CLOCK; | 6 | pub const CLOCK = emscripten.CLOCK; |
| 8 | pub const CPU_COUNT = emscripten.CPU_COUNT; | 7 | pub const CPU_COUNT = emscripten.CPU_COUNT; |
| 9 | pub const E = emscripten.E; | 8 | pub const E = emscripten.E; |
| ... | @@ -19,7 +18,6 @@ pub const MADV = emscripten.MADV; | ... | @@ -19,7 +18,6 @@ pub const MADV = emscripten.MADV; |
| 19 | pub const MSF = emscripten.MSF; | 18 | pub const MSF = emscripten.MSF; |
| 20 | pub const MSG = emscripten.MSG; | 19 | pub const MSG = emscripten.MSG; |
| 21 | pub const NAME_MAX = emscripten.NAME_MAX; | 20 | pub const NAME_MAX = emscripten.NAME_MAX; |
| 22 | pub const O = emscripten.O; | ||
| 23 | pub const PATH_MAX = emscripten.PATH_MAX; | 21 | pub const PATH_MAX = emscripten.PATH_MAX; |
| 24 | pub const POLL = emscripten.POLL; | 22 | pub const POLL = emscripten.POLL; |
| 25 | pub const PROT = emscripten.PROT; | 23 | pub const PROT = emscripten.PROT; |
| ... | @@ -159,19 +157,6 @@ pub const pthread_attr_t = extern struct { | ... | @@ -159,19 +157,6 @@ pub const pthread_attr_t = extern struct { |
| 159 | __align: c_long, | 157 | __align: c_long, |
| 160 | }; | 158 | }; |
| 161 | 159 | ||
| 162 | pub const pthread_mutex_t = extern struct { | ||
| 163 | size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(4) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, | ||
| 164 | }; | ||
| 165 | pub const pthread_cond_t = extern struct { | ||
| 166 | size: [__SIZEOF_PTHREAD_COND_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_COND_T, | ||
| 167 | }; | ||
| 168 | pub const pthread_rwlock_t = extern struct { | ||
| 169 | size: [32]u8 align(4) = [_]u8{0} ** 32, | ||
| 170 | }; | ||
| 171 | |||
| 172 | const __SIZEOF_PTHREAD_COND_T = 48; | ||
| 173 | const __SIZEOF_PTHREAD_MUTEX_T = 24; | ||
| 174 | |||
| 175 | pub const pthread_key_t = c_uint; | 160 | pub const pthread_key_t = c_uint; |
| 176 | pub const sem_t = extern struct { | 161 | pub const sem_t = extern struct { |
| 177 | __size: [__SIZEOF_SEM_T]u8 align(@alignOf(usize)), | 162 | __size: [__SIZEOF_SEM_T]u8 align(@alignOf(usize)), |
| ... | @@ -189,9 +174,9 @@ pub const RTLD = struct { | ... | @@ -189,9 +174,9 @@ pub const RTLD = struct { |
| 189 | }; | 174 | }; |
| 190 | 175 | ||
| 191 | pub const dirent = struct { | 176 | pub const dirent = struct { |
| 192 | d_ino: c_uint, | 177 | ino: c_uint, |
| 193 | d_off: c_uint, | 178 | off: c_uint, |
| 194 | d_reclen: c_ushort, | 179 | reclen: c_ushort, |
| 195 | d_type: u8, | 180 | type: u8, |
| 196 | d_name: [256]u8, | 181 | name: [256]u8, |
| 197 | }; | 182 | }; |
lib/std/c/freebsd.zig+9-70| ... | @@ -44,16 +44,6 @@ pub extern "c" fn sendfile( | ... | @@ -44,16 +44,6 @@ pub extern "c" fn sendfile( |
| 44 | pub const dl_iterate_phdr_callback = *const fn (info: *dl_phdr_info, size: usize, data: ?*anyopaque) callconv(.C) c_int; | 44 | pub const dl_iterate_phdr_callback = *const fn (info: *dl_phdr_info, size: usize, data: ?*anyopaque) callconv(.C) c_int; |
| 45 | pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*anyopaque) c_int; | 45 | pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*anyopaque) c_int; |
| 46 | 46 | ||
| 47 | pub const pthread_mutex_t = extern struct { | ||
| 48 | inner: ?*anyopaque = null, | ||
| 49 | }; | ||
| 50 | pub const pthread_cond_t = extern struct { | ||
| 51 | inner: ?*anyopaque = null, | ||
| 52 | }; | ||
| 53 | pub const pthread_rwlock_t = extern struct { | ||
| 54 | ptr: ?*anyopaque = null, | ||
| 55 | }; | ||
| 56 | |||
| 57 | pub const pthread_attr_t = extern struct { | 47 | pub const pthread_attr_t = extern struct { |
| 58 | inner: ?*anyopaque = null, | 48 | inner: ?*anyopaque = null, |
| 59 | }; | 49 | }; |
| ... | @@ -376,23 +366,19 @@ pub const timeval = extern struct { | ... | @@ -376,23 +366,19 @@ pub const timeval = extern struct { |
| 376 | 366 | ||
| 377 | pub const dirent = extern struct { | 367 | pub const dirent = extern struct { |
| 378 | /// File number of entry. | 368 | /// File number of entry. |
| 379 | d_fileno: ino_t, | 369 | fileno: ino_t, |
| 380 | /// Directory offset of entry. | 370 | /// Directory offset of entry. |
| 381 | d_off: off_t, | 371 | off: off_t, |
| 382 | /// Length of this record. | 372 | /// Length of this record. |
| 383 | d_reclen: u16, | 373 | reclen: u16, |
| 384 | /// File type, one of DT_. | 374 | /// File type, one of DT_. |
| 385 | d_type: u8, | 375 | type: u8, |
| 386 | _d_pad0: u8, | 376 | pad0: u8 = 0, |
| 387 | /// Length of the d_name member. | 377 | /// Length of the name member. |
| 388 | d_namlen: u16, | 378 | namlen: u16, |
| 389 | _d_pad1: u16, | 379 | pad1: u16 = 0, |
| 390 | /// Name of entry. | 380 | /// Name of entry. |
| 391 | d_name: [255:0]u8, | 381 | name: [255:0]u8, |
| 392 | |||
| 393 | pub fn reclen(self: dirent) u16 { | ||
| 394 | return self.d_reclen; | ||
| 395 | } | ||
| 396 | }; | 382 | }; |
| 397 | 383 | ||
| 398 | pub const in_port_t = u16; | 384 | pub const in_port_t = u16; |
| ... | @@ -746,36 +732,6 @@ pub const X_OK = 1; // test for execute or search permission | ... | @@ -746,36 +732,6 @@ pub const X_OK = 1; // test for execute or search permission |
| 746 | pub const W_OK = 2; // test for write permission | 732 | pub const W_OK = 2; // test for write permission |
| 747 | pub const R_OK = 4; // test for read permission | 733 | pub const R_OK = 4; // test for read permission |
| 748 | 734 | ||
| 749 | pub const O = struct { | ||
| 750 | pub const RDONLY = 0x0000; | ||
| 751 | pub const WRONLY = 0x0001; | ||
| 752 | pub const RDWR = 0x0002; | ||
| 753 | pub const ACCMODE = 0x0003; | ||
| 754 | |||
| 755 | pub const SHLOCK = 0x0010; | ||
| 756 | pub const EXLOCK = 0x0020; | ||
| 757 | |||
| 758 | pub const CREAT = 0x0200; | ||
| 759 | pub const EXCL = 0x0800; | ||
| 760 | pub const NOCTTY = 0x8000; | ||
| 761 | pub const TRUNC = 0x0400; | ||
| 762 | pub const APPEND = 0x0008; | ||
| 763 | pub const NONBLOCK = 0x0004; | ||
| 764 | pub const DSYNC = 0o10000; | ||
| 765 | pub const SYNC = 0x0080; | ||
| 766 | pub const RSYNC = 0o4010000; | ||
| 767 | pub const DIRECTORY = 0x20000; | ||
| 768 | pub const NOFOLLOW = 0x0100; | ||
| 769 | pub const CLOEXEC = 0x00100000; | ||
| 770 | |||
| 771 | pub const ASYNC = 0x0040; | ||
| 772 | pub const DIRECT = 0x00010000; | ||
| 773 | pub const NOATIME = 0o1000000; | ||
| 774 | pub const PATH = 0o10000000; | ||
| 775 | pub const TMPFILE = 0o20200000; | ||
| 776 | pub const NDELAY = NONBLOCK; | ||
| 777 | }; | ||
| 778 | |||
| 779 | /// Command flags for fcntl(2). | 735 | /// Command flags for fcntl(2). |
| 780 | pub const F = struct { | 736 | pub const F = struct { |
| 781 | /// Duplicate file descriptor. | 737 | /// Duplicate file descriptor. |
| ... | @@ -1573,23 +1529,6 @@ pub const S = struct { | ... | @@ -1573,23 +1529,6 @@ pub const S = struct { |
| 1573 | 1529 | ||
| 1574 | pub const HOST_NAME_MAX = 255; | 1530 | pub const HOST_NAME_MAX = 255; |
| 1575 | 1531 | ||
| 1576 | pub const AT = struct { | ||
| 1577 | /// Magic value that specify the use of the current working directory | ||
| 1578 | /// to determine the target of relative file paths in the openat() and | ||
| 1579 | /// similar syscalls. | ||
| 1580 | pub const FDCWD = -100; | ||
| 1581 | /// Check access using effective user and group ID | ||
| 1582 | pub const EACCESS = 0x0100; | ||
| 1583 | /// Do not follow symbolic links | ||
| 1584 | pub const SYMLINK_NOFOLLOW = 0x0200; | ||
| 1585 | /// Follow symbolic link | ||
| 1586 | pub const SYMLINK_FOLLOW = 0x0400; | ||
| 1587 | /// Remove directory instead of file | ||
| 1588 | pub const REMOVEDIR = 0x0800; | ||
| 1589 | /// Fail if not under dirfd | ||
| 1590 | pub const BENEATH = 0x1000; | ||
| 1591 | }; | ||
| 1592 | |||
| 1593 | pub const addrinfo = extern struct { | 1532 | pub const addrinfo = extern struct { |
| 1594 | flags: i32, | 1533 | flags: i32, |
| 1595 | family: i32, | 1534 | family: i32, |
lib/std/c/fuchsia.zig deleted-11| ... | @@ -1,11 +0,0 @@ | ||
| 1 | pub const pthread_mutex_t = extern struct { | ||
| 2 | size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, | ||
| 3 | }; | ||
| 4 | pub const pthread_cond_t = extern struct { | ||
| 5 | size: [__SIZEOF_PTHREAD_COND_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_COND_T, | ||
| 6 | }; | ||
| 7 | pub const pthread_rwlock_t = extern struct { | ||
| 8 | size: [56]u8 align(@alignOf(usize)) = [_]u8{0} ** 56, | ||
| 9 | }; | ||
| 10 | const __SIZEOF_PTHREAD_COND_T = 48; | ||
| 11 | const __SIZEOF_PTHREAD_MUTEX_T = 40; | ||
lib/std/c/haiku.zig+6-60| ... | @@ -45,22 +45,6 @@ pub const pthread_attr_t = extern struct { | ... | @@ -45,22 +45,6 @@ pub const pthread_attr_t = extern struct { |
| 45 | __stack_address: ?*anyopaque, | 45 | __stack_address: ?*anyopaque, |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | pub const pthread_mutex_t = extern struct { | ||
| 49 | flags: u32 = 0, | ||
| 50 | lock: i32 = 0, | ||
| 51 | unused: i32 = -42, | ||
| 52 | owner: i32 = -1, | ||
| 53 | owner_count: i32 = 0, | ||
| 54 | }; | ||
| 55 | |||
| 56 | pub const pthread_cond_t = extern struct { | ||
| 57 | flags: u32 = 0, | ||
| 58 | unused: i32 = -42, | ||
| 59 | mutex: ?*anyopaque = null, | ||
| 60 | waiter_count: i32 = 0, | ||
| 61 | lock: i32 = 0, | ||
| 62 | }; | ||
| 63 | |||
| 64 | pub const EAI = enum(c_int) { | 48 | pub const EAI = enum(c_int) { |
| 65 | /// address family for hostname not supported | 49 | /// address family for hostname not supported |
| 66 | ADDRFAMILY = 1, | 50 | ADDRFAMILY = 1, |
| ... | @@ -238,16 +222,12 @@ pub const timespec = extern struct { | ... | @@ -238,16 +222,12 @@ pub const timespec = extern struct { |
| 238 | }; | 222 | }; |
| 239 | 223 | ||
| 240 | pub const dirent = extern struct { | 224 | pub const dirent = extern struct { |
| 241 | d_dev: i32, | 225 | dev: i32, |
| 242 | d_pdev: i32, | 226 | pdev: i32, |
| 243 | d_ino: i64, | 227 | ino: i64, |
| 244 | d_pino: i64, | 228 | pino: i64, |
| 245 | d_reclen: u16, | 229 | reclen: u16, |
| 246 | d_name: [256]u8, | 230 | name: [256]u8, |
| 247 | |||
| 248 | pub fn reclen(self: dirent) u16 { | ||
| 249 | return self.d_reclen; | ||
| 250 | } | ||
| 251 | }; | 231 | }; |
| 252 | 232 | ||
| 253 | pub const B_OS_NAME_LENGTH = 32; // OS.h | 233 | pub const B_OS_NAME_LENGTH = 32; // OS.h |
| ... | @@ -510,32 +490,6 @@ pub const X_OK = 1; // test for execute or search permission | ... | @@ -510,32 +490,6 @@ pub const X_OK = 1; // test for execute or search permission |
| 510 | pub const W_OK = 2; // test for write permission | 490 | pub const W_OK = 2; // test for write permission |
| 511 | pub const R_OK = 4; // test for read permission | 491 | pub const R_OK = 4; // test for read permission |
| 512 | 492 | ||
| 513 | pub const O = struct { | ||
| 514 | pub const RDONLY = 0x0000; | ||
| 515 | pub const WRONLY = 0x0001; | ||
| 516 | pub const RDWR = 0x0002; | ||
| 517 | pub const ACCMODE = 0x0003; | ||
| 518 | pub const RWMASK = ACCMODE; | ||
| 519 | |||
| 520 | pub const EXCL = 0x0100; | ||
| 521 | pub const CREAT = 0x0200; | ||
| 522 | pub const TRUNC = 0x0400; | ||
| 523 | pub const NOCTTY = 0x1000; | ||
| 524 | pub const NOTRAVERSE = 0x2000; | ||
| 525 | |||
| 526 | pub const CLOEXEC = 0x00000040; | ||
| 527 | pub const NONBLOCK = 0x00000080; | ||
| 528 | pub const NDELAY = NONBLOCK; | ||
| 529 | pub const APPEND = 0x00000800; | ||
| 530 | pub const SYNC = 0x00010000; | ||
| 531 | pub const RSYNC = 0x00020000; | ||
| 532 | pub const DSYNC = 0x00040000; | ||
| 533 | pub const NOFOLLOW = 0x00080000; | ||
| 534 | pub const DIRECT = 0x00100000; | ||
| 535 | pub const NOCACHE = DIRECT; | ||
| 536 | pub const DIRECTORY = 0x00200000; | ||
| 537 | }; | ||
| 538 | |||
| 539 | pub const F = struct { | 493 | pub const F = struct { |
| 540 | pub const DUPFD = 0x0001; | 494 | pub const DUPFD = 0x0001; |
| 541 | pub const GETFD = 0x0002; | 495 | pub const GETFD = 0x0002; |
| ... | @@ -923,14 +877,6 @@ pub const S = struct { | ... | @@ -923,14 +877,6 @@ pub const S = struct { |
| 923 | 877 | ||
| 924 | pub const HOST_NAME_MAX = 255; | 878 | pub const HOST_NAME_MAX = 255; |
| 925 | 879 | ||
| 926 | pub const AT = struct { | ||
| 927 | pub const FDCWD = -1; | ||
| 928 | pub const SYMLINK_NOFOLLOW = 0x01; | ||
| 929 | pub const SYMLINK_FOLLOW = 0x02; | ||
| 930 | pub const REMOVEDIR = 0x04; | ||
| 931 | pub const EACCESS = 0x08; | ||
| 932 | }; | ||
| 933 | |||
| 934 | pub const addrinfo = extern struct { | 880 | pub const addrinfo = extern struct { |
| 935 | flags: i32, | 881 | flags: i32, |
| 936 | family: i32, | 882 | family: i32, |
lib/std/c/hermit.zig deleted-12| ... | @@ -1,12 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const maxInt = std.math.maxInt; | ||
| 3 | |||
| 4 | pub const pthread_mutex_t = extern struct { | ||
| 5 | inner: usize = ~@as(usize, 0), | ||
| 6 | }; | ||
| 7 | pub const pthread_cond_t = extern struct { | ||
| 8 | inner: usize = ~@as(usize, 0), | ||
| 9 | }; | ||
| 10 | pub const pthread_rwlock_t = extern struct { | ||
| 11 | ptr: usize = maxInt(usize), | ||
| 12 | }; | ||
lib/std/c/linux.zig+13-47| ... | @@ -9,7 +9,6 @@ const FILE = std.c.FILE; | ... | @@ -9,7 +9,6 @@ const FILE = std.c.FILE; |
| 9 | 9 | ||
| 10 | pub const AF = linux.AF; | 10 | pub const AF = linux.AF; |
| 11 | pub const ARCH = linux.ARCH; | 11 | pub const ARCH = linux.ARCH; |
| 12 | pub const AT = linux.AT; | ||
| 13 | pub const CLOCK = linux.CLOCK; | 12 | pub const CLOCK = linux.CLOCK; |
| 14 | pub const CPU_COUNT = linux.CPU_COUNT; | 13 | pub const CPU_COUNT = linux.CPU_COUNT; |
| 15 | pub const E = linux.E; | 14 | pub const E = linux.E; |
| ... | @@ -28,7 +27,6 @@ pub const MSF = linux.MSF; | ... | @@ -28,7 +27,6 @@ pub const MSF = linux.MSF; |
| 28 | pub const MMAP2_UNIT = linux.MMAP2_UNIT; | 27 | pub const MMAP2_UNIT = linux.MMAP2_UNIT; |
| 29 | pub const MSG = linux.MSG; | 28 | pub const MSG = linux.MSG; |
| 30 | pub const NAME_MAX = linux.NAME_MAX; | 29 | pub const NAME_MAX = linux.NAME_MAX; |
| 31 | pub const O = linux.O; | ||
| 32 | pub const PATH_MAX = linux.PATH_MAX; | 30 | pub const PATH_MAX = linux.PATH_MAX; |
| 33 | pub const POLL = linux.POLL; | 31 | pub const POLL = linux.POLL; |
| 34 | pub const PROT = linux.PROT; | 32 | pub const PROT = linux.PROT; |
| ... | @@ -241,8 +239,8 @@ pub extern "c" fn ftruncate64(fd: c_int, length: off_t) c_int; | ... | @@ -241,8 +239,8 @@ pub extern "c" fn ftruncate64(fd: c_int, length: off_t) c_int; |
| 241 | pub extern "c" fn getrlimit64(resource: rlimit_resource, rlim: *rlimit) c_int; | 239 | pub extern "c" fn getrlimit64(resource: rlimit_resource, rlim: *rlimit) c_int; |
| 242 | pub extern "c" fn lseek64(fd: fd_t, offset: i64, whence: c_int) i64; | 240 | pub extern "c" fn lseek64(fd: fd_t, offset: i64, whence: c_int) i64; |
| 243 | pub extern "c" fn mmap64(addr: ?*align(std.mem.page_size) anyopaque, len: usize, prot: c_uint, flags: c_uint, fd: fd_t, offset: i64) *anyopaque; | 241 | pub extern "c" fn mmap64(addr: ?*align(std.mem.page_size) anyopaque, len: usize, prot: c_uint, flags: c_uint, fd: fd_t, offset: i64) *anyopaque; |
| 244 | pub extern "c" fn open64(path: [*:0]const u8, oflag: c_uint, ...) c_int; | 242 | pub extern "c" fn open64(path: [*:0]const u8, oflag: linux.O, ...) c_int; |
| 245 | pub extern "c" fn openat64(fd: c_int, path: [*:0]const u8, oflag: c_uint, ...) c_int; | 243 | pub extern "c" fn openat64(fd: c_int, path: [*:0]const u8, oflag: linux.O, ...) c_int; |
| 246 | pub extern "c" fn pread64(fd: fd_t, buf: [*]u8, nbyte: usize, offset: i64) isize; | 244 | pub extern "c" fn pread64(fd: fd_t, buf: [*]u8, nbyte: usize, offset: i64) isize; |
| 247 | pub extern "c" fn preadv64(fd: c_int, iov: [*]const iovec, iovcnt: c_uint, offset: i64) isize; | 245 | pub extern "c" fn preadv64(fd: c_int, iov: [*]const iovec, iovcnt: c_uint, offset: i64) isize; |
| 248 | pub extern "c" fn pwrite64(fd: fd_t, buf: [*]const u8, nbyte: usize, offset: i64) isize; | 246 | pub extern "c" fn pwrite64(fd: fd_t, buf: [*]const u8, nbyte: usize, offset: i64) isize; |
| ... | @@ -277,7 +275,7 @@ pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*an | ... | @@ -277,7 +275,7 @@ pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*an |
| 277 | pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; | 275 | pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; |
| 278 | 276 | ||
| 279 | pub extern "c" fn memfd_create(name: [*:0]const u8, flags: c_uint) c_int; | 277 | pub extern "c" fn memfd_create(name: [*:0]const u8, flags: c_uint) c_int; |
| 280 | pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int; | 278 | pub extern "c" fn pipe2(fds: *[2]fd_t, flags: linux.O) c_int; |
| 281 | 279 | ||
| 282 | pub extern "c" fn fallocate(fd: fd_t, mode: c_int, offset: off_t, len: off_t) c_int; | 280 | pub extern "c" fn fallocate(fd: fd_t, mode: c_int, offset: off_t, len: off_t) c_int; |
| 283 | 281 | ||
| ... | @@ -313,43 +311,11 @@ pub const pthread_attr_t = extern struct { | ... | @@ -313,43 +311,11 @@ pub const pthread_attr_t = extern struct { |
| 313 | __align: c_long, | 311 | __align: c_long, |
| 314 | }; | 312 | }; |
| 315 | 313 | ||
| 316 | pub const pthread_mutex_t = extern struct { | ||
| 317 | size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, | ||
| 318 | }; | ||
| 319 | pub const pthread_cond_t = extern struct { | ||
| 320 | size: [__SIZEOF_PTHREAD_COND_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_COND_T, | ||
| 321 | }; | ||
| 322 | pub const pthread_rwlock_t = switch (native_abi) { | ||
| 323 | .android => switch (@sizeOf(usize)) { | ||
| 324 | 4 => extern struct { | ||
| 325 | size: [40]u8 align(@alignOf(usize)) = [_]u8{0} ** 40, | ||
| 326 | }, | ||
| 327 | 8 => extern struct { | ||
| 328 | size: [56]u8 align(@alignOf(usize)) = [_]u8{0} ** 56, | ||
| 329 | }, | ||
| 330 | else => @compileError("impossible pointer size"), | ||
| 331 | }, | ||
| 332 | else => extern struct { | ||
| 333 | size: [56]u8 align(@alignOf(usize)) = [_]u8{0} ** 56, | ||
| 334 | }, | ||
| 335 | }; | ||
| 336 | pub const pthread_key_t = c_uint; | 314 | pub const pthread_key_t = c_uint; |
| 337 | pub const sem_t = extern struct { | 315 | pub const sem_t = extern struct { |
| 338 | __size: [__SIZEOF_SEM_T]u8 align(@alignOf(usize)), | 316 | __size: [__SIZEOF_SEM_T]u8 align(@alignOf(usize)), |
| 339 | }; | 317 | }; |
| 340 | 318 | ||
| 341 | const __SIZEOF_PTHREAD_COND_T = 48; | ||
| 342 | const __SIZEOF_PTHREAD_MUTEX_T = switch (native_abi) { | ||
| 343 | .musl, .musleabi, .musleabihf => if (@sizeOf(usize) == 8) 40 else 24, | ||
| 344 | .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => switch (native_arch) { | ||
| 345 | .aarch64 => 48, | ||
| 346 | .x86_64 => if (native_abi == .gnux32) 40 else 32, | ||
| 347 | .mips64, .powerpc64, .powerpc64le, .sparc64 => 40, | ||
| 348 | else => if (@sizeOf(usize) == 8) 40 else 24, | ||
| 349 | }, | ||
| 350 | .android => if (@sizeOf(usize) == 8) 40 else 4, | ||
| 351 | else => @compileError("unsupported ABI"), | ||
| 352 | }; | ||
| 353 | const __SIZEOF_SEM_T = 4 * @sizeOf(usize); | 319 | const __SIZEOF_SEM_T = 4 * @sizeOf(usize); |
| 354 | 320 | ||
| 355 | pub extern "c" fn pthread_setname_np(thread: std.c.pthread_t, name: [*:0]const u8) E; | 321 | pub extern "c" fn pthread_setname_np(thread: std.c.pthread_t, name: [*:0]const u8) E; |
| ... | @@ -365,16 +331,16 @@ pub const RTLD = struct { | ... | @@ -365,16 +331,16 @@ pub const RTLD = struct { |
| 365 | }; | 331 | }; |
| 366 | 332 | ||
| 367 | pub const dirent = struct { | 333 | pub const dirent = struct { |
| 368 | d_ino: c_uint, | 334 | ino: c_uint, |
| 369 | d_off: c_uint, | 335 | off: c_uint, |
| 370 | d_reclen: c_ushort, | 336 | reclen: c_ushort, |
| 371 | d_type: u8, | 337 | type: u8, |
| 372 | d_name: [256]u8, | 338 | name: [256]u8, |
| 373 | }; | 339 | }; |
| 374 | pub const dirent64 = struct { | 340 | pub const dirent64 = struct { |
| 375 | d_ino: c_ulong, | 341 | ino: c_ulong, |
| 376 | d_off: c_ulong, | 342 | off: c_ulong, |
| 377 | d_reclen: c_ushort, | 343 | reclen: c_ushort, |
| 378 | d_type: u8, | 344 | type: u8, |
| 379 | d_name: [256]u8, | 345 | name: [256]u8, |
| 380 | }; | 346 | }; |
lib/std/c/minix.zig deleted-18| ... | @@ -1,18 +0,0 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | pub const pthread_mutex_t = extern struct { | ||
| 3 | size: [__SIZEOF_PTHREAD_MUTEX_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_MUTEX_T, | ||
| 4 | }; | ||
| 5 | pub const pthread_cond_t = extern struct { | ||
| 6 | size: [__SIZEOF_PTHREAD_COND_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_COND_T, | ||
| 7 | }; | ||
| 8 | const __SIZEOF_PTHREAD_COND_T = 48; | ||
| 9 | const __SIZEOF_PTHREAD_MUTEX_T = switch (builtin.abi) { | ||
| 10 | .musl, .musleabi, .musleabihf => if (@sizeOf(usize) == 8) 40 else 24, | ||
| 11 | .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => switch (builtin.cpu.arch) { | ||
| 12 | .aarch64 => 48, | ||
| 13 | .x86_64 => if (builtin.abi == .gnux32) 40 else 32, | ||
| 14 | .mips64, .powerpc64, .powerpc64le, .sparc64 => 40, | ||
| 15 | else => if (@sizeOf(usize) == 8) 40 else 24, | ||
| 16 | }, | ||
| 17 | else => unreachable, | ||
| 18 | }; | ||
lib/std/c/netbsd.zig+5-109| ... | @@ -18,9 +18,6 @@ pub extern "c" fn _lwp_self() lwpid_t; | ... | @@ -18,9 +18,6 @@ pub extern "c" fn _lwp_self() lwpid_t; |
| 18 | pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int; | 18 | pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int; |
| 19 | pub extern "c" fn arc4random_buf(buf: [*]u8, len: usize) void; | 19 | pub extern "c" fn arc4random_buf(buf: [*]u8, len: usize) void; |
| 20 | 20 | ||
| 21 | pub extern "c" fn __fstat50(fd: fd_t, buf: *Stat) c_int; | ||
| 22 | pub const fstat = __fstat50; | ||
| 23 | |||
| 24 | pub extern "c" fn __stat50(path: [*:0]const u8, buf: *Stat) c_int; | 21 | pub extern "c" fn __stat50(path: [*:0]const u8, buf: *Stat) c_int; |
| 25 | pub const stat = __stat50; | 22 | pub const stat = __stat50; |
| 26 | 23 | ||
| ... | @@ -62,41 +59,6 @@ pub extern "c" fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: u | ... | @@ -62,41 +59,6 @@ pub extern "c" fn posix_memalign(memptr: *?*anyopaque, alignment: usize, size: u |
| 62 | pub extern "c" fn __msync13(addr: *align(std.mem.page_size) const anyopaque, len: usize, flags: c_int) c_int; | 59 | pub extern "c" fn __msync13(addr: *align(std.mem.page_size) const anyopaque, len: usize, flags: c_int) c_int; |
| 63 | pub const msync = __msync13; | 60 | pub const msync = __msync13; |
| 64 | 61 | ||
| 65 | pub const pthread_mutex_t = extern struct { | ||
| 66 | magic: u32 = 0x33330003, | ||
| 67 | errorcheck: padded_pthread_spin_t = 0, | ||
| 68 | ceiling: padded_pthread_spin_t = 0, | ||
| 69 | owner: usize = 0, | ||
| 70 | waiters: ?*u8 = null, | ||
| 71 | recursed: u32 = 0, | ||
| 72 | spare2: ?*anyopaque = null, | ||
| 73 | }; | ||
| 74 | |||
| 75 | pub const pthread_cond_t = extern struct { | ||
| 76 | magic: u32 = 0x55550005, | ||
| 77 | lock: pthread_spin_t = 0, | ||
| 78 | waiters_first: ?*u8 = null, | ||
| 79 | waiters_last: ?*u8 = null, | ||
| 80 | mutex: ?*pthread_mutex_t = null, | ||
| 81 | private: ?*anyopaque = null, | ||
| 82 | }; | ||
| 83 | |||
| 84 | pub const pthread_rwlock_t = extern struct { | ||
| 85 | magic: c_uint = 0x99990009, | ||
| 86 | interlock: switch (builtin.cpu.arch) { | ||
| 87 | .aarch64, .sparc, .x86_64, .x86 => u8, | ||
| 88 | .arm, .powerpc => c_int, | ||
| 89 | else => unreachable, | ||
| 90 | } = 0, | ||
| 91 | rblocked_first: ?*u8 = null, | ||
| 92 | rblocked_last: ?*u8 = null, | ||
| 93 | wblocked_first: ?*u8 = null, | ||
| 94 | wblocked_last: ?*u8 = null, | ||
| 95 | nreaders: c_uint = 0, | ||
| 96 | owner: ?std.c.pthread_t = null, | ||
| 97 | private: ?*anyopaque = null, | ||
| 98 | }; | ||
| 99 | |||
| 100 | const pthread_spin_t = switch (builtin.cpu.arch) { | 62 | const pthread_spin_t = switch (builtin.cpu.arch) { |
| 101 | .aarch64, .aarch64_be, .aarch64_32 => u8, | 63 | .aarch64, .aarch64_be, .aarch64_32 => u8, |
| 102 | .mips, .mipsel, .mips64, .mips64el => u32, | 64 | .mips, .mipsel, .mips64, .mips64el => u32, |
| ... | @@ -337,15 +299,11 @@ pub const timeval = extern struct { | ... | @@ -337,15 +299,11 @@ pub const timeval = extern struct { |
| 337 | pub const MAXNAMLEN = 511; | 299 | pub const MAXNAMLEN = 511; |
| 338 | 300 | ||
| 339 | pub const dirent = extern struct { | 301 | pub const dirent = extern struct { |
| 340 | d_fileno: ino_t, | 302 | fileno: ino_t, |
| 341 | d_reclen: u16, | 303 | reclen: u16, |
| 342 | d_namlen: u16, | 304 | namlen: u16, |
| 343 | d_type: u8, | 305 | type: u8, |
| 344 | d_name: [MAXNAMLEN + 1]u8, | 306 | name: [MAXNAMLEN + 1]u8, |
| 345 | |||
| 346 | pub fn reclen(self: dirent) u16 { | ||
| 347 | return self.d_reclen; | ||
| 348 | } | ||
| 349 | }; | 307 | }; |
| 350 | 308 | ||
| 351 | pub const SOCK = struct { | 309 | pub const SOCK = struct { |
| ... | @@ -630,53 +588,6 @@ pub const X_OK = 1; // test for execute or search permission | ... | @@ -630,53 +588,6 @@ pub const X_OK = 1; // test for execute or search permission |
| 630 | pub const W_OK = 2; // test for write permission | 588 | pub const W_OK = 2; // test for write permission |
| 631 | pub const R_OK = 4; // test for read permission | 589 | pub const R_OK = 4; // test for read permission |
| 632 | 590 | ||
| 633 | pub const O = struct { | ||
| 634 | /// open for reading only | ||
| 635 | pub const RDONLY = 0x00000000; | ||
| 636 | /// open for writing only | ||
| 637 | pub const WRONLY = 0x00000001; | ||
| 638 | /// open for reading and writing | ||
| 639 | pub const RDWR = 0x00000002; | ||
| 640 | /// mask for above modes | ||
| 641 | pub const ACCMODE = 0x00000003; | ||
| 642 | /// no delay | ||
| 643 | pub const NONBLOCK = 0x00000004; | ||
| 644 | /// set append mode | ||
| 645 | pub const APPEND = 0x00000008; | ||
| 646 | /// open with shared file lock | ||
| 647 | pub const SHLOCK = 0x00000010; | ||
| 648 | /// open with exclusive file lock | ||
| 649 | pub const EXLOCK = 0x00000020; | ||
| 650 | /// signal pgrp when data ready | ||
| 651 | pub const ASYNC = 0x00000040; | ||
| 652 | /// synchronous writes | ||
| 653 | pub const SYNC = 0x00000080; | ||
| 654 | /// don't follow symlinks on the last | ||
| 655 | pub const NOFOLLOW = 0x00000100; | ||
| 656 | /// create if nonexistent | ||
| 657 | pub const CREAT = 0x00000200; | ||
| 658 | /// truncate to zero length | ||
| 659 | pub const TRUNC = 0x00000400; | ||
| 660 | /// error if already exists | ||
| 661 | pub const EXCL = 0x00000800; | ||
| 662 | /// don't assign controlling terminal | ||
| 663 | pub const NOCTTY = 0x00008000; | ||
| 664 | /// write: I/O data completion | ||
| 665 | pub const DSYNC = 0x00010000; | ||
| 666 | /// read: I/O completion as for write | ||
| 667 | pub const RSYNC = 0x00020000; | ||
| 668 | /// use alternate i/o semantics | ||
| 669 | pub const ALT_IO = 0x00040000; | ||
| 670 | /// direct I/O hint | ||
| 671 | pub const DIRECT = 0x00080000; | ||
| 672 | /// fail if not a directory | ||
| 673 | pub const DIRECTORY = 0x00200000; | ||
| 674 | /// set close on exec | ||
| 675 | pub const CLOEXEC = 0x00400000; | ||
| 676 | /// skip search permission checks | ||
| 677 | pub const SEARCH = 0x00800000; | ||
| 678 | }; | ||
| 679 | |||
| 680 | pub const F = struct { | 591 | pub const F = struct { |
| 681 | pub const DUPFD = 0; | 592 | pub const DUPFD = 0; |
| 682 | pub const GETFD = 1; | 593 | pub const GETFD = 1; |
| ... | @@ -1466,21 +1377,6 @@ pub const S = struct { | ... | @@ -1466,21 +1377,6 @@ pub const S = struct { |
| 1466 | } | 1377 | } |
| 1467 | }; | 1378 | }; |
| 1468 | 1379 | ||
| 1469 | pub const AT = struct { | ||
| 1470 | /// Magic value that specify the use of the current working directory | ||
| 1471 | /// to determine the target of relative file paths in the openat() and | ||
| 1472 | /// similar syscalls. | ||
| 1473 | pub const FDCWD = -100; | ||
| 1474 | /// Check access using effective user and group ID | ||
| 1475 | pub const EACCESS = 0x0100; | ||
| 1476 | /// Do not follow symbolic links | ||
| 1477 | pub const SYMLINK_NOFOLLOW = 0x0200; | ||
| 1478 | /// Follow symbolic link | ||
| 1479 | pub const SYMLINK_FOLLOW = 0x0400; | ||
| 1480 | /// Remove directory instead of file | ||
| 1481 | pub const REMOVEDIR = 0x0800; | ||
| 1482 | }; | ||
| 1483 | |||
| 1484 | pub const HOST_NAME_MAX = 255; | 1380 | pub const HOST_NAME_MAX = 255; |
| 1485 | 1381 | ||
| 1486 | pub const IPPROTO = struct { | 1382 | pub const IPPROTO = struct { |
lib/std/c/openbsd.zig+7-76| ... | @@ -19,15 +19,6 @@ pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int; | ... | @@ -19,15 +19,6 @@ pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int; |
| 19 | pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) c_int; | 19 | pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) c_int; |
| 20 | pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; | 20 | pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; |
| 21 | 21 | ||
| 22 | pub const pthread_mutex_t = extern struct { | ||
| 23 | inner: ?*anyopaque = null, | ||
| 24 | }; | ||
| 25 | pub const pthread_cond_t = extern struct { | ||
| 26 | inner: ?*anyopaque = null, | ||
| 27 | }; | ||
| 28 | pub const pthread_rwlock_t = extern struct { | ||
| 29 | ptr: ?*anyopaque = null, | ||
| 30 | }; | ||
| 31 | pub const pthread_spinlock_t = extern struct { | 22 | pub const pthread_spinlock_t = extern struct { |
| 32 | inner: ?*anyopaque = null, | 23 | inner: ?*anyopaque = null, |
| 33 | }; | 24 | }; |
| ... | @@ -336,17 +327,13 @@ pub const timezone = extern struct { | ... | @@ -336,17 +327,13 @@ pub const timezone = extern struct { |
| 336 | pub const MAXNAMLEN = 255; | 327 | pub const MAXNAMLEN = 255; |
| 337 | 328 | ||
| 338 | pub const dirent = extern struct { | 329 | pub const dirent = extern struct { |
| 339 | d_fileno: ino_t, | 330 | fileno: ino_t, |
| 340 | d_off: off_t, | 331 | off: off_t, |
| 341 | d_reclen: u16, | 332 | reclen: u16, |
| 342 | d_type: u8, | 333 | type: u8, |
| 343 | d_namlen: u8, | 334 | namlen: u8, |
| 344 | __d_padding: [4]u8, | 335 | _: u32 align(1) = 0, |
| 345 | d_name: [MAXNAMLEN + 1]u8, | 336 | name: [MAXNAMLEN + 1]u8, |
| 346 | |||
| 347 | pub fn reclen(self: dirent) u16 { | ||
| 348 | return self.d_reclen; | ||
| 349 | } | ||
| 350 | }; | 337 | }; |
| 351 | 338 | ||
| 352 | pub const in_port_t = u16; | 339 | pub const in_port_t = u16; |
| ... | @@ -489,47 +476,6 @@ pub const X_OK = 1; // test for execute or search permission | ... | @@ -489,47 +476,6 @@ pub const X_OK = 1; // test for execute or search permission |
| 489 | pub const W_OK = 2; // test for write permission | 476 | pub const W_OK = 2; // test for write permission |
| 490 | pub const R_OK = 4; // test for read permission | 477 | pub const R_OK = 4; // test for read permission |
| 491 | 478 | ||
| 492 | pub const O = struct { | ||
| 493 | /// open for reading only | ||
| 494 | pub const RDONLY = 0x00000000; | ||
| 495 | /// open for writing only | ||
| 496 | pub const WRONLY = 0x00000001; | ||
| 497 | /// open for reading and writing | ||
| 498 | pub const RDWR = 0x00000002; | ||
| 499 | /// mask for above modes | ||
| 500 | pub const ACCMODE = 0x00000003; | ||
| 501 | /// no delay | ||
| 502 | pub const NONBLOCK = 0x00000004; | ||
| 503 | /// set append mode | ||
| 504 | pub const APPEND = 0x00000008; | ||
| 505 | /// open with shared file lock | ||
| 506 | pub const SHLOCK = 0x00000010; | ||
| 507 | /// open with exclusive file lock | ||
| 508 | pub const EXLOCK = 0x00000020; | ||
| 509 | /// signal pgrp when data ready | ||
| 510 | pub const ASYNC = 0x00000040; | ||
| 511 | /// synchronous writes | ||
| 512 | pub const SYNC = 0x00000080; | ||
| 513 | /// don't follow symlinks on the last | ||
| 514 | pub const NOFOLLOW = 0x00000100; | ||
| 515 | /// create if nonexistent | ||
| 516 | pub const CREAT = 0x00000200; | ||
| 517 | /// truncate to zero length | ||
| 518 | pub const TRUNC = 0x00000400; | ||
| 519 | /// error if already exists | ||
| 520 | pub const EXCL = 0x00000800; | ||
| 521 | /// don't assign controlling terminal | ||
| 522 | pub const NOCTTY = 0x00008000; | ||
| 523 | /// write: I/O data completion | ||
| 524 | pub const DSYNC = SYNC; | ||
| 525 | /// read: I/O completion as for write | ||
| 526 | pub const RSYNC = SYNC; | ||
| 527 | /// fail if not a directory | ||
| 528 | pub const DIRECTORY = 0x20000; | ||
| 529 | /// set close on exec | ||
| 530 | pub const CLOEXEC = 0x10000; | ||
| 531 | }; | ||
| 532 | |||
| 533 | pub const F = struct { | 479 | pub const F = struct { |
| 534 | pub const DUPFD = 0; | 480 | pub const DUPFD = 0; |
| 535 | pub const GETFD = 1; | 481 | pub const GETFD = 1; |
| ... | @@ -1312,21 +1258,6 @@ pub const S = struct { | ... | @@ -1312,21 +1258,6 @@ pub const S = struct { |
| 1312 | } | 1258 | } |
| 1313 | }; | 1259 | }; |
| 1314 | 1260 | ||
| 1315 | pub const AT = struct { | ||
| 1316 | /// Magic value that specify the use of the current working directory | ||
| 1317 | /// to determine the target of relative file paths in the openat() and | ||
| 1318 | /// similar syscalls. | ||
| 1319 | pub const FDCWD = -100; | ||
| 1320 | /// Check access using effective user and group ID | ||
| 1321 | pub const EACCESS = 0x01; | ||
| 1322 | /// Do not follow symbolic links | ||
| 1323 | pub const SYMLINK_NOFOLLOW = 0x02; | ||
| 1324 | /// Follow symbolic link | ||
| 1325 | pub const SYMLINK_FOLLOW = 0x04; | ||
| 1326 | /// Remove directory instead of file | ||
| 1327 | pub const REMOVEDIR = 0x08; | ||
| 1328 | }; | ||
| 1329 | |||
| 1330 | pub const HOST_NAME_MAX = 255; | 1261 | pub const HOST_NAME_MAX = 255; |
| 1331 | 1262 | ||
| 1332 | pub const IPPROTO = struct { | 1263 | pub const IPPROTO = struct { |
lib/std/c/solaris.zig+4-74| ... | @@ -21,29 +21,6 @@ pub extern "c" fn sysconf(sc: c_int) i64; | ... | @@ -21,29 +21,6 @@ pub extern "c" fn sysconf(sc: c_int) i64; |
| 21 | pub extern "c" fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) c_int; | 21 | pub extern "c" fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) c_int; |
| 22 | pub extern "c" fn madvise(address: [*]u8, len: usize, advise: u32) c_int; | 22 | pub extern "c" fn madvise(address: [*]u8, len: usize, advise: u32) c_int; |
| 23 | 23 | ||
| 24 | pub const pthread_mutex_t = extern struct { | ||
| 25 | flag1: u16 = 0, | ||
| 26 | flag2: u8 = 0, | ||
| 27 | ceiling: u8 = 0, | ||
| 28 | type: u16 = 0, | ||
| 29 | magic: u16 = 0x4d58, | ||
| 30 | lock: u64 = 0, | ||
| 31 | data: u64 = 0, | ||
| 32 | }; | ||
| 33 | pub const pthread_cond_t = extern struct { | ||
| 34 | flag: [4]u8 = [_]u8{0} ** 4, | ||
| 35 | type: u16 = 0, | ||
| 36 | magic: u16 = 0x4356, | ||
| 37 | data: u64 = 0, | ||
| 38 | }; | ||
| 39 | pub const pthread_rwlock_t = extern struct { | ||
| 40 | readers: i32 = 0, | ||
| 41 | type: u16 = 0, | ||
| 42 | magic: u16 = 0x5257, | ||
| 43 | mutex: pthread_mutex_t = .{}, | ||
| 44 | readercv: pthread_cond_t = .{}, | ||
| 45 | writercv: pthread_cond_t = .{}, | ||
| 46 | }; | ||
| 47 | pub const pthread_attr_t = extern struct { | 24 | pub const pthread_attr_t = extern struct { |
| 48 | mutexattr: ?*anyopaque = null, | 25 | mutexattr: ?*anyopaque = null, |
| 49 | }; | 26 | }; |
| ... | @@ -266,17 +243,13 @@ pub const MAXNAMLEN = 511; | ... | @@ -266,17 +243,13 @@ pub const MAXNAMLEN = 511; |
| 266 | 243 | ||
| 267 | pub const dirent = extern struct { | 244 | pub const dirent = extern struct { |
| 268 | /// Inode number of entry. | 245 | /// Inode number of entry. |
| 269 | d_ino: ino_t, | 246 | ino: ino_t, |
| 270 | /// Offset of this entry on disk. | 247 | /// Offset of this entry on disk. |
| 271 | d_off: off_t, | 248 | off: off_t, |
| 272 | /// Length of this record. | 249 | /// Length of this record. |
| 273 | d_reclen: u16, | 250 | reclen: u16, |
| 274 | /// File name. | 251 | /// File name. |
| 275 | d_name: [MAXNAMLEN:0]u8, | 252 | name: [MAXNAMLEN:0]u8, |
| 276 | |||
| 277 | pub fn reclen(self: dirent) u16 { | ||
| 278 | return self.d_reclen; | ||
| 279 | } | ||
| 280 | }; | 253 | }; |
| 281 | 254 | ||
| 282 | pub const SOCK = struct { | 255 | pub const SOCK = struct { |
| ... | @@ -708,32 +681,6 @@ pub const F = struct { | ... | @@ -708,32 +681,6 @@ pub const F = struct { |
| 708 | pub const RMDNY = 0x4; | 681 | pub const RMDNY = 0x4; |
| 709 | }; | 682 | }; |
| 710 | 683 | ||
| 711 | pub const O = struct { | ||
| 712 | pub const RDONLY = 0; | ||
| 713 | pub const WRONLY = 1; | ||
| 714 | pub const RDWR = 2; | ||
| 715 | pub const SEARCH = 0x200000; | ||
| 716 | pub const EXEC = 0x400000; | ||
| 717 | pub const NDELAY = 0x04; | ||
| 718 | pub const APPEND = 0x08; | ||
| 719 | pub const SYNC = 0x10; | ||
| 720 | pub const DSYNC = 0x40; | ||
| 721 | pub const RSYNC = 0x8000; | ||
| 722 | pub const NONBLOCK = 0x80; | ||
| 723 | pub const LARGEFILE = 0x2000; | ||
| 724 | |||
| 725 | pub const CREAT = 0x100; | ||
| 726 | pub const TRUNC = 0x200; | ||
| 727 | pub const EXCL = 0x400; | ||
| 728 | pub const NOCTTY = 0x800; | ||
| 729 | pub const XATTR = 0x4000; | ||
| 730 | pub const NOFOLLOW = 0x20000; | ||
| 731 | pub const NOLINKS = 0x40000; | ||
| 732 | pub const CLOEXEC = 0x800000; | ||
| 733 | pub const DIRECTORY = 0x1000000; | ||
| 734 | pub const DIRECT = 0x2000000; | ||
| 735 | }; | ||
| 736 | |||
| 737 | pub const LOCK = struct { | 684 | pub const LOCK = struct { |
| 738 | pub const SH = 1; | 685 | pub const SH = 1; |
| 739 | pub const EX = 2; | 686 | pub const EX = 2; |
| ... | @@ -1430,23 +1377,6 @@ pub const S = struct { | ... | @@ -1430,23 +1377,6 @@ pub const S = struct { |
| 1430 | } | 1377 | } |
| 1431 | }; | 1378 | }; |
| 1432 | 1379 | ||
| 1433 | pub const AT = struct { | ||
| 1434 | /// Magic value that specify the use of the current working directory | ||
| 1435 | /// to determine the target of relative file paths in the openat() and | ||
| 1436 | /// similar syscalls. | ||
| 1437 | pub const FDCWD = @as(fd_t, @bitCast(@as(u32, 0xffd19553))); | ||
| 1438 | |||
| 1439 | /// Do not follow symbolic links | ||
| 1440 | pub const SYMLINK_NOFOLLOW = 0x1000; | ||
| 1441 | /// Follow symbolic link | ||
| 1442 | pub const SYMLINK_FOLLOW = 0x2000; | ||
| 1443 | /// Remove directory instead of file | ||
| 1444 | pub const REMOVEDIR = 0x1; | ||
| 1445 | pub const TRIGGER = 0x2; | ||
| 1446 | /// Check access using effective user and group ID | ||
| 1447 | pub const EACCESS = 0x4; | ||
| 1448 | }; | ||
| 1449 | |||
| 1450 | pub const POSIX_FADV = struct { | 1380 | pub const POSIX_FADV = struct { |
| 1451 | pub const NORMAL = 0; | 1381 | pub const NORMAL = 0; |
| 1452 | pub const RANDOM = 1; | 1382 | pub const RANDOM = 1; |
lib/std/c/wasi.zig+90-45| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const builtin = @import("builtin"); | ||
| 1 | const std = @import("../std.zig"); | 2 | const std = @import("../std.zig"); |
| 2 | const wasi = std.os.wasi; | 3 | const wasi = std.os.wasi; |
| 3 | const FDFLAG = wasi.FDFLAG; | ||
| 4 | 4 | ||
| 5 | extern threadlocal var errno: c_int; | 5 | extern threadlocal var errno: c_int; |
| 6 | 6 | ||
| ... | @@ -8,42 +8,82 @@ pub fn _errno() *c_int { | ... | @@ -8,42 +8,82 @@ pub fn _errno() *c_int { |
| 8 | return &errno; | 8 | return &errno; |
| 9 | } | 9 | } |
| 10 | 10 | ||
| 11 | pub const AT = wasi.AT; | 11 | pub const mode_t = u32; |
| 12 | pub const CLOCK = wasi.CLOCK; | 12 | pub const time_t = i64; |
| 13 | pub const E = wasi.E; | 13 | |
| 14 | pub const IOV_MAX = wasi.IOV_MAX; | 14 | pub const timespec = extern struct { |
| 15 | pub const LOCK = wasi.LOCK; | 15 | tv_sec: time_t, |
| 16 | pub const S = wasi.S; | 16 | tv_nsec: isize, |
| 17 | pub const STDERR_FILENO = wasi.STDERR_FILENO; | 17 | |
| 18 | pub const STDIN_FILENO = wasi.STDIN_FILENO; | 18 | pub fn fromTimestamp(tm: wasi.timestamp_t) timespec { |
| 19 | pub const STDOUT_FILENO = wasi.STDOUT_FILENO; | 19 | const tv_sec: wasi.timestamp_t = tm / 1_000_000_000; |
| 20 | const tv_nsec = tm - tv_sec * 1_000_000_000; | ||
| 21 | return .{ | ||
| 22 | .tv_sec = @as(time_t, @intCast(tv_sec)), | ||
| 23 | .tv_nsec = @as(isize, @intCast(tv_nsec)), | ||
| 24 | }; | ||
| 25 | } | ||
| 26 | |||
| 27 | pub fn toTimestamp(ts: timespec) wasi.timestamp_t { | ||
| 28 | return @as(wasi.timestamp_t, @intCast(ts.tv_sec * 1_000_000_000)) + | ||
| 29 | @as(wasi.timestamp_t, @intCast(ts.tv_nsec)); | ||
| 30 | } | ||
| 31 | }; | ||
| 32 | |||
| 33 | pub const STDIN_FILENO = 0; | ||
| 34 | pub const STDOUT_FILENO = 1; | ||
| 35 | pub const STDERR_FILENO = 2; | ||
| 36 | |||
| 37 | pub const E = wasi.errno_t; | ||
| 38 | |||
| 39 | pub const CLOCK = wasi.clockid_t; | ||
| 40 | pub const IOV_MAX = 1024; | ||
| 41 | pub const LOCK = struct { | ||
| 42 | pub const SH = 0x1; | ||
| 43 | pub const EX = 0x2; | ||
| 44 | pub const NB = 0x4; | ||
| 45 | pub const UN = 0x8; | ||
| 46 | }; | ||
| 47 | pub const S = struct { | ||
| 48 | pub const IEXEC = @compileError("TODO audit this"); | ||
| 49 | pub const IFBLK = 0x6000; | ||
| 50 | pub const IFCHR = 0x2000; | ||
| 51 | pub const IFDIR = 0x4000; | ||
| 52 | pub const IFIFO = 0xc000; | ||
| 53 | pub const IFLNK = 0xa000; | ||
| 54 | pub const IFMT = IFBLK | IFCHR | IFDIR | IFIFO | IFLNK | IFREG | IFSOCK; | ||
| 55 | pub const IFREG = 0x8000; | ||
| 56 | /// There's no concept of UNIX domain socket but we define this value here | ||
| 57 | /// in order to line with other OSes. | ||
| 58 | pub const IFSOCK = 0x1; | ||
| 59 | }; | ||
| 20 | pub const fd_t = wasi.fd_t; | 60 | pub const fd_t = wasi.fd_t; |
| 21 | pub const pid_t = c_int; | 61 | pub const pid_t = c_int; |
| 22 | pub const uid_t = u32; | 62 | pub const uid_t = u32; |
| 23 | pub const gid_t = u32; | 63 | pub const gid_t = u32; |
| 24 | pub const off_t = i64; | 64 | pub const off_t = i64; |
| 25 | pub const ino_t = wasi.ino_t; | 65 | pub const ino_t = wasi.inode_t; |
| 26 | pub const mode_t = wasi.mode_t; | 66 | pub const dev_t = wasi.device_t; |
| 27 | pub const time_t = wasi.time_t; | 67 | pub const nlink_t = c_ulonglong; |
| 28 | pub const timespec = wasi.timespec; | 68 | pub const blksize_t = c_long; |
| 69 | pub const blkcnt_t = c_longlong; | ||
| 29 | 70 | ||
| 30 | pub const Stat = extern struct { | 71 | pub const Stat = extern struct { |
| 31 | dev: i32, | 72 | dev: dev_t, |
| 32 | ino: ino_t, | 73 | ino: ino_t, |
| 33 | nlink: u64, | 74 | nlink: nlink_t, |
| 34 | |||
| 35 | mode: mode_t, | 75 | mode: mode_t, |
| 36 | uid: uid_t, | 76 | uid: uid_t, |
| 37 | gid: gid_t, | 77 | gid: gid_t, |
| 38 | __pad0: isize, | 78 | __pad0: c_uint = 0, |
| 39 | rdev: i32, | 79 | rdev: dev_t, |
| 40 | size: off_t, | 80 | size: off_t, |
| 41 | blksize: i32, | 81 | blksize: blksize_t, |
| 42 | blocks: i64, | 82 | blocks: blkcnt_t, |
| 43 | |||
| 44 | atim: timespec, | 83 | atim: timespec, |
| 45 | mtim: timespec, | 84 | mtim: timespec, |
| 46 | ctim: timespec, | 85 | ctim: timespec, |
| 86 | __reserved: [3]c_longlong = [3]c_longlong{ 0, 0, 0 }, | ||
| 47 | 87 | ||
| 48 | pub fn atime(self: @This()) timespec { | 88 | pub fn atime(self: @This()) timespec { |
| 49 | return self.atim; | 89 | return self.atim; |
| ... | @@ -56,30 +96,35 @@ pub const Stat = extern struct { | ... | @@ -56,30 +96,35 @@ pub const Stat = extern struct { |
| 56 | pub fn ctime(self: @This()) timespec { | 96 | pub fn ctime(self: @This()) timespec { |
| 57 | return self.ctim; | 97 | return self.ctim; |
| 58 | } | 98 | } |
| 59 | }; | ||
| 60 | 99 | ||
| 61 | /// Derived from | 100 | pub fn fromFilestat(stat: wasi.filestat_t) Stat { |
| 62 | /// https://github.com/WebAssembly/wasi-libc/blob/main/expected/wasm32-wasi/predefined-macros.txt | 101 | return .{ |
| 63 | pub const O = struct { | 102 | .dev = stat.dev, |
| 64 | pub const ACCMODE = (EXEC | RDWR | SEARCH); | 103 | .ino = stat.ino, |
| 65 | pub const APPEND = @as(u32, FDFLAG.APPEND); | 104 | .mode = switch (stat.filetype) { |
| 66 | pub const CLOEXEC = (0); | 105 | .UNKNOWN => 0, |
| 67 | pub const CREAT = ((1 << 0) << 12); // = __WASI_OFLAGS_CREAT << 12 | 106 | .BLOCK_DEVICE => S.IFBLK, |
| 68 | pub const DIRECTORY = ((1 << 1) << 12); // = __WASI_OFLAGS_DIRECTORY << 12 | 107 | .CHARACTER_DEVICE => S.IFCHR, |
| 69 | pub const DSYNC = @as(u32, FDFLAG.DSYNC); | 108 | .DIRECTORY => S.IFDIR, |
| 70 | pub const EXCL = ((1 << 2) << 12); // = __WASI_OFLAGS_EXCL << 12 | 109 | .REGULAR_FILE => S.IFREG, |
| 71 | pub const EXEC = (0x02000000); | 110 | .SOCKET_DGRAM => S.IFSOCK, |
| 72 | pub const NOCTTY = (0); | 111 | .SOCKET_STREAM => S.IFIFO, |
| 73 | pub const NOFOLLOW = (0x01000000); | 112 | .SYMBOLIC_LINK => S.IFLNK, |
| 74 | pub const NONBLOCK = @as(u32, FDFLAG.NONBLOCK); | 113 | _ => 0, |
| 75 | pub const RDONLY = (0x04000000); | 114 | }, |
| 76 | pub const RDWR = (RDONLY | WRONLY); | 115 | .nlink = stat.nlink, |
| 77 | pub const RSYNC = @as(u32, FDFLAG.RSYNC); | 116 | .size = @intCast(stat.size), |
| 78 | pub const SEARCH = (0x08000000); | 117 | .atim = timespec.fromTimestamp(stat.atim), |
| 79 | pub const SYNC = @as(u32, FDFLAG.SYNC); | 118 | .mtim = timespec.fromTimestamp(stat.mtim), |
| 80 | pub const TRUNC = ((1 << 3) << 12); // = __WASI_OFLAGS_TRUNC << 12 | 119 | .ctim = timespec.fromTimestamp(stat.ctim), |
| 81 | pub const TTY_INIT = (0); | 120 | |
| 82 | pub const WRONLY = (0x10000000); | 121 | .uid = 0, |
| 122 | .gid = 0, | ||
| 123 | .rdev = 0, | ||
| 124 | .blksize = 0, | ||
| 125 | .blocks = 0, | ||
| 126 | }; | ||
| 127 | } | ||
| 83 | }; | 128 | }; |
| 84 | 129 | ||
| 85 | pub const F = struct { | 130 | pub const F = struct { |
lib/std/c/windows.zig-33| ... | @@ -11,7 +11,6 @@ pub extern "c" fn _msize(memblock: ?*anyopaque) usize; | ... | @@ -11,7 +11,6 @@ pub extern "c" fn _msize(memblock: ?*anyopaque) usize; |
| 11 | // need to verify which of these is actually supported on windows | 11 | // need to verify which of these is actually supported on windows |
| 12 | pub extern "c" fn clock_getres(clk_id: c_int, tp: *timespec) c_int; | 12 | pub extern "c" fn clock_getres(clk_id: c_int, tp: *timespec) c_int; |
| 13 | pub extern "c" fn clock_gettime(clk_id: c_int, tp: *timespec) c_int; | 13 | pub extern "c" fn clock_gettime(clk_id: c_int, tp: *timespec) c_int; |
| 14 | pub extern "c" fn fstat(fd: fd_t, buf: *Stat) c_int; | ||
| 15 | pub extern "c" fn getrusage(who: c_int, usage: *rusage) c_int; | 14 | pub extern "c" fn getrusage(who: c_int, usage: *rusage) c_int; |
| 16 | pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; | 15 | pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; |
| 17 | pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; | 16 | pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; |
| ... | @@ -200,11 +199,6 @@ pub const STRUNCATE = 80; | ... | @@ -200,11 +199,6 @@ pub const STRUNCATE = 80; |
| 200 | 199 | ||
| 201 | pub const F_OK = 0; | 200 | pub const F_OK = 0; |
| 202 | 201 | ||
| 203 | /// Remove directory instead of unlinking file | ||
| 204 | pub const AT = struct { | ||
| 205 | pub const REMOVEDIR = 0x200; | ||
| 206 | }; | ||
| 207 | |||
| 208 | pub const in_port_t = u16; | 202 | pub const in_port_t = u16; |
| 209 | pub const sa_family_t = ws2_32.ADDRESS_FAMILY; | 203 | pub const sa_family_t = ws2_32.ADDRESS_FAMILY; |
| 210 | pub const socklen_t = ws2_32.socklen_t; | 204 | pub const socklen_t = ws2_32.socklen_t; |
| ... | @@ -229,31 +223,4 @@ pub const SOL = ws2_32.SOL; | ... | @@ -229,31 +223,4 @@ pub const SOL = ws2_32.SOL; |
| 229 | pub const SO = ws2_32.SO; | 223 | pub const SO = ws2_32.SO; |
| 230 | pub const PVD_CONFIG = ws2_32.PVD_CONFIG; | 224 | pub const PVD_CONFIG = ws2_32.PVD_CONFIG; |
| 231 | 225 | ||
| 232 | pub const O = struct { | ||
| 233 | pub const RDONLY = 0o0; | ||
| 234 | pub const WRONLY = 0o1; | ||
| 235 | pub const RDWR = 0o2; | ||
| 236 | |||
| 237 | pub const CREAT = 0o100; | ||
| 238 | pub const EXCL = 0o200; | ||
| 239 | pub const NOCTTY = 0o400; | ||
| 240 | pub const TRUNC = 0o1000; | ||
| 241 | pub const APPEND = 0o2000; | ||
| 242 | pub const NONBLOCK = 0o4000; | ||
| 243 | pub const DSYNC = 0o10000; | ||
| 244 | pub const SYNC = 0o4010000; | ||
| 245 | pub const RSYNC = 0o4010000; | ||
| 246 | pub const DIRECTORY = 0o200000; | ||
| 247 | pub const NOFOLLOW = 0o400000; | ||
| 248 | pub const CLOEXEC = 0o2000000; | ||
| 249 | |||
| 250 | pub const ASYNC = 0o20000; | ||
| 251 | pub const DIRECT = 0o40000; | ||
| 252 | pub const LARGEFILE = 0; | ||
| 253 | pub const NOATIME = 0o1000000; | ||
| 254 | pub const PATH = 0o10000000; | ||
| 255 | pub const TMPFILE = 0o20200000; | ||
| 256 | pub const NDELAY = NONBLOCK; | ||
| 257 | }; | ||
| 258 | |||
| 259 | pub const IFNAMESIZE = 30; | 226 | pub const IFNAMESIZE = 30; |
lib/std/child_process.zig+3-3| ... | @@ -495,7 +495,7 @@ pub const ChildProcess = struct { | ... | @@ -495,7 +495,7 @@ pub const ChildProcess = struct { |
| 495 | } | 495 | } |
| 496 | 496 | ||
| 497 | fn spawnPosix(self: *ChildProcess) SpawnError!void { | 497 | fn spawnPosix(self: *ChildProcess) SpawnError!void { |
| 498 | const pipe_flags = 0; | 498 | const pipe_flags: os.O = .{}; |
| 499 | const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try os.pipe2(pipe_flags) else undefined; | 499 | const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try os.pipe2(pipe_flags) else undefined; |
| 500 | errdefer if (self.stdin_behavior == StdIo.Pipe) { | 500 | errdefer if (self.stdin_behavior == StdIo.Pipe) { |
| 501 | destroyPipe(stdin_pipe); | 501 | destroyPipe(stdin_pipe); |
| ... | @@ -513,7 +513,7 @@ pub const ChildProcess = struct { | ... | @@ -513,7 +513,7 @@ pub const ChildProcess = struct { |
| 513 | 513 | ||
| 514 | const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore); | 514 | const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore); |
| 515 | const dev_null_fd = if (any_ignore) | 515 | const dev_null_fd = if (any_ignore) |
| 516 | os.openZ("/dev/null", os.O.RDWR, 0) catch |err| switch (err) { | 516 | os.openZ("/dev/null", .{ .ACCMODE = .RDWR }, 0) catch |err| switch (err) { |
| 517 | error.PathAlreadyExists => unreachable, | 517 | error.PathAlreadyExists => unreachable, |
| 518 | error.NoSpaceLeft => unreachable, | 518 | error.NoSpaceLeft => unreachable, |
| 519 | error.FileTooBig => unreachable, | 519 | error.FileTooBig => unreachable, |
| ... | @@ -572,7 +572,7 @@ pub const ChildProcess = struct { | ... | @@ -572,7 +572,7 @@ pub const ChildProcess = struct { |
| 572 | // end with eventfd | 572 | // end with eventfd |
| 573 | break :blk [2]os.fd_t{ fd, fd }; | 573 | break :blk [2]os.fd_t{ fd, fd }; |
| 574 | } else { | 574 | } else { |
| 575 | break :blk try os.pipe2(os.O.CLOEXEC); | 575 | break :blk try os.pipe2(.{ .CLOEXEC = true }); |
| 576 | } | 576 | } |
| 577 | }; | 577 | }; |
| 578 | errdefer destroyPipe(err_pipe); | 578 | errdefer destroyPipe(err_pipe); |
lib/std/compress/deflate/deflate_fast.zig+8| ... | @@ -354,6 +354,10 @@ pub const DeflateFast = struct { | ... | @@ -354,6 +354,10 @@ pub const DeflateFast = struct { |
| 354 | }; | 354 | }; |
| 355 | 355 | ||
| 356 | test "best speed match 1/3" { | 356 | test "best speed match 1/3" { |
| 357 | if (@import("builtin").os.tag == .wasi) { | ||
| 358 | // https://github.com/ziglang/zig/issues/18885 | ||
| 359 | return error.SkipZigTest; | ||
| 360 | } | ||
| 357 | const expectEqual = std.testing.expectEqual; | 361 | const expectEqual = std.testing.expectEqual; |
| 358 | 362 | ||
| 359 | { | 363 | { |
| ... | @@ -450,6 +454,10 @@ test "best speed match 1/3" { | ... | @@ -450,6 +454,10 @@ test "best speed match 1/3" { |
| 450 | } | 454 | } |
| 451 | 455 | ||
| 452 | test "best speed match 2/3" { | 456 | test "best speed match 2/3" { |
| 457 | if (@import("builtin").os.tag == .wasi) { | ||
| 458 | // https://github.com/ziglang/zig/issues/18885 | ||
| 459 | return error.SkipZigTest; | ||
| 460 | } | ||
| 453 | const expectEqual = std.testing.expectEqual; | 461 | const expectEqual = std.testing.expectEqual; |
| 454 | 462 | ||
| 455 | { | 463 | { |
lib/std/dynamic_library.zig+1-1| ... | @@ -115,7 +115,7 @@ pub const ElfDynLib = struct { | ... | @@ -115,7 +115,7 @@ pub const ElfDynLib = struct { |
| 115 | 115 | ||
| 116 | /// Trusts the file. Malicious file will be able to execute arbitrary code. | 116 | /// Trusts the file. Malicious file will be able to execute arbitrary code. |
| 117 | pub fn open(path: []const u8) !ElfDynLib { | 117 | pub fn open(path: []const u8) !ElfDynLib { |
| 118 | const fd = try os.open(path, 0, os.O.RDONLY | os.O.CLOEXEC); | 118 | const fd = try os.open(path, .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); |
| 119 | defer os.close(fd); | 119 | defer os.close(fd); |
| 120 | 120 | ||
| 121 | const stat = try os.fstat(fd); | 121 | const stat = try os.fstat(fd); |
lib/std/fs/Dir.zig+239-224| ... | @@ -62,16 +62,16 @@ pub const Iterator = switch (builtin.os.tag) { | ... | @@ -62,16 +62,16 @@ pub const Iterator = switch (builtin.os.tag) { |
| 62 | self.end_index = @as(usize, @intCast(rc)); | 62 | self.end_index = @as(usize, @intCast(rc)); |
| 63 | } | 63 | } |
| 64 | const darwin_entry = @as(*align(1) posix.system.dirent, @ptrCast(&self.buf[self.index])); | 64 | const darwin_entry = @as(*align(1) posix.system.dirent, @ptrCast(&self.buf[self.index])); |
| 65 | const next_index = self.index + darwin_entry.reclen(); | 65 | const next_index = self.index + darwin_entry.reclen; |
| 66 | self.index = next_index; | 66 | self.index = next_index; |
| 67 | 67 | ||
| 68 | const name = @as([*]u8, @ptrCast(&darwin_entry.d_name))[0..darwin_entry.d_namlen]; | 68 | const name = @as([*]u8, @ptrCast(&darwin_entry.name))[0..darwin_entry.namlen]; |
| 69 | 69 | ||
| 70 | if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..") or (darwin_entry.d_ino == 0)) { | 70 | if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..") or (darwin_entry.ino == 0)) { |
| 71 | continue :start_over; | 71 | continue :start_over; |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | const entry_kind: Entry.Kind = switch (darwin_entry.d_type) { | 74 | const entry_kind: Entry.Kind = switch (darwin_entry.type) { |
| 75 | posix.DT.BLK => .block_device, | 75 | posix.DT.BLK => .block_device, |
| 76 | posix.DT.CHR => .character_device, | 76 | posix.DT.CHR => .character_device, |
| 77 | posix.DT.DIR => .directory, | 77 | posix.DT.DIR => .directory, |
| ... | @@ -110,14 +110,14 @@ pub const Iterator = switch (builtin.os.tag) { | ... | @@ -110,14 +110,14 @@ pub const Iterator = switch (builtin.os.tag) { |
| 110 | self.end_index = @as(usize, @intCast(rc)); | 110 | self.end_index = @as(usize, @intCast(rc)); |
| 111 | } | 111 | } |
| 112 | const entry = @as(*align(1) posix.system.dirent, @ptrCast(&self.buf[self.index])); | 112 | const entry = @as(*align(1) posix.system.dirent, @ptrCast(&self.buf[self.index])); |
| 113 | const next_index = self.index + entry.reclen(); | 113 | const next_index = self.index + entry.reclen; |
| 114 | self.index = next_index; | 114 | self.index = next_index; |
| 115 | 115 | ||
| 116 | const name = mem.sliceTo(@as([*:0]u8, @ptrCast(&entry.d_name)), 0); | 116 | const name = mem.sliceTo(@as([*:0]u8, @ptrCast(&entry.name)), 0); |
| 117 | if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) | 117 | if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) |
| 118 | continue :start_over; | 118 | continue :start_over; |
| 119 | 119 | ||
| 120 | // Solaris dirent doesn't expose d_type, so we have to call stat to get it. | 120 | // Solaris dirent doesn't expose type, so we have to call stat to get it. |
| 121 | const stat_info = posix.fstatat( | 121 | const stat_info = posix.fstatat( |
| 122 | self.dir.fd, | 122 | self.dir.fd, |
| 123 | name, | 123 | name, |
| ... | @@ -174,23 +174,23 @@ pub const Iterator = switch (builtin.os.tag) { | ... | @@ -174,23 +174,23 @@ pub const Iterator = switch (builtin.os.tag) { |
| 174 | self.end_index = @as(usize, @intCast(rc)); | 174 | self.end_index = @as(usize, @intCast(rc)); |
| 175 | } | 175 | } |
| 176 | const bsd_entry = @as(*align(1) posix.system.dirent, @ptrCast(&self.buf[self.index])); | 176 | const bsd_entry = @as(*align(1) posix.system.dirent, @ptrCast(&self.buf[self.index])); |
| 177 | const next_index = self.index + bsd_entry.reclen(); | 177 | const next_index = self.index + bsd_entry.reclen; |
| 178 | self.index = next_index; | 178 | self.index = next_index; |
| 179 | 179 | ||
| 180 | const name = @as([*]u8, @ptrCast(&bsd_entry.d_name))[0..bsd_entry.d_namlen]; | 180 | const name = @as([*]u8, @ptrCast(&bsd_entry.name))[0..bsd_entry.namlen]; |
| 181 | 181 | ||
| 182 | const skip_zero_fileno = switch (builtin.os.tag) { | 182 | const skip_zero_fileno = switch (builtin.os.tag) { |
| 183 | // d_fileno=0 is used to mark invalid entries or deleted files. | 183 | // fileno=0 is used to mark invalid entries or deleted files. |
| 184 | .openbsd, .netbsd => true, | 184 | .openbsd, .netbsd => true, |
| 185 | else => false, | 185 | else => false, |
| 186 | }; | 186 | }; |
| 187 | if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..") or | 187 | if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..") or |
| 188 | (skip_zero_fileno and bsd_entry.d_fileno == 0)) | 188 | (skip_zero_fileno and bsd_entry.fileno == 0)) |
| 189 | { | 189 | { |
| 190 | continue :start_over; | 190 | continue :start_over; |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | const entry_kind: Entry.Kind = switch (bsd_entry.d_type) { | 193 | const entry_kind: Entry.Kind = switch (bsd_entry.type) { |
| 194 | posix.DT.BLK => .block_device, | 194 | posix.DT.BLK => .block_device, |
| 195 | posix.DT.CHR => .character_device, | 195 | posix.DT.CHR => .character_device, |
| 196 | posix.DT.DIR => .directory, | 196 | posix.DT.DIR => .directory, |
| ... | @@ -256,18 +256,18 @@ pub const Iterator = switch (builtin.os.tag) { | ... | @@ -256,18 +256,18 @@ pub const Iterator = switch (builtin.os.tag) { |
| 256 | self.end_index = @as(usize, @intCast(rc)); | 256 | self.end_index = @as(usize, @intCast(rc)); |
| 257 | } | 257 | } |
| 258 | const haiku_entry = @as(*align(1) posix.system.dirent, @ptrCast(&self.buf[self.index])); | 258 | const haiku_entry = @as(*align(1) posix.system.dirent, @ptrCast(&self.buf[self.index])); |
| 259 | const next_index = self.index + haiku_entry.reclen(); | 259 | const next_index = self.index + haiku_entry.reclen; |
| 260 | self.index = next_index; | 260 | self.index = next_index; |
| 261 | const name = mem.sliceTo(@as([*:0]u8, @ptrCast(&haiku_entry.d_name)), 0); | 261 | const name = mem.sliceTo(@as([*:0]u8, @ptrCast(&haiku_entry.name)), 0); |
| 262 | 262 | ||
| 263 | if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..") or (haiku_entry.d_ino == 0)) { | 263 | if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..") or (haiku_entry.ino == 0)) { |
| 264 | continue :start_over; | 264 | continue :start_over; |
| 265 | } | 265 | } |
| 266 | 266 | ||
| 267 | var stat_info: posix.Stat = undefined; | 267 | var stat_info: posix.Stat = undefined; |
| 268 | const rc = posix.system._kern_read_stat( | 268 | const rc = posix.system._kern_read_stat( |
| 269 | self.dir.fd, | 269 | self.dir.fd, |
| 270 | &haiku_entry.d_name, | 270 | &haiku_entry.name, |
| 271 | false, | 271 | false, |
| 272 | &stat_info, | 272 | &stat_info, |
| 273 | 0, | 273 | 0, |
| ... | @@ -359,17 +359,17 @@ pub const Iterator = switch (builtin.os.tag) { | ... | @@ -359,17 +359,17 @@ pub const Iterator = switch (builtin.os.tag) { |
| 359 | self.end_index = rc; | 359 | self.end_index = rc; |
| 360 | } | 360 | } |
| 361 | const linux_entry = @as(*align(1) linux.dirent64, @ptrCast(&self.buf[self.index])); | 361 | const linux_entry = @as(*align(1) linux.dirent64, @ptrCast(&self.buf[self.index])); |
| 362 | const next_index = self.index + linux_entry.reclen(); | 362 | const next_index = self.index + linux_entry.reclen; |
| 363 | self.index = next_index; | 363 | self.index = next_index; |
| 364 | 364 | ||
| 365 | const name = mem.sliceTo(@as([*:0]u8, @ptrCast(&linux_entry.d_name)), 0); | 365 | const name = mem.sliceTo(@as([*:0]u8, @ptrCast(&linux_entry.name)), 0); |
| 366 | 366 | ||
| 367 | // skip . and .. entries | 367 | // skip . and .. entries |
| 368 | if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) { | 368 | if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) { |
| 369 | continue :start_over; | 369 | continue :start_over; |
| 370 | } | 370 | } |
| 371 | 371 | ||
| 372 | const entry_kind: Entry.Kind = switch (linux_entry.d_type) { | 372 | const entry_kind: Entry.Kind = switch (linux_entry.type) { |
| 373 | linux.DT.BLK => .block_device, | 373 | linux.DT.BLK => .block_device, |
| 374 | linux.DT.CHR => .character_device, | 374 | linux.DT.CHR => .character_device, |
| 375 | linux.DT.DIR => .directory, | 375 | linux.DT.DIR => .directory, |
| ... | @@ -525,23 +525,23 @@ pub const Iterator = switch (builtin.os.tag) { | ... | @@ -525,23 +525,23 @@ pub const Iterator = switch (builtin.os.tag) { |
| 525 | const entry = @as(*align(1) w.dirent_t, @ptrCast(&self.buf[self.index])); | 525 | const entry = @as(*align(1) w.dirent_t, @ptrCast(&self.buf[self.index])); |
| 526 | const entry_size = @sizeOf(w.dirent_t); | 526 | const entry_size = @sizeOf(w.dirent_t); |
| 527 | const name_index = self.index + entry_size; | 527 | const name_index = self.index + entry_size; |
| 528 | if (name_index + entry.d_namlen > self.end_index) { | 528 | if (name_index + entry.namlen > self.end_index) { |
| 529 | // This case, the name is truncated, so we need to call readdir to store the entire name. | 529 | // This case, the name is truncated, so we need to call readdir to store the entire name. |
| 530 | self.end_index = self.index; // Force fd_readdir in the next loop. | 530 | self.end_index = self.index; // Force fd_readdir in the next loop. |
| 531 | continue :start_over; | 531 | continue :start_over; |
| 532 | } | 532 | } |
| 533 | const name = self.buf[name_index .. name_index + entry.d_namlen]; | 533 | const name = self.buf[name_index .. name_index + entry.namlen]; |
| 534 | 534 | ||
| 535 | const next_index = name_index + entry.d_namlen; | 535 | const next_index = name_index + entry.namlen; |
| 536 | self.index = next_index; | 536 | self.index = next_index; |
| 537 | self.cookie = entry.d_next; | 537 | self.cookie = entry.next; |
| 538 | 538 | ||
| 539 | // skip . and .. entries | 539 | // skip . and .. entries |
| 540 | if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) { | 540 | if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) { |
| 541 | continue :start_over; | 541 | continue :start_over; |
| 542 | } | 542 | } |
| 543 | 543 | ||
| 544 | const entry_kind: Entry.Kind = switch (entry.d_type) { | 544 | const entry_kind: Entry.Kind = switch (entry.type) { |
| 545 | .BLOCK_DEVICE => .block_device, | 545 | .BLOCK_DEVICE => .block_device, |
| 546 | .CHARACTER_DEVICE => .character_device, | 546 | .CHARACTER_DEVICE => .character_device, |
| 547 | .DIRECTORY => .directory, | 547 | .DIRECTORY => .directory, |
| ... | @@ -764,81 +764,79 @@ pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.Ope | ... | @@ -764,81 +764,79 @@ pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.Ope |
| 764 | const path_w = try std.os.windows.sliceToPrefixedFileW(self.fd, sub_path); | 764 | const path_w = try std.os.windows.sliceToPrefixedFileW(self.fd, sub_path); |
| 765 | return self.openFileW(path_w.span(), flags); | 765 | return self.openFileW(path_w.span(), flags); |
| 766 | } | 766 | } |
| 767 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 767 | if (builtin.os.tag == .wasi) { |
| 768 | return self.openFileWasi(sub_path, flags); | 768 | var base: std.os.wasi.rights_t = .{}; |
| 769 | if (flags.isRead()) { | ||
| 770 | base.FD_READ = true; | ||
| 771 | base.FD_TELL = true; | ||
| 772 | base.FD_SEEK = true; | ||
| 773 | base.FD_FILESTAT_GET = true; | ||
| 774 | } | ||
| 775 | if (flags.isWrite()) { | ||
| 776 | base.FD_WRITE = true; | ||
| 777 | base.FD_TELL = true; | ||
| 778 | base.FD_SEEK = true; | ||
| 779 | base.FD_DATASYNC = true; | ||
| 780 | base.FD_FDSTAT_SET_FLAGS = true; | ||
| 781 | base.FD_SYNC = true; | ||
| 782 | base.FD_ALLOCATE = true; | ||
| 783 | base.FD_ADVISE = true; | ||
| 784 | base.FD_FILESTAT_SET_TIMES = true; | ||
| 785 | base.FD_FILESTAT_SET_SIZE = true; | ||
| 786 | } | ||
| 787 | const fd = try posix.openatWasi(self.fd, sub_path, .{}, .{}, .{}, base, .{}); | ||
| 788 | return .{ .handle = fd }; | ||
| 769 | } | 789 | } |
| 770 | const path_c = try posix.toPosixPath(sub_path); | 790 | const path_c = try posix.toPosixPath(sub_path); |
| 771 | return self.openFileZ(&path_c, flags); | 791 | return self.openFileZ(&path_c, flags); |
| 772 | } | 792 | } |
| 773 | 793 | ||
| 774 | /// Same as `openFile` but WASI only. | ||
| 775 | pub fn openFileWasi(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File { | ||
| 776 | const w = std.os.wasi; | ||
| 777 | var fdflags: w.fdflags_t = 0x0; | ||
| 778 | var base: w.rights_t = 0x0; | ||
| 779 | if (flags.isRead()) { | ||
| 780 | base |= w.RIGHT.FD_READ | w.RIGHT.FD_TELL | w.RIGHT.FD_SEEK | w.RIGHT.FD_FILESTAT_GET; | ||
| 781 | } | ||
| 782 | if (flags.isWrite()) { | ||
| 783 | fdflags |= w.FDFLAG.APPEND; | ||
| 784 | base |= w.RIGHT.FD_WRITE | | ||
| 785 | w.RIGHT.FD_TELL | | ||
| 786 | w.RIGHT.FD_SEEK | | ||
| 787 | w.RIGHT.FD_DATASYNC | | ||
| 788 | w.RIGHT.FD_FDSTAT_SET_FLAGS | | ||
| 789 | w.RIGHT.FD_SYNC | | ||
| 790 | w.RIGHT.FD_ALLOCATE | | ||
| 791 | w.RIGHT.FD_ADVISE | | ||
| 792 | w.RIGHT.FD_FILESTAT_SET_TIMES | | ||
| 793 | w.RIGHT.FD_FILESTAT_SET_SIZE; | ||
| 794 | } | ||
| 795 | const fd = try posix.openatWasi(self.fd, sub_path, 0x0, 0x0, fdflags, base, 0x0); | ||
| 796 | return File{ .handle = fd }; | ||
| 797 | } | ||
| 798 | |||
| 799 | /// Same as `openFile` but the path parameter is null-terminated. | 794 | /// Same as `openFile` but the path parameter is null-terminated. |
| 800 | pub fn openFileZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File.OpenError!File { | 795 | pub fn openFileZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File.OpenError!File { |
| 801 | if (builtin.os.tag == .windows) { | 796 | switch (builtin.os.tag) { |
| 802 | const path_w = try std.os.windows.cStrToPrefixedFileW(self.fd, sub_path); | 797 | .windows => { |
| 803 | return self.openFileW(path_w.span(), flags); | 798 | const path_w = try std.os.windows.cStrToPrefixedFileW(self.fd, sub_path); |
| 799 | return self.openFileW(path_w.span(), flags); | ||
| 800 | }, | ||
| 801 | .wasi => { | ||
| 802 | return openFile(self, mem.sliceTo(sub_path, 0), flags); | ||
| 803 | }, | ||
| 804 | else => {}, | ||
| 804 | } | 805 | } |
| 805 | 806 | ||
| 806 | var os_flags: u32 = 0; | 807 | var os_flags: posix.O = .{ |
| 807 | if (@hasDecl(posix.O, "CLOEXEC")) os_flags = posix.O.CLOEXEC; | 808 | .ACCMODE = switch (flags.mode) { |
| 809 | .read_only => .RDONLY, | ||
| 810 | .write_only => .WRONLY, | ||
| 811 | .read_write => .RDWR, | ||
| 812 | }, | ||
| 813 | }; | ||
| 814 | if (@hasField(posix.O, "CLOEXEC")) os_flags.CLOEXEC = true; | ||
| 815 | if (@hasField(posix.O, "LARGEFILE")) os_flags.LARGEFILE = true; | ||
| 816 | if (@hasField(posix.O, "NOCTTY")) os_flags.NOCTTY = !flags.allow_ctty; | ||
| 808 | 817 | ||
| 809 | // Use the O locking flags if the os supports them to acquire the lock | 818 | // Use the O locking flags if the os supports them to acquire the lock |
| 810 | // atomically. | 819 | // atomically. |
| 811 | const has_flock_open_flags = @hasDecl(posix.O, "EXLOCK"); | 820 | const has_flock_open_flags = @hasField(posix.O, "EXLOCK"); |
| 812 | if (has_flock_open_flags) { | 821 | if (has_flock_open_flags) { |
| 813 | // Note that the O.NONBLOCK flag is removed after the openat() call | 822 | // Note that the NONBLOCK flag is removed after the openat() call |
| 814 | // is successful. | 823 | // is successful. |
| 815 | const nonblocking_lock_flag: u32 = if (flags.lock_nonblocking) | 824 | switch (flags.lock) { |
| 816 | posix.O.NONBLOCK | 825 | .none => {}, |
| 817 | else | 826 | .shared => { |
| 818 | 0; | 827 | os_flags.SHLOCK = true; |
| 819 | os_flags |= switch (flags.lock) { | 828 | os_flags.NONBLOCK = flags.lock_nonblocking; |
| 820 | .none => @as(u32, 0), | 829 | }, |
| 821 | .shared => posix.O.SHLOCK | nonblocking_lock_flag, | 830 | .exclusive => { |
| 822 | .exclusive => posix.O.EXLOCK | nonblocking_lock_flag, | 831 | os_flags.EXLOCK = true; |
| 823 | }; | 832 | os_flags.NONBLOCK = flags.lock_nonblocking; |
| 824 | } | 833 | }, |
| 825 | if (@hasDecl(posix.O, "LARGEFILE")) { | 834 | } |
| 826 | os_flags |= posix.O.LARGEFILE; | ||
| 827 | } | ||
| 828 | if (@hasDecl(posix.O, "NOCTTY") and !flags.allow_ctty) { | ||
| 829 | os_flags |= posix.O.NOCTTY; | ||
| 830 | } | 835 | } |
| 831 | os_flags |= switch (flags.mode) { | ||
| 832 | .read_only => @as(u32, posix.O.RDONLY), | ||
| 833 | .write_only => @as(u32, posix.O.WRONLY), | ||
| 834 | .read_write => @as(u32, posix.O.RDWR), | ||
| 835 | }; | ||
| 836 | const fd = try posix.openatZ(self.fd, sub_path, os_flags, 0); | 836 | const fd = try posix.openatZ(self.fd, sub_path, os_flags, 0); |
| 837 | errdefer posix.close(fd); | 837 | errdefer posix.close(fd); |
| 838 | 838 | ||
| 839 | // WASI doesn't have posix.flock so we intetinally check OS prior to the inner if block | 839 | if (@hasDecl(posix.system, "LOCK")) { |
| 840 | // since it is not compiltime-known and we need to avoid undefined symbol in Wasm. | ||
| 841 | if (@hasDecl(posix.system, "LOCK") and builtin.target.os.tag != .wasi) { | ||
| 842 | if (!has_flock_open_flags and flags.lock != .none) { | 840 | if (!has_flock_open_flags and flags.lock != .none) { |
| 843 | // TODO: integrate async I/O | 841 | // TODO: integrate async I/O |
| 844 | const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0; | 842 | const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0; |
| ... | @@ -859,7 +857,7 @@ pub fn openFileZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File | ... | @@ -859,7 +857,7 @@ pub fn openFileZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File |
| 859 | error.LockedRegionLimitExceeded => unreachable, | 857 | error.LockedRegionLimitExceeded => unreachable, |
| 860 | else => |e| return e, | 858 | else => |e| return e, |
| 861 | }; | 859 | }; |
| 862 | fl_flags &= ~@as(usize, posix.O.NONBLOCK); | 860 | fl_flags &= ~@as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK")); |
| 863 | _ = posix.fcntl(fd, posix.F.SETFL, fl_flags) catch |err| switch (err) { | 861 | _ = posix.fcntl(fd, posix.F.SETFL, fl_flags) catch |err| switch (err) { |
| 864 | error.FileBusy => unreachable, | 862 | error.FileBusy => unreachable, |
| 865 | error.Locked => unreachable, | 863 | error.Locked => unreachable, |
| ... | @@ -870,7 +868,7 @@ pub fn openFileZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File | ... | @@ -870,7 +868,7 @@ pub fn openFileZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File |
| 870 | }; | 868 | }; |
| 871 | } | 869 | } |
| 872 | 870 | ||
| 873 | return File{ .handle = fd }; | 871 | return .{ .handle = fd }; |
| 874 | } | 872 | } |
| 875 | 873 | ||
| 876 | /// Same as `openFile` but Windows-only and the path parameter is | 874 | /// Same as `openFile` but Windows-only and the path parameter is |
| ... | @@ -918,83 +916,81 @@ pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File | ... | @@ -918,83 +916,81 @@ pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File |
| 918 | const path_w = try std.os.windows.sliceToPrefixedFileW(self.fd, sub_path); | 916 | const path_w = try std.os.windows.sliceToPrefixedFileW(self.fd, sub_path); |
| 919 | return self.createFileW(path_w.span(), flags); | 917 | return self.createFileW(path_w.span(), flags); |
| 920 | } | 918 | } |
| 921 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 919 | if (builtin.os.tag == .wasi) { |
| 922 | return self.createFileWasi(sub_path, flags); | 920 | return .{ |
| 921 | .handle = try posix.openatWasi(self.fd, sub_path, .{}, .{ | ||
| 922 | .CREAT = true, | ||
| 923 | .TRUNC = flags.truncate, | ||
| 924 | .EXCL = flags.exclusive, | ||
| 925 | }, .{}, .{ | ||
| 926 | .FD_READ = flags.read, | ||
| 927 | .FD_WRITE = true, | ||
| 928 | .FD_DATASYNC = true, | ||
| 929 | .FD_SEEK = true, | ||
| 930 | .FD_TELL = true, | ||
| 931 | .FD_FDSTAT_SET_FLAGS = true, | ||
| 932 | .FD_SYNC = true, | ||
| 933 | .FD_ALLOCATE = true, | ||
| 934 | .FD_ADVISE = true, | ||
| 935 | .FD_FILESTAT_SET_TIMES = true, | ||
| 936 | .FD_FILESTAT_SET_SIZE = true, | ||
| 937 | .FD_FILESTAT_GET = true, | ||
| 938 | }, .{}), | ||
| 939 | }; | ||
| 923 | } | 940 | } |
| 924 | const path_c = try posix.toPosixPath(sub_path); | 941 | const path_c = try posix.toPosixPath(sub_path); |
| 925 | return self.createFileZ(&path_c, flags); | 942 | return self.createFileZ(&path_c, flags); |
| 926 | } | 943 | } |
| 927 | 944 | ||
| 928 | /// Same as `createFile` but WASI only. | ||
| 929 | pub fn createFileWasi(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File { | ||
| 930 | const w = std.os.wasi; | ||
| 931 | var oflags = w.O.CREAT; | ||
| 932 | var base: w.rights_t = w.RIGHT.FD_WRITE | | ||
| 933 | w.RIGHT.FD_DATASYNC | | ||
| 934 | w.RIGHT.FD_SEEK | | ||
| 935 | w.RIGHT.FD_TELL | | ||
| 936 | w.RIGHT.FD_FDSTAT_SET_FLAGS | | ||
| 937 | w.RIGHT.FD_SYNC | | ||
| 938 | w.RIGHT.FD_ALLOCATE | | ||
| 939 | w.RIGHT.FD_ADVISE | | ||
| 940 | w.RIGHT.FD_FILESTAT_SET_TIMES | | ||
| 941 | w.RIGHT.FD_FILESTAT_SET_SIZE | | ||
| 942 | w.RIGHT.FD_FILESTAT_GET; | ||
| 943 | if (flags.read) { | ||
| 944 | base |= w.RIGHT.FD_READ; | ||
| 945 | } | ||
| 946 | if (flags.truncate) { | ||
| 947 | oflags |= w.O.TRUNC; | ||
| 948 | } | ||
| 949 | if (flags.exclusive) { | ||
| 950 | oflags |= w.O.EXCL; | ||
| 951 | } | ||
| 952 | const fd = try posix.openatWasi(self.fd, sub_path, 0x0, oflags, 0x0, base, 0x0); | ||
| 953 | return File{ .handle = fd }; | ||
| 954 | } | ||
| 955 | |||
| 956 | /// Same as `createFile` but the path parameter is null-terminated. | 945 | /// Same as `createFile` but the path parameter is null-terminated. |
| 957 | pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags) File.OpenError!File { | 946 | pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags) File.OpenError!File { |
| 958 | if (builtin.os.tag == .windows) { | 947 | switch (builtin.os.tag) { |
| 959 | const path_w = try std.os.windows.cStrToPrefixedFileW(self.fd, sub_path_c); | 948 | .windows => { |
| 960 | return self.createFileW(path_w.span(), flags); | 949 | const path_w = try std.os.windows.cStrToPrefixedFileW(self.fd, sub_path_c); |
| 950 | return self.createFileW(path_w.span(), flags); | ||
| 951 | }, | ||
| 952 | .wasi => { | ||
| 953 | return createFile(self, mem.sliceTo(sub_path_c, 0), flags); | ||
| 954 | }, | ||
| 955 | else => {}, | ||
| 961 | } | 956 | } |
| 962 | 957 | ||
| 958 | var os_flags: std.os.O = .{ | ||
| 959 | .ACCMODE = if (flags.read) .RDWR else .WRONLY, | ||
| 960 | .CREAT = true, | ||
| 961 | .TRUNC = flags.truncate, | ||
| 962 | .EXCL = flags.exclusive, | ||
| 963 | }; | ||
| 964 | if (@hasField(posix.O, "LARGEFILE")) os_flags.LARGEFILE = true; | ||
| 965 | if (@hasField(posix.O, "CLOEXEC")) os_flags.CLOEXEC = true; | ||
| 966 | |||
| 963 | // Use the O locking flags if the os supports them to acquire the lock | 967 | // Use the O locking flags if the os supports them to acquire the lock |
| 964 | // atomically. | 968 | // atomically. Note that the NONBLOCK flag is removed after the openat() |
| 965 | const has_flock_open_flags = @hasDecl(posix.O, "EXLOCK"); | 969 | // call is successful. |
| 966 | // Note that the O.NONBLOCK flag is removed after the openat() call | 970 | const has_flock_open_flags = @hasField(posix.O, "EXLOCK"); |
| 967 | // is successful. | 971 | if (has_flock_open_flags) switch (flags.lock) { |
| 968 | const nonblocking_lock_flag: u32 = if (has_flock_open_flags and flags.lock_nonblocking) | 972 | .none => {}, |
| 969 | posix.O.NONBLOCK | 973 | .shared => { |
| 970 | else | 974 | os_flags.SHLOCK = true; |
| 971 | 0; | 975 | os_flags.NONBLOCK = flags.lock_nonblocking; |
| 972 | const lock_flag: u32 = if (has_flock_open_flags) switch (flags.lock) { | 976 | }, |
| 973 | .none => @as(u32, 0), | 977 | .exclusive => { |
| 974 | .shared => posix.O.SHLOCK | nonblocking_lock_flag, | 978 | os_flags.EXLOCK = true; |
| 975 | .exclusive => posix.O.EXLOCK | nonblocking_lock_flag, | 979 | os_flags.NONBLOCK = flags.lock_nonblocking; |
| 976 | } else 0; | 980 | }, |
| 977 | 981 | }; | |
| 978 | const O_LARGEFILE = if (@hasDecl(posix.O, "LARGEFILE")) posix.O.LARGEFILE else 0; | 982 | |
| 979 | const os_flags = lock_flag | O_LARGEFILE | posix.O.CREAT | posix.O.CLOEXEC | | ||
| 980 | (if (flags.truncate) @as(u32, posix.O.TRUNC) else 0) | | ||
| 981 | (if (flags.read) @as(u32, posix.O.RDWR) else posix.O.WRONLY) | | ||
| 982 | (if (flags.exclusive) @as(u32, posix.O.EXCL) else 0); | ||
| 983 | const fd = try posix.openatZ(self.fd, sub_path_c, os_flags, flags.mode); | 983 | const fd = try posix.openatZ(self.fd, sub_path_c, os_flags, flags.mode); |
| 984 | errdefer posix.close(fd); | 984 | errdefer posix.close(fd); |
| 985 | 985 | ||
| 986 | // WASI doesn't have posix.flock so we intetinally check OS prior to the inner if block | 986 | if (!has_flock_open_flags and flags.lock != .none) { |
| 987 | // since it is not compiltime-known and we need to avoid undefined symbol in Wasm. | 987 | // TODO: integrate async I/O |
| 988 | if (builtin.target.os.tag != .wasi) { | 988 | const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0; |
| 989 | if (!has_flock_open_flags and flags.lock != .none) { | 989 | try posix.flock(fd, switch (flags.lock) { |
| 990 | // TODO: integrate async I/O | 990 | .none => unreachable, |
| 991 | const lock_nonblocking: i32 = if (flags.lock_nonblocking) posix.LOCK.NB else 0; | 991 | .shared => posix.LOCK.SH | lock_nonblocking, |
| 992 | try posix.flock(fd, switch (flags.lock) { | 992 | .exclusive => posix.LOCK.EX | lock_nonblocking, |
| 993 | .none => unreachable, | 993 | }); |
| 994 | .shared => posix.LOCK.SH | lock_nonblocking, | ||
| 995 | .exclusive => posix.LOCK.EX | lock_nonblocking, | ||
| 996 | }); | ||
| 997 | } | ||
| 998 | } | 994 | } |
| 999 | 995 | ||
| 1000 | if (has_flock_open_flags and flags.lock_nonblocking) { | 996 | if (has_flock_open_flags and flags.lock_nonblocking) { |
| ... | @@ -1006,7 +1002,7 @@ pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags | ... | @@ -1006,7 +1002,7 @@ pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags |
| 1006 | error.LockedRegionLimitExceeded => unreachable, | 1002 | error.LockedRegionLimitExceeded => unreachable, |
| 1007 | else => |e| return e, | 1003 | else => |e| return e, |
| 1008 | }; | 1004 | }; |
| 1009 | fl_flags &= ~@as(usize, posix.O.NONBLOCK); | 1005 | fl_flags &= ~@as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK")); |
| 1010 | _ = posix.fcntl(fd, posix.F.SETFL, fl_flags) catch |err| switch (err) { | 1006 | _ = posix.fcntl(fd, posix.F.SETFL, fl_flags) catch |err| switch (err) { |
| 1011 | error.FileBusy => unreachable, | 1007 | error.FileBusy => unreachable, |
| 1012 | error.Locked => unreachable, | 1008 | error.Locked => unreachable, |
| ... | @@ -1017,7 +1013,7 @@ pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags | ... | @@ -1017,7 +1013,7 @@ pub fn createFileZ(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags |
| 1017 | }; | 1013 | }; |
| 1018 | } | 1014 | } |
| 1019 | 1015 | ||
| 1020 | return File{ .handle = fd }; | 1016 | return .{ .handle = fd }; |
| 1021 | } | 1017 | } |
| 1022 | 1018 | ||
| 1023 | /// Same as `createFile` but Windows-only and the path parameter is | 1019 | /// Same as `createFile` but Windows-only and the path parameter is |
| ... | @@ -1210,10 +1206,18 @@ pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) ![]u8 { | ... | @@ -1210,10 +1206,18 @@ pub fn realpathZ(self: Dir, pathname: [*:0]const u8, out_buffer: []u8) ![]u8 { |
| 1210 | return self.realpathW(pathname_w.span(), out_buffer); | 1206 | return self.realpathW(pathname_w.span(), out_buffer); |
| 1211 | } | 1207 | } |
| 1212 | 1208 | ||
| 1213 | const flags = if (builtin.os.tag == .linux) | 1209 | const flags: posix.O = switch (builtin.os.tag) { |
| 1214 | posix.O.PATH | posix.O.NONBLOCK | posix.O.CLOEXEC | 1210 | .linux => .{ |
| 1215 | else | 1211 | .NONBLOCK = true, |
| 1216 | posix.O.NONBLOCK | posix.O.CLOEXEC; | 1212 | .CLOEXEC = true, |
| 1213 | .PATH = true, | ||
| 1214 | }, | ||
| 1215 | else => .{ | ||
| 1216 | .NONBLOCK = true, | ||
| 1217 | .CLOEXEC = true, | ||
| 1218 | }, | ||
| 1219 | }; | ||
| 1220 | |||
| 1217 | const fd = posix.openatZ(self.fd, pathname, flags, 0) catch |err| switch (err) { | 1221 | const fd = posix.openatZ(self.fd, pathname, flags, 0) catch |err| switch (err) { |
| 1218 | error.FileLocksNotSupported => unreachable, | 1222 | error.FileLocksNotSupported => unreachable, |
| 1219 | else => |e| return e, | 1223 | else => |e| return e, |
| ... | @@ -1334,76 +1338,85 @@ pub const OpenDirOptions = struct { | ... | @@ -1334,76 +1338,85 @@ pub const OpenDirOptions = struct { |
| 1334 | /// | 1338 | /// |
| 1335 | /// Asserts that the path parameter has no null bytes. | 1339 | /// Asserts that the path parameter has no null bytes. |
| 1336 | pub fn openDir(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!Dir { | 1340 | pub fn openDir(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!Dir { |
| 1337 | if (builtin.os.tag == .windows) { | 1341 | switch (builtin.os.tag) { |
| 1338 | const sub_path_w = try posix.windows.sliceToPrefixedFileW(self.fd, sub_path); | 1342 | .windows => { |
| 1339 | return self.openDirW(sub_path_w.span().ptr, args); | 1343 | const sub_path_w = try posix.windows.sliceToPrefixedFileW(self.fd, sub_path); |
| 1340 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 1344 | return self.openDirW(sub_path_w.span().ptr, args); |
| 1341 | return self.openDirWasi(sub_path, args); | 1345 | }, |
| 1342 | } else { | 1346 | .wasi => { |
| 1343 | const sub_path_c = try posix.toPosixPath(sub_path); | 1347 | var base: std.os.wasi.rights_t = .{ |
| 1344 | return self.openDirZ(&sub_path_c, args); | 1348 | .FD_FILESTAT_GET = true, |
| 1345 | } | 1349 | .FD_FDSTAT_SET_FLAGS = true, |
| 1346 | } | 1350 | .FD_FILESTAT_SET_TIMES = true, |
| 1351 | }; | ||
| 1352 | if (args.access_sub_paths) { | ||
| 1353 | base.FD_READDIR = true; | ||
| 1354 | base.PATH_CREATE_DIRECTORY = true; | ||
| 1355 | base.PATH_CREATE_FILE = true; | ||
| 1356 | base.PATH_LINK_SOURCE = true; | ||
| 1357 | base.PATH_LINK_TARGET = true; | ||
| 1358 | base.PATH_OPEN = true; | ||
| 1359 | base.PATH_READLINK = true; | ||
| 1360 | base.PATH_RENAME_SOURCE = true; | ||
| 1361 | base.PATH_RENAME_TARGET = true; | ||
| 1362 | base.PATH_FILESTAT_GET = true; | ||
| 1363 | base.PATH_FILESTAT_SET_SIZE = true; | ||
| 1364 | base.PATH_FILESTAT_SET_TIMES = true; | ||
| 1365 | base.PATH_SYMLINK = true; | ||
| 1366 | base.PATH_REMOVE_DIRECTORY = true; | ||
| 1367 | base.PATH_UNLINK_FILE = true; | ||
| 1368 | } | ||
| 1347 | 1369 | ||
| 1348 | /// Same as `openDir` except only WASI. | 1370 | const result = posix.openatWasi( |
| 1349 | pub fn openDirWasi(self: Dir, sub_path: []const u8, args: OpenDirOptions) OpenError!Dir { | 1371 | self.fd, |
| 1350 | const w = std.os.wasi; | 1372 | sub_path, |
| 1351 | var base: w.rights_t = w.RIGHT.FD_FILESTAT_GET | w.RIGHT.FD_FDSTAT_SET_FLAGS | w.RIGHT.FD_FILESTAT_SET_TIMES; | 1373 | .{ .SYMLINK_FOLLOW = !args.no_follow }, |
| 1352 | if (args.access_sub_paths) { | 1374 | .{ .DIRECTORY = true }, |
| 1353 | base |= w.RIGHT.FD_READDIR | | 1375 | .{}, |
| 1354 | w.RIGHT.PATH_CREATE_DIRECTORY | | 1376 | base, |
| 1355 | w.RIGHT.PATH_CREATE_FILE | | 1377 | base, |
| 1356 | w.RIGHT.PATH_LINK_SOURCE | | 1378 | ); |
| 1357 | w.RIGHT.PATH_LINK_TARGET | | 1379 | const fd = result catch |err| switch (err) { |
| 1358 | w.RIGHT.PATH_OPEN | | 1380 | error.FileTooBig => unreachable, // can't happen for directories |
| 1359 | w.RIGHT.PATH_READLINK | | 1381 | error.IsDir => unreachable, // we're setting DIRECTORY |
| 1360 | w.RIGHT.PATH_RENAME_SOURCE | | 1382 | error.NoSpaceLeft => unreachable, // not setting CREAT |
| 1361 | w.RIGHT.PATH_RENAME_TARGET | | 1383 | error.PathAlreadyExists => unreachable, // not setting CREAT |
| 1362 | w.RIGHT.PATH_FILESTAT_GET | | 1384 | error.FileLocksNotSupported => unreachable, // locking folders is not supported |
| 1363 | w.RIGHT.PATH_FILESTAT_SET_SIZE | | 1385 | error.WouldBlock => unreachable, // can't happen for directories |
| 1364 | w.RIGHT.PATH_FILESTAT_SET_TIMES | | 1386 | error.FileBusy => unreachable, // can't happen for directories |
| 1365 | w.RIGHT.PATH_SYMLINK | | 1387 | else => |e| return e, |
| 1366 | w.RIGHT.PATH_REMOVE_DIRECTORY | | 1388 | }; |
| 1367 | w.RIGHT.PATH_UNLINK_FILE; | 1389 | return .{ .fd = fd }; |
| 1390 | }, | ||
| 1391 | else => { | ||
| 1392 | const sub_path_c = try posix.toPosixPath(sub_path); | ||
| 1393 | return self.openDirZ(&sub_path_c, args); | ||
| 1394 | }, | ||
| 1368 | } | 1395 | } |
| 1369 | const symlink_flags: w.lookupflags_t = if (args.no_follow) 0x0 else w.LOOKUP_SYMLINK_FOLLOW; | ||
| 1370 | // TODO do we really need all the rights here? | ||
| 1371 | const inheriting: w.rights_t = w.RIGHT.ALL ^ w.RIGHT.SOCK_SHUTDOWN; | ||
| 1372 | |||
| 1373 | const result = posix.openatWasi( | ||
| 1374 | self.fd, | ||
| 1375 | sub_path, | ||
| 1376 | symlink_flags, | ||
| 1377 | w.O.DIRECTORY, | ||
| 1378 | 0x0, | ||
| 1379 | base, | ||
| 1380 | inheriting, | ||
| 1381 | ); | ||
| 1382 | const fd = result catch |err| switch (err) { | ||
| 1383 | error.FileTooBig => unreachable, // can't happen for directories | ||
| 1384 | error.IsDir => unreachable, // we're providing O.DIRECTORY | ||
| 1385 | error.NoSpaceLeft => unreachable, // not providing O.CREAT | ||
| 1386 | error.PathAlreadyExists => unreachable, // not providing O.CREAT | ||
| 1387 | error.FileLocksNotSupported => unreachable, // locking folders is not supported | ||
| 1388 | error.WouldBlock => unreachable, // can't happen for directories | ||
| 1389 | error.FileBusy => unreachable, // can't happen for directories | ||
| 1390 | else => |e| return e, | ||
| 1391 | }; | ||
| 1392 | return Dir{ .fd = fd }; | ||
| 1393 | } | 1396 | } |
| 1394 | 1397 | ||
| 1395 | /// Same as `openDir` except the parameter is null-terminated. | 1398 | /// Same as `openDir` except the parameter is null-terminated. |
| 1396 | pub fn openDirZ(self: Dir, sub_path_c: [*:0]const u8, args: OpenDirOptions) OpenError!Dir { | 1399 | pub fn openDirZ(self: Dir, sub_path_c: [*:0]const u8, args: OpenDirOptions) OpenError!Dir { |
| 1397 | if (builtin.os.tag == .windows) { | 1400 | switch (builtin.os.tag) { |
| 1398 | const sub_path_w = try std.os.windows.cStrToPrefixedFileW(self.fd, sub_path_c); | 1401 | .windows => { |
| 1399 | return self.openDirW(sub_path_w.span().ptr, args); | 1402 | const sub_path_w = try std.os.windows.cStrToPrefixedFileW(self.fd, sub_path_c); |
| 1400 | } | 1403 | return self.openDirW(sub_path_w.span().ptr, args); |
| 1401 | const symlink_flags: u32 = if (args.no_follow) posix.O.NOFOLLOW else 0x0; | 1404 | }, |
| 1402 | if (!args.iterate) { | 1405 | .wasi => { |
| 1403 | const O_PATH = if (@hasDecl(posix.O, "PATH")) posix.O.PATH else 0; | 1406 | return openDir(self, mem.sliceTo(sub_path_c, 0), args); |
| 1404 | return self.openDirFlagsZ(sub_path_c, posix.O.DIRECTORY | posix.O.RDONLY | posix.O.CLOEXEC | O_PATH | symlink_flags); | 1407 | }, |
| 1405 | } else { | 1408 | else => { |
| 1406 | return self.openDirFlagsZ(sub_path_c, posix.O.DIRECTORY | posix.O.RDONLY | posix.O.CLOEXEC | symlink_flags); | 1409 | var symlink_flags: posix.O = .{ |
| 1410 | .ACCMODE = .RDONLY, | ||
| 1411 | .NOFOLLOW = args.no_follow, | ||
| 1412 | .DIRECTORY = true, | ||
| 1413 | .CLOEXEC = true, | ||
| 1414 | }; | ||
| 1415 | if (@hasField(posix.O, "PATH") and !args.iterate) | ||
| 1416 | symlink_flags.PATH = true; | ||
| 1417 | |||
| 1418 | return self.openDirFlagsZ(sub_path_c, symlink_flags); | ||
| 1419 | }, | ||
| 1407 | } | 1420 | } |
| 1408 | } | 1421 | } |
| 1409 | 1422 | ||
| ... | @@ -1422,13 +1435,14 @@ pub fn openDirW(self: Dir, sub_path_w: [*:0]const u16, args: OpenDirOptions) Ope | ... | @@ -1422,13 +1435,14 @@ pub fn openDirW(self: Dir, sub_path_w: [*:0]const u16, args: OpenDirOptions) Ope |
| 1422 | return dir; | 1435 | return dir; |
| 1423 | } | 1436 | } |
| 1424 | 1437 | ||
| 1425 | /// `flags` must contain `posix.O.DIRECTORY`. | 1438 | /// Asserts `flags` has `DIRECTORY` set. |
| 1426 | fn openDirFlagsZ(self: Dir, sub_path_c: [*:0]const u8, flags: u32) OpenError!Dir { | 1439 | fn openDirFlagsZ(self: Dir, sub_path_c: [*:0]const u8, flags: posix.O) OpenError!Dir { |
| 1440 | assert(flags.DIRECTORY); | ||
| 1427 | const fd = posix.openatZ(self.fd, sub_path_c, flags, 0) catch |err| switch (err) { | 1441 | const fd = posix.openatZ(self.fd, sub_path_c, flags, 0) catch |err| switch (err) { |
| 1428 | error.FileTooBig => unreachable, // can't happen for directories | 1442 | error.FileTooBig => unreachable, // can't happen for directories |
| 1429 | error.IsDir => unreachable, // we're providing O.DIRECTORY | 1443 | error.IsDir => unreachable, // we're setting DIRECTORY |
| 1430 | error.NoSpaceLeft => unreachable, // not providing O.CREAT | 1444 | error.NoSpaceLeft => unreachable, // not setting CREAT |
| 1431 | error.PathAlreadyExists => unreachable, // not providing O.CREAT | 1445 | error.PathAlreadyExists => unreachable, // not setting CREAT |
| 1432 | error.FileLocksNotSupported => unreachable, // locking folders is not supported | 1446 | error.FileLocksNotSupported => unreachable, // locking folders is not supported |
| 1433 | error.WouldBlock => unreachable, // can't happen for directories | 1447 | error.WouldBlock => unreachable, // can't happen for directories |
| 1434 | error.FileBusy => unreachable, // can't happen for directories | 1448 | error.FileBusy => unreachable, // can't happen for directories |
| ... | @@ -2446,8 +2460,8 @@ pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat { | ... | @@ -2446,8 +2460,8 @@ pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat { |
| 2446 | return file.stat(); | 2460 | return file.stat(); |
| 2447 | } | 2461 | } |
| 2448 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 2462 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2449 | const st = try posix.fstatatWasi(self.fd, sub_path, posix.wasi.LOOKUP_SYMLINK_FOLLOW); | 2463 | const st = try posix.fstatat_wasi(self.fd, sub_path, .{ .SYMLINK_FOLLOW = true }); |
| 2450 | return Stat.fromSystem(st); | 2464 | return Stat.fromWasi(st); |
| 2451 | } | 2465 | } |
| 2452 | const st = try posix.fstatat(self.fd, sub_path, 0); | 2466 | const st = try posix.fstatat(self.fd, sub_path, 0); |
| 2453 | return Stat.fromSystem(st); | 2467 | return Stat.fromSystem(st); |
| ... | @@ -2507,3 +2521,4 @@ const posix = std.os; | ... | @@ -2507,3 +2521,4 @@ const posix = std.os; |
| 2507 | const mem = std.mem; | 2521 | const mem = std.mem; |
| 2508 | const fs = std.fs; | 2522 | const fs = std.fs; |
| 2509 | const Allocator = std.mem.Allocator; | 2523 | const Allocator = std.mem.Allocator; |
| 2524 | const assert = std.debug.assert; |
lib/std/fs/File.zig+95-47| ... | @@ -290,49 +290,59 @@ pub const Stat = struct { | ... | @@ -290,49 +290,59 @@ pub const Stat = struct { |
| 290 | /// Last status/metadata change time in nanoseconds, relative to UTC 1970-01-01. | 290 | /// Last status/metadata change time in nanoseconds, relative to UTC 1970-01-01. |
| 291 | ctime: i128, | 291 | ctime: i128, |
| 292 | 292 | ||
| 293 | pub fn fromSystem(st: posix.system.Stat) Stat { | 293 | pub fn fromSystem(st: posix.Stat) Stat { |
| 294 | const atime = st.atime(); | 294 | const atime = st.atime(); |
| 295 | const mtime = st.mtime(); | 295 | const mtime = st.mtime(); |
| 296 | const ctime = st.ctime(); | 296 | const ctime = st.ctime(); |
| 297 | const kind: Kind = if (builtin.os.tag == .wasi and !builtin.link_libc) switch (st.filetype) { | 297 | return .{ |
| 298 | .BLOCK_DEVICE => .block_device, | ||
| 299 | .CHARACTER_DEVICE => .character_device, | ||
| 300 | .DIRECTORY => .directory, | ||
| 301 | .SYMBOLIC_LINK => .sym_link, | ||
| 302 | .REGULAR_FILE => .file, | ||
| 303 | .SOCKET_STREAM, .SOCKET_DGRAM => .unix_domain_socket, | ||
| 304 | else => .unknown, | ||
| 305 | } else blk: { | ||
| 306 | const m = st.mode & posix.S.IFMT; | ||
| 307 | switch (m) { | ||
| 308 | posix.S.IFBLK => break :blk .block_device, | ||
| 309 | posix.S.IFCHR => break :blk .character_device, | ||
| 310 | posix.S.IFDIR => break :blk .directory, | ||
| 311 | posix.S.IFIFO => break :blk .named_pipe, | ||
| 312 | posix.S.IFLNK => break :blk .sym_link, | ||
| 313 | posix.S.IFREG => break :blk .file, | ||
| 314 | posix.S.IFSOCK => break :blk .unix_domain_socket, | ||
| 315 | else => {}, | ||
| 316 | } | ||
| 317 | if (builtin.os.tag.isSolarish()) switch (m) { | ||
| 318 | posix.S.IFDOOR => break :blk .door, | ||
| 319 | posix.S.IFPORT => break :blk .event_port, | ||
| 320 | else => {}, | ||
| 321 | }; | ||
| 322 | |||
| 323 | break :blk .unknown; | ||
| 324 | }; | ||
| 325 | |||
| 326 | return Stat{ | ||
| 327 | .inode = st.ino, | 298 | .inode = st.ino, |
| 328 | .size = @as(u64, @bitCast(st.size)), | 299 | .size = @bitCast(st.size), |
| 329 | .mode = st.mode, | 300 | .mode = st.mode, |
| 330 | .kind = kind, | 301 | .kind = k: { |
| 302 | const m = st.mode & posix.S.IFMT; | ||
| 303 | switch (m) { | ||
| 304 | posix.S.IFBLK => break :k .block_device, | ||
| 305 | posix.S.IFCHR => break :k .character_device, | ||
| 306 | posix.S.IFDIR => break :k .directory, | ||
| 307 | posix.S.IFIFO => break :k .named_pipe, | ||
| 308 | posix.S.IFLNK => break :k .sym_link, | ||
| 309 | posix.S.IFREG => break :k .file, | ||
| 310 | posix.S.IFSOCK => break :k .unix_domain_socket, | ||
| 311 | else => {}, | ||
| 312 | } | ||
| 313 | if (builtin.os.tag.isSolarish()) switch (m) { | ||
| 314 | posix.S.IFDOOR => break :k .door, | ||
| 315 | posix.S.IFPORT => break :k .event_port, | ||
| 316 | else => {}, | ||
| 317 | }; | ||
| 318 | |||
| 319 | break :k .unknown; | ||
| 320 | }, | ||
| 331 | .atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec, | 321 | .atime = @as(i128, atime.tv_sec) * std.time.ns_per_s + atime.tv_nsec, |
| 332 | .mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec, | 322 | .mtime = @as(i128, mtime.tv_sec) * std.time.ns_per_s + mtime.tv_nsec, |
| 333 | .ctime = @as(i128, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec, | 323 | .ctime = @as(i128, ctime.tv_sec) * std.time.ns_per_s + ctime.tv_nsec, |
| 334 | }; | 324 | }; |
| 335 | } | 325 | } |
| 326 | |||
| 327 | pub fn fromWasi(st: std.os.wasi.filestat_t) Stat { | ||
| 328 | return .{ | ||
| 329 | .inode = st.ino, | ||
| 330 | .size = @bitCast(st.size), | ||
| 331 | .mode = 0, | ||
| 332 | .kind = switch (st.filetype) { | ||
| 333 | .BLOCK_DEVICE => .block_device, | ||
| 334 | .CHARACTER_DEVICE => .character_device, | ||
| 335 | .DIRECTORY => .directory, | ||
| 336 | .SYMBOLIC_LINK => .sym_link, | ||
| 337 | .REGULAR_FILE => .file, | ||
| 338 | .SOCKET_STREAM, .SOCKET_DGRAM => .unix_domain_socket, | ||
| 339 | else => .unknown, | ||
| 340 | }, | ||
| 341 | .atime = st.atim, | ||
| 342 | .mtime = st.mtim, | ||
| 343 | .ctime = st.ctim, | ||
| 344 | }; | ||
| 345 | } | ||
| 336 | }; | 346 | }; |
| 337 | 347 | ||
| 338 | pub const StatError = posix.FStatError; | 348 | pub const StatError = posix.FStatError; |
| ... | @@ -355,7 +365,7 @@ pub fn stat(self: File) StatError!Stat { | ... | @@ -355,7 +365,7 @@ pub fn stat(self: File) StatError!Stat { |
| 355 | .ACCESS_DENIED => return error.AccessDenied, | 365 | .ACCESS_DENIED => return error.AccessDenied, |
| 356 | else => return windows.unexpectedStatus(rc), | 366 | else => return windows.unexpectedStatus(rc), |
| 357 | } | 367 | } |
| 358 | return Stat{ | 368 | return .{ |
| 359 | .inode = info.InternalInformation.IndexNumber, | 369 | .inode = info.InternalInformation.IndexNumber, |
| 360 | .size = @as(u64, @bitCast(info.StandardInformation.EndOfFile)), | 370 | .size = @as(u64, @bitCast(info.StandardInformation.EndOfFile)), |
| 361 | .mode = 0, | 371 | .mode = 0, |
| ... | @@ -385,6 +395,11 @@ pub fn stat(self: File) StatError!Stat { | ... | @@ -385,6 +395,11 @@ pub fn stat(self: File) StatError!Stat { |
| 385 | }; | 395 | }; |
| 386 | } | 396 | } |
| 387 | 397 | ||
| 398 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | ||
| 399 | const st = try posix.fstat_wasi(self.handle); | ||
| 400 | return Stat.fromWasi(st); | ||
| 401 | } | ||
| 402 | |||
| 388 | const st = try posix.fstat(self.handle); | 403 | const st = try posix.fstat(self.handle); |
| 389 | return Stat.fromSystem(st); | 404 | return Stat.fromSystem(st); |
| 390 | } | 405 | } |
| ... | @@ -576,10 +591,11 @@ pub fn setPermissions(self: File, permissions: Permissions) SetPermissionsError! | ... | @@ -576,10 +591,11 @@ pub fn setPermissions(self: File, permissions: Permissions) SetPermissionsError! |
| 576 | /// Cross-platform representation of file metadata. | 591 | /// Cross-platform representation of file metadata. |
| 577 | /// Platform-specific functionality is available through the `inner` field. | 592 | /// Platform-specific functionality is available through the `inner` field. |
| 578 | pub const Metadata = struct { | 593 | pub const Metadata = struct { |
| 579 | /// You may use the `inner` field to use platform-specific functionality | 594 | /// Exposes platform-specific functionality. |
| 580 | inner: switch (builtin.os.tag) { | 595 | inner: switch (builtin.os.tag) { |
| 581 | .windows => MetadataWindows, | 596 | .windows => MetadataWindows, |
| 582 | .linux => MetadataLinux, | 597 | .linux => MetadataLinux, |
| 598 | .wasi => MetadataWasi, | ||
| 583 | else => MetadataUnix, | 599 | else => MetadataUnix, |
| 584 | }, | 600 | }, |
| 585 | 601 | ||
| ... | @@ -628,12 +644,12 @@ pub const MetadataUnix = struct { | ... | @@ -628,12 +644,12 @@ pub const MetadataUnix = struct { |
| 628 | 644 | ||
| 629 | /// Returns the size of the file | 645 | /// Returns the size of the file |
| 630 | pub fn size(self: Self) u64 { | 646 | pub fn size(self: Self) u64 { |
| 631 | return @as(u64, @intCast(self.stat.size)); | 647 | return @intCast(self.stat.size); |
| 632 | } | 648 | } |
| 633 | 649 | ||
| 634 | /// Returns a `Permissions` struct, representing the permissions on the file | 650 | /// Returns a `Permissions` struct, representing the permissions on the file |
| 635 | pub fn permissions(self: Self) Permissions { | 651 | pub fn permissions(self: Self) Permissions { |
| 636 | return Permissions{ .inner = PermissionsUnix{ .mode = self.stat.mode } }; | 652 | return .{ .inner = .{ .mode = self.stat.mode } }; |
| 637 | } | 653 | } |
| 638 | 654 | ||
| 639 | /// Returns the `Kind` of the file | 655 | /// Returns the `Kind` of the file |
| ... | @@ -756,6 +772,42 @@ pub const MetadataLinux = struct { | ... | @@ -756,6 +772,42 @@ pub const MetadataLinux = struct { |
| 756 | } | 772 | } |
| 757 | }; | 773 | }; |
| 758 | 774 | ||
| 775 | pub const MetadataWasi = struct { | ||
| 776 | stat: std.os.wasi.filestat_t, | ||
| 777 | |||
| 778 | pub fn size(self: @This()) u64 { | ||
| 779 | return self.stat.size; | ||
| 780 | } | ||
| 781 | |||
| 782 | pub fn permissions(self: @This()) Permissions { | ||
| 783 | return .{ .inner = .{ .mode = self.stat.mode } }; | ||
| 784 | } | ||
| 785 | |||
| 786 | pub fn kind(self: @This()) Kind { | ||
| 787 | return switch (self.stat.filetype) { | ||
| 788 | .BLOCK_DEVICE => .block_device, | ||
| 789 | .CHARACTER_DEVICE => .character_device, | ||
| 790 | .DIRECTORY => .directory, | ||
| 791 | .SYMBOLIC_LINK => .sym_link, | ||
| 792 | .REGULAR_FILE => .file, | ||
| 793 | .SOCKET_STREAM, .SOCKET_DGRAM => .unix_domain_socket, | ||
| 794 | else => .unknown, | ||
| 795 | }; | ||
| 796 | } | ||
| 797 | |||
| 798 | pub fn accessed(self: @This()) i128 { | ||
| 799 | return self.stat.atim; | ||
| 800 | } | ||
| 801 | |||
| 802 | pub fn modified(self: @This()) i128 { | ||
| 803 | return self.stat.mtim; | ||
| 804 | } | ||
| 805 | |||
| 806 | pub fn created(self: @This()) ?i128 { | ||
| 807 | return self.stat.ctim; | ||
| 808 | } | ||
| 809 | }; | ||
| 810 | |||
| 759 | pub const MetadataWindows = struct { | 811 | pub const MetadataWindows = struct { |
| 760 | attributes: windows.DWORD, | 812 | attributes: windows.DWORD, |
| 761 | reparse_tag: windows.DWORD, | 813 | reparse_tag: windows.DWORD, |
| ... | @@ -773,7 +825,7 @@ pub const MetadataWindows = struct { | ... | @@ -773,7 +825,7 @@ pub const MetadataWindows = struct { |
| 773 | 825 | ||
| 774 | /// Returns a `Permissions` struct, representing the permissions on the file | 826 | /// Returns a `Permissions` struct, representing the permissions on the file |
| 775 | pub fn permissions(self: Self) Permissions { | 827 | pub fn permissions(self: Self) Permissions { |
| 776 | return Permissions{ .inner = PermissionsWindows{ .attributes = self.attributes } }; | 828 | return .{ .inner = .{ .attributes = self.attributes } }; |
| 777 | } | 829 | } |
| 778 | 830 | ||
| 779 | /// Returns the `Kind` of the file. | 831 | /// Returns the `Kind` of the file. |
| ... | @@ -811,7 +863,7 @@ pub const MetadataWindows = struct { | ... | @@ -811,7 +863,7 @@ pub const MetadataWindows = struct { |
| 811 | pub const MetadataError = posix.FStatError; | 863 | pub const MetadataError = posix.FStatError; |
| 812 | 864 | ||
| 813 | pub fn metadata(self: File) MetadataError!Metadata { | 865 | pub fn metadata(self: File) MetadataError!Metadata { |
| 814 | return Metadata{ | 866 | return .{ |
| 815 | .inner = switch (builtin.os.tag) { | 867 | .inner = switch (builtin.os.tag) { |
| 816 | .windows => blk: { | 868 | .windows => blk: { |
| 817 | var io_status_block: windows.IO_STATUS_BLOCK = undefined; | 869 | var io_status_block: windows.IO_STATUS_BLOCK = undefined; |
| ... | @@ -846,7 +898,7 @@ pub fn metadata(self: File) MetadataError!Metadata { | ... | @@ -846,7 +898,7 @@ pub fn metadata(self: File) MetadataError!Metadata { |
| 846 | break :reparse_blk 0; | 898 | break :reparse_blk 0; |
| 847 | }; | 899 | }; |
| 848 | 900 | ||
| 849 | break :blk MetadataWindows{ | 901 | break :blk .{ |
| 850 | .attributes = info.BasicInformation.FileAttributes, | 902 | .attributes = info.BasicInformation.FileAttributes, |
| 851 | .reparse_tag = reparse_tag, | 903 | .reparse_tag = reparse_tag, |
| 852 | ._size = @as(u64, @bitCast(info.StandardInformation.EndOfFile)), | 904 | ._size = @as(u64, @bitCast(info.StandardInformation.EndOfFile)), |
| ... | @@ -887,16 +939,12 @@ pub fn metadata(self: File) MetadataError!Metadata { | ... | @@ -887,16 +939,12 @@ pub fn metadata(self: File) MetadataError!Metadata { |
| 887 | else => |err| return posix.unexpectedErrno(err), | 939 | else => |err| return posix.unexpectedErrno(err), |
| 888 | } | 940 | } |
| 889 | 941 | ||
| 890 | break :blk MetadataLinux{ | 942 | break :blk .{ |
| 891 | .statx = stx, | 943 | .statx = stx, |
| 892 | }; | 944 | }; |
| 893 | }, | 945 | }, |
| 894 | else => blk: { | 946 | .wasi => .{ .stat = try posix.fstat_wasi(self.handle) }, |
| 895 | const st = try posix.fstat(self.handle); | 947 | else => .{ .stat = try posix.fstat(self.handle) }, |
| 896 | break :blk MetadataUnix{ | ||
| 897 | .stat = st, | ||
| 898 | }; | ||
| 899 | }, | ||
| 900 | }, | 948 | }, |
| 901 | }; | 949 | }; |
| 902 | } | 950 | } |
lib/std/fs/test.zig+6-1| ... | @@ -242,7 +242,12 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { | ... | @@ -242,7 +242,12 @@ test "File.stat on a File that is a symlink returns Kind.sym_link" { |
| 242 | const sub_path_c = try os.toPosixPath("symlink"); | 242 | const sub_path_c = try os.toPosixPath("symlink"); |
| 243 | // the O_NOFOLLOW | O_PATH combination can obtain a fd to a symlink | 243 | // the O_NOFOLLOW | O_PATH combination can obtain a fd to a symlink |
| 244 | // note that if O_DIRECTORY is set, then this will error with ENOTDIR | 244 | // note that if O_DIRECTORY is set, then this will error with ENOTDIR |
| 245 | const flags = os.O.NOFOLLOW | os.O.PATH | os.O.RDONLY | os.O.CLOEXEC; | 245 | const flags: os.O = .{ |
| 246 | .NOFOLLOW = true, | ||
| 247 | .PATH = true, | ||
| 248 | .ACCMODE = .RDONLY, | ||
| 249 | .CLOEXEC = true, | ||
| 250 | }; | ||
| 246 | const fd = try os.openatZ(ctx.dir.fd, &sub_path_c, flags, 0); | 251 | const fd = try os.openatZ(ctx.dir.fd, &sub_path_c, flags, 0); |
| 247 | break :linux_symlink Dir{ .fd = fd }; | 252 | break :linux_symlink Dir{ .fd = fd }; |
| 248 | }, | 253 | }, |
lib/std/os.zig+214-220| ... | @@ -24,7 +24,6 @@ const elf = std.elf; | ... | @@ -24,7 +24,6 @@ const elf = std.elf; |
| 24 | const fs = std.fs; | 24 | const fs = std.fs; |
| 25 | const dl = @import("dynamic_library.zig"); | 25 | const dl = @import("dynamic_library.zig"); |
| 26 | const MAX_PATH_BYTES = std.fs.MAX_PATH_BYTES; | 26 | const MAX_PATH_BYTES = std.fs.MAX_PATH_BYTES; |
| 27 | const is_windows = builtin.os.tag == .windows; | ||
| 28 | 27 | ||
| 29 | pub const darwin = std.c; | 28 | pub const darwin = std.c; |
| 30 | pub const dragonfly = std.c; | 29 | pub const dragonfly = std.c; |
| ... | @@ -62,16 +61,21 @@ test { | ... | @@ -62,16 +61,21 @@ test { |
| 62 | /// When not linking libc, it is the OS-specific system interface. | 61 | /// When not linking libc, it is the OS-specific system interface. |
| 63 | pub const system = if (@hasDecl(root, "os") and root.os != @This()) | 62 | pub const system = if (@hasDecl(root, "os") and root.os != @This()) |
| 64 | root.os.system | 63 | root.os.system |
| 65 | else if (builtin.link_libc or is_windows) | 64 | else if (use_libc) |
| 66 | std.c | 65 | std.c |
| 67 | else switch (builtin.os.tag) { | 66 | else switch (builtin.os.tag) { |
| 68 | .linux => linux, | 67 | .linux => linux, |
| 69 | .plan9 => plan9, | 68 | .plan9 => plan9, |
| 70 | .wasi => wasi, | ||
| 71 | .uefi => uefi, | 69 | .uefi => uefi, |
| 72 | else => struct {}, | 70 | else => struct {}, |
| 73 | }; | 71 | }; |
| 74 | 72 | ||
| 73 | /// Whether to use libc for the POSIX API layer. | ||
| 74 | const use_libc = builtin.link_libc or switch (builtin.os.tag) { | ||
| 75 | .windows, .wasi => true, | ||
| 76 | else => false, | ||
| 77 | }; | ||
| 78 | |||
| 75 | pub const AF = system.AF; | 79 | pub const AF = system.AF; |
| 76 | pub const AF_SUN = system.AF_SUN; | 80 | pub const AF_SUN = system.AF_SUN; |
| 77 | pub const ARCH = system.ARCH; | 81 | pub const ARCH = system.ARCH; |
| ... | @@ -87,10 +91,7 @@ pub const F = system.F; | ... | @@ -87,10 +91,7 @@ pub const F = system.F; |
| 87 | pub const FD_CLOEXEC = system.FD_CLOEXEC; | 91 | pub const FD_CLOEXEC = system.FD_CLOEXEC; |
| 88 | pub const Flock = system.Flock; | 92 | pub const Flock = system.Flock; |
| 89 | pub const HOST_NAME_MAX = system.HOST_NAME_MAX; | 93 | pub const HOST_NAME_MAX = system.HOST_NAME_MAX; |
| 90 | pub const HW = switch (builtin.os.tag) { | 94 | pub const HW = system.HW; |
| 91 | .openbsd => system.HW, | ||
| 92 | else => .{}, | ||
| 93 | }; | ||
| 94 | pub const IFNAMESIZE = system.IFNAMESIZE; | 95 | pub const IFNAMESIZE = system.IFNAMESIZE; |
| 95 | pub const IOV_MAX = system.IOV_MAX; | 96 | pub const IOV_MAX = system.IOV_MAX; |
| 96 | pub const IPPROTO = system.IPPROTO; | 97 | pub const IPPROTO = system.IPPROTO; |
| ... | @@ -105,19 +106,13 @@ pub const MFD = system.MFD; | ... | @@ -105,19 +106,13 @@ pub const MFD = system.MFD; |
| 105 | pub const MMAP2_UNIT = system.MMAP2_UNIT; | 106 | pub const MMAP2_UNIT = system.MMAP2_UNIT; |
| 106 | pub const MSG = system.MSG; | 107 | pub const MSG = system.MSG; |
| 107 | pub const NAME_MAX = system.NAME_MAX; | 108 | pub const NAME_MAX = system.NAME_MAX; |
| 108 | pub const O = switch (builtin.os.tag) { | 109 | pub const O = system.O; |
| 109 | // We want to expose the POSIX-like OFLAGS, so we use std.c.wasi.O instead | ||
| 110 | // of std.os.wasi.O, which is for non-POSIX-like `wasi.path_open`, etc. | ||
| 111 | .wasi => std.c.O, | ||
| 112 | else => system.O, | ||
| 113 | }; | ||
| 114 | pub const PATH_MAX = system.PATH_MAX; | 110 | pub const PATH_MAX = system.PATH_MAX; |
| 115 | pub const POLL = system.POLL; | 111 | pub const POLL = system.POLL; |
| 116 | pub const POSIX_FADV = system.POSIX_FADV; | 112 | pub const POSIX_FADV = system.POSIX_FADV; |
| 117 | pub const PR = system.PR; | 113 | pub const PR = system.PR; |
| 118 | pub const PROT = system.PROT; | 114 | pub const PROT = system.PROT; |
| 119 | pub const REG = system.REG; | 115 | pub const REG = system.REG; |
| 120 | pub const RIGHT = system.RIGHT; | ||
| 121 | pub const RLIM = system.RLIM; | 116 | pub const RLIM = system.RLIM; |
| 122 | pub const RR = system.RR; | 117 | pub const RR = system.RR; |
| 123 | pub const S = system.S; | 118 | pub const S = system.S; |
| ... | @@ -151,12 +146,9 @@ pub const dl_phdr_info = system.dl_phdr_info; | ... | @@ -151,12 +146,9 @@ pub const dl_phdr_info = system.dl_phdr_info; |
| 151 | pub const empty_sigset = system.empty_sigset; | 146 | pub const empty_sigset = system.empty_sigset; |
| 152 | pub const filled_sigset = system.filled_sigset; | 147 | pub const filled_sigset = system.filled_sigset; |
| 153 | pub const fd_t = system.fd_t; | 148 | pub const fd_t = system.fd_t; |
| 154 | pub const fdflags_t = system.fdflags_t; | ||
| 155 | pub const fdstat_t = system.fdstat_t; | ||
| 156 | pub const gid_t = system.gid_t; | 149 | pub const gid_t = system.gid_t; |
| 157 | pub const ifreq = system.ifreq; | 150 | pub const ifreq = system.ifreq; |
| 158 | pub const ino_t = system.ino_t; | 151 | pub const ino_t = system.ino_t; |
| 159 | pub const lookupflags_t = system.lookupflags_t; | ||
| 160 | pub const mcontext_t = system.mcontext_t; | 152 | pub const mcontext_t = system.mcontext_t; |
| 161 | pub const mode_t = system.mode_t; | 153 | pub const mode_t = system.mode_t; |
| 162 | pub const msghdr = system.msghdr; | 154 | pub const msghdr = system.msghdr; |
| ... | @@ -164,14 +156,12 @@ pub const msghdr_const = system.msghdr_const; | ... | @@ -164,14 +156,12 @@ pub const msghdr_const = system.msghdr_const; |
| 164 | pub const nfds_t = system.nfds_t; | 156 | pub const nfds_t = system.nfds_t; |
| 165 | pub const nlink_t = system.nlink_t; | 157 | pub const nlink_t = system.nlink_t; |
| 166 | pub const off_t = system.off_t; | 158 | pub const off_t = system.off_t; |
| 167 | pub const oflags_t = system.oflags_t; | ||
| 168 | pub const pid_t = system.pid_t; | 159 | pub const pid_t = system.pid_t; |
| 169 | pub const pollfd = system.pollfd; | 160 | pub const pollfd = system.pollfd; |
| 170 | pub const port_t = system.port_t; | 161 | pub const port_t = system.port_t; |
| 171 | pub const port_event = system.port_event; | 162 | pub const port_event = system.port_event; |
| 172 | pub const port_notify = system.port_notify; | 163 | pub const port_notify = system.port_notify; |
| 173 | pub const file_obj = system.file_obj; | 164 | pub const file_obj = system.file_obj; |
| 174 | pub const rights_t = system.rights_t; | ||
| 175 | pub const rlim_t = system.rlim_t; | 165 | pub const rlim_t = system.rlim_t; |
| 176 | pub const rlimit = system.rlimit; | 166 | pub const rlimit = system.rlimit; |
| 177 | pub const rlimit_resource = system.rlimit_resource; | 167 | pub const rlimit_resource = system.rlimit_resource; |
| ... | @@ -209,6 +199,12 @@ pub const iovec_const = extern struct { | ... | @@ -209,6 +199,12 @@ pub const iovec_const = extern struct { |
| 209 | iov_len: usize, | 199 | iov_len: usize, |
| 210 | }; | 200 | }; |
| 211 | 201 | ||
| 202 | pub const ACCMODE = enum(u2) { | ||
| 203 | RDONLY = 0, | ||
| 204 | WRONLY = 1, | ||
| 205 | RDWR = 2, | ||
| 206 | }; | ||
| 207 | |||
| 212 | pub const LOG = struct { | 208 | pub const LOG = struct { |
| 213 | /// system is unusable | 209 | /// system is unusable |
| 214 | pub const EMERG = 0; | 210 | pub const EMERG = 0; |
| ... | @@ -460,13 +456,13 @@ fn fchmodat2(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtEr | ... | @@ -460,13 +456,13 @@ fn fchmodat2(dirfd: fd_t, path: []const u8, mode: mode_t, flags: u32) FChmodAtEr |
| 460 | 456 | ||
| 461 | // Fallback to changing permissions using procfs: | 457 | // Fallback to changing permissions using procfs: |
| 462 | // | 458 | // |
| 463 | // 1. Open `path` as an `O.PATH` descriptor. | 459 | // 1. Open `path` as a `PATH` descriptor. |
| 464 | // 2. Stat the fd and check if it isn't a symbolic link. | 460 | // 2. Stat the fd and check if it isn't a symbolic link. |
| 465 | // 3. Generate the procfs reference to the fd via `/proc/self/fd/{fd}`. | 461 | // 3. Generate the procfs reference to the fd via `/proc/self/fd/{fd}`. |
| 466 | // 4. Pass the procfs path to `chmod` with the `mode`. | 462 | // 4. Pass the procfs path to `chmod` with the `mode`. |
| 467 | var pathfd: fd_t = undefined; | 463 | var pathfd: fd_t = undefined; |
| 468 | while (true) { | 464 | while (true) { |
| 469 | const rc = system.openat(dirfd, &path_c, O.PATH | O.NOFOLLOW | O.CLOEXEC, @as(mode_t, 0)); | 465 | const rc = system.openat(dirfd, &path_c, .{ .PATH = true, .NOFOLLOW = true, .CLOEXEC = true }, @as(mode_t, 0)); |
| 470 | switch (system.getErrno(rc)) { | 466 | switch (system.getErrno(rc)) { |
| 471 | .SUCCESS => { | 467 | .SUCCESS => { |
| 472 | pathfd = @as(fd_t, @intCast(rc)); | 468 | pathfd = @as(fd_t, @intCast(rc)); |
| ... | @@ -536,8 +532,10 @@ pub const FChownError = error{ | ... | @@ -536,8 +532,10 @@ pub const FChownError = error{ |
| 536 | /// any group of which the owner is a member. If the owner or group is | 532 | /// any group of which the owner is a member. If the owner or group is |
| 537 | /// specified as `null`, the ID is not changed. | 533 | /// specified as `null`, the ID is not changed. |
| 538 | pub fn fchown(fd: fd_t, owner: ?uid_t, group: ?gid_t) FChownError!void { | 534 | pub fn fchown(fd: fd_t, owner: ?uid_t, group: ?gid_t) FChownError!void { |
| 539 | if (builtin.os.tag == .windows or builtin.os.tag == .wasi) | 535 | switch (builtin.os.tag) { |
| 540 | @compileError("Unsupported OS"); | 536 | .windows, .wasi => @compileError("Unsupported OS"), |
| 537 | else => {}, | ||
| 538 | } | ||
| 541 | 539 | ||
| 542 | while (true) { | 540 | while (true) { |
| 543 | const res = system.fchown(fd, owner orelse @as(u32, 0) -% 1, group orelse @as(u32, 0) -% 1); | 541 | const res = system.fchown(fd, owner orelse @as(u32, 0) -% 1, group orelse @as(u32, 0) -% 1); |
| ... | @@ -675,7 +673,7 @@ pub fn getrandom(buffer: []u8) GetRandomError!void { | ... | @@ -675,7 +673,7 @@ pub fn getrandom(buffer: []u8) GetRandomError!void { |
| 675 | } | 673 | } |
| 676 | 674 | ||
| 677 | fn getRandomBytesDevURandom(buf: []u8) !void { | 675 | fn getRandomBytesDevURandom(buf: []u8) !void { |
| 678 | const fd = try openZ("/dev/urandom", O.RDONLY | O.CLOEXEC, 0); | 676 | const fd = try openZ("/dev/urandom", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); |
| 679 | defer close(fd); | 677 | defer close(fd); |
| 680 | 678 | ||
| 681 | const st = try fstat(fd); | 679 | const st = try fstat(fd); |
| ... | @@ -1590,18 +1588,18 @@ pub const OpenError = error{ | ... | @@ -1590,18 +1588,18 @@ pub const OpenError = error{ |
| 1590 | /// for 64-bit targets, as well as when opening directories. | 1588 | /// for 64-bit targets, as well as when opening directories. |
| 1591 | FileTooBig, | 1589 | FileTooBig, |
| 1592 | 1590 | ||
| 1593 | /// The path refers to directory but the `O.DIRECTORY` flag was not provided. | 1591 | /// The path refers to directory but the `DIRECTORY` flag was not provided. |
| 1594 | IsDir, | 1592 | IsDir, |
| 1595 | 1593 | ||
| 1596 | /// A new path cannot be created because the device has no room for the new file. | 1594 | /// A new path cannot be created because the device has no room for the new file. |
| 1597 | /// This error is only reachable when the `O.CREAT` flag is provided. | 1595 | /// This error is only reachable when the `CREAT` flag is provided. |
| 1598 | NoSpaceLeft, | 1596 | NoSpaceLeft, |
| 1599 | 1597 | ||
| 1600 | /// A component used as a directory in the path was not, in fact, a directory, or | 1598 | /// A component used as a directory in the path was not, in fact, a directory, or |
| 1601 | /// `O.DIRECTORY` was specified and the path was not a directory. | 1599 | /// `DIRECTORY` was specified and the path was not a directory. |
| 1602 | NotDir, | 1600 | NotDir, |
| 1603 | 1601 | ||
| 1604 | /// The path already exists and the `O.CREAT` and `O.EXCL` flags were provided. | 1602 | /// The path already exists and the `CREAT` and `EXCL` flags were provided. |
| 1605 | PathAlreadyExists, | 1603 | PathAlreadyExists, |
| 1606 | DeviceBusy, | 1604 | DeviceBusy, |
| 1607 | 1605 | ||
| ... | @@ -1629,12 +1627,11 @@ pub const OpenError = error{ | ... | @@ -1629,12 +1627,11 @@ pub const OpenError = error{ |
| 1629 | 1627 | ||
| 1630 | /// Open and possibly create a file. Keeps trying if it gets interrupted. | 1628 | /// Open and possibly create a file. Keeps trying if it gets interrupted. |
| 1631 | /// See also `openZ`. | 1629 | /// See also `openZ`. |
| 1632 | pub fn open(file_path: []const u8, flags: u32, perm: mode_t) OpenError!fd_t { | 1630 | pub fn open(file_path: []const u8, flags: O, perm: mode_t) OpenError!fd_t { |
| 1633 | if (builtin.os.tag == .windows) { | 1631 | if (builtin.os.tag == .windows) { |
| 1634 | const file_path_w = try windows.sliceToPrefixedFileW(null, file_path); | 1632 | @compileError("Windows does not support POSIX; use Windows-specific API or cross-platform std.fs API"); |
| 1635 | return openW(file_path_w.span(), flags, perm); | ||
| 1636 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 1633 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1637 | return openat(wasi.AT.FDCWD, file_path, flags, perm); | 1634 | return openat(AT.FDCWD, file_path, flags, perm); |
| 1638 | } | 1635 | } |
| 1639 | const file_path_c = try toPosixPath(file_path); | 1636 | const file_path_c = try toPosixPath(file_path); |
| 1640 | return openZ(&file_path_c, flags, perm); | 1637 | return openZ(&file_path_c, flags, perm); |
| ... | @@ -1642,10 +1639,9 @@ pub fn open(file_path: []const u8, flags: u32, perm: mode_t) OpenError!fd_t { | ... | @@ -1642,10 +1639,9 @@ pub fn open(file_path: []const u8, flags: u32, perm: mode_t) OpenError!fd_t { |
| 1642 | 1639 | ||
| 1643 | /// Open and possibly create a file. Keeps trying if it gets interrupted. | 1640 | /// Open and possibly create a file. Keeps trying if it gets interrupted. |
| 1644 | /// See also `open`. | 1641 | /// See also `open`. |
| 1645 | pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: mode_t) OpenError!fd_t { | 1642 | pub fn openZ(file_path: [*:0]const u8, flags: O, perm: mode_t) OpenError!fd_t { |
| 1646 | if (builtin.os.tag == .windows) { | 1643 | if (builtin.os.tag == .windows) { |
| 1647 | const file_path_w = try windows.cStrToPrefixedFileW(null, file_path); | 1644 | @compileError("Windows does not support POSIX; use Windows-specific API or cross-platform std.fs API"); |
| 1648 | return openW(file_path_w.span(), flags, perm); | ||
| 1649 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 1645 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1650 | return open(mem.sliceTo(file_path, 0), flags, perm); | 1646 | return open(mem.sliceTo(file_path, 0), flags, perm); |
| 1651 | } | 1647 | } |
| ... | @@ -1681,64 +1677,15 @@ pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: mode_t) OpenError!fd_t | ... | @@ -1681,64 +1677,15 @@ pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: mode_t) OpenError!fd_t |
| 1681 | } | 1677 | } |
| 1682 | } | 1678 | } |
| 1683 | 1679 | ||
| 1684 | fn openOptionsFromFlagsWindows(flags: u32) windows.OpenFileOptions { | ||
| 1685 | const w = windows; | ||
| 1686 | |||
| 1687 | var access_mask: w.ULONG = w.READ_CONTROL | w.FILE_WRITE_ATTRIBUTES | w.SYNCHRONIZE; | ||
| 1688 | if (flags & O.RDWR != 0) { | ||
| 1689 | access_mask |= w.GENERIC_READ | w.GENERIC_WRITE; | ||
| 1690 | } else if (flags & O.WRONLY != 0) { | ||
| 1691 | access_mask |= w.GENERIC_WRITE; | ||
| 1692 | } else { | ||
| 1693 | access_mask |= w.GENERIC_READ | w.GENERIC_WRITE; | ||
| 1694 | } | ||
| 1695 | |||
| 1696 | const filter: windows.OpenFileOptions.Filter = if (flags & O.DIRECTORY != 0) .dir_only else .file_only; | ||
| 1697 | const follow_symlinks: bool = flags & O.NOFOLLOW == 0; | ||
| 1698 | |||
| 1699 | const creation: w.ULONG = blk: { | ||
| 1700 | if (flags & O.CREAT != 0) { | ||
| 1701 | if (flags & O.EXCL != 0) { | ||
| 1702 | break :blk w.FILE_CREATE; | ||
| 1703 | } | ||
| 1704 | } | ||
| 1705 | break :blk w.FILE_OPEN; | ||
| 1706 | }; | ||
| 1707 | |||
| 1708 | return .{ | ||
| 1709 | .access_mask = access_mask, | ||
| 1710 | .creation = creation, | ||
| 1711 | .filter = filter, | ||
| 1712 | .follow_symlinks = follow_symlinks, | ||
| 1713 | }; | ||
| 1714 | } | ||
| 1715 | |||
| 1716 | /// Windows-only. The path parameter is | ||
| 1717 | /// [WTF-16](https://simonsapin.github.io/wtf-8/#potentially-ill-formed-utf-16) encoded. | ||
| 1718 | /// Translates the POSIX open API call to a Windows API call. | ||
| 1719 | /// TODO currently, this function does not handle all flag combinations | ||
| 1720 | /// or makes use of perm argument. | ||
| 1721 | pub fn openW(file_path_w: []const u16, flags: u32, perm: mode_t) OpenError!fd_t { | ||
| 1722 | _ = perm; | ||
| 1723 | var options = openOptionsFromFlagsWindows(flags); | ||
| 1724 | options.dir = std.fs.cwd().fd; | ||
| 1725 | return windows.OpenFile(file_path_w, options) catch |err| switch (err) { | ||
| 1726 | error.WouldBlock => unreachable, | ||
| 1727 | error.PipeBusy => unreachable, | ||
| 1728 | else => |e| return e, | ||
| 1729 | }; | ||
| 1730 | } | ||
| 1731 | |||
| 1732 | /// Open and possibly create a file. Keeps trying if it gets interrupted. | 1680 | /// Open and possibly create a file. Keeps trying if it gets interrupted. |
| 1733 | /// `file_path` is relative to the open directory handle `dir_fd`. | 1681 | /// `file_path` is relative to the open directory handle `dir_fd`. |
| 1734 | /// See also `openatZ`. | 1682 | /// See also `openatZ`. |
| 1735 | pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) OpenError!fd_t { | 1683 | pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: O, mode: mode_t) OpenError!fd_t { |
| 1736 | if (builtin.os.tag == .windows) { | 1684 | if (builtin.os.tag == .windows) { |
| 1737 | const file_path_w = try windows.sliceToPrefixedFileW(dir_fd, file_path); | 1685 | @compileError("Windows does not support POSIX; use Windows-specific API or cross-platform std.fs API"); |
| 1738 | return openatW(dir_fd, file_path_w.span(), flags, mode); | ||
| 1739 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 1686 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1740 | // `mode` is ignored on WASI, which does not support unix-style file permissions | 1687 | // `mode` is ignored on WASI, which does not support unix-style file permissions |
| 1741 | const opts = try openOptionsFromFlagsWasi(dir_fd, flags); | 1688 | const opts = try openOptionsFromFlagsWasi(flags); |
| 1742 | const fd = try openatWasi( | 1689 | const fd = try openatWasi( |
| 1743 | dir_fd, | 1690 | dir_fd, |
| 1744 | file_path, | 1691 | file_path, |
| ... | @@ -1750,8 +1697,8 @@ pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) Ope | ... | @@ -1750,8 +1697,8 @@ pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) Ope |
| 1750 | ); | 1697 | ); |
| 1751 | errdefer close(fd); | 1698 | errdefer close(fd); |
| 1752 | 1699 | ||
| 1753 | if (flags & O.WRONLY != 0) { | 1700 | if (flags.write) { |
| 1754 | const info = try fstat(fd); | 1701 | const info = try fstat_wasi(fd); |
| 1755 | if (info.filetype == .DIRECTORY) | 1702 | if (info.filetype == .DIRECTORY) |
| 1756 | return error.IsDir; | 1703 | return error.IsDir; |
| 1757 | } | 1704 | } |
| ... | @@ -1762,6 +1709,37 @@ pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) Ope | ... | @@ -1762,6 +1709,37 @@ pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) Ope |
| 1762 | return openatZ(dir_fd, &file_path_c, flags, mode); | 1709 | return openatZ(dir_fd, &file_path_c, flags, mode); |
| 1763 | } | 1710 | } |
| 1764 | 1711 | ||
| 1712 | pub const CommonOpenFlags = packed struct { | ||
| 1713 | ACCMODE: ACCMODE = .RDONLY, | ||
| 1714 | CREAT: bool = false, | ||
| 1715 | EXCL: bool = false, | ||
| 1716 | LARGEFILE: bool = false, | ||
| 1717 | DIRECTORY: bool = false, | ||
| 1718 | CLOEXEC: bool = false, | ||
| 1719 | NONBLOCK: bool = false, | ||
| 1720 | |||
| 1721 | pub fn lower(cof: CommonOpenFlags) O { | ||
| 1722 | if (builtin.os.tag == .wasi) return .{ | ||
| 1723 | .read = cof.ACCMODE != .WRONLY, | ||
| 1724 | .write = cof.ACCMODE != .RDONLY, | ||
| 1725 | .CREAT = cof.CREAT, | ||
| 1726 | .EXCL = cof.EXCL, | ||
| 1727 | .DIRECTORY = cof.DIRECTORY, | ||
| 1728 | .NONBLOCK = cof.NONBLOCK, | ||
| 1729 | }; | ||
| 1730 | var result: O = .{ | ||
| 1731 | .ACCMODE = cof.ACCMODE, | ||
| 1732 | .CREAT = cof.CREAT, | ||
| 1733 | .EXCL = cof.EXCL, | ||
| 1734 | .DIRECTORY = cof.DIRECTORY, | ||
| 1735 | .NONBLOCK = cof.NONBLOCK, | ||
| 1736 | .CLOEXEC = cof.CLOEXEC, | ||
| 1737 | }; | ||
| 1738 | if (@hasField(O, "LARGEFILE")) result.LARGEFILE = cof.LARGEFILE; | ||
| 1739 | return result; | ||
| 1740 | } | ||
| 1741 | }; | ||
| 1742 | |||
| 1765 | /// A struct to contain all lookup/rights flags accepted by `wasi.path_open` | 1743 | /// A struct to contain all lookup/rights flags accepted by `wasi.path_open` |
| 1766 | const WasiOpenOptions = struct { | 1744 | const WasiOpenOptions = struct { |
| 1767 | oflags: wasi.oflags_t, | 1745 | oflags: wasi.oflags_t, |
| ... | @@ -1772,42 +1750,38 @@ const WasiOpenOptions = struct { | ... | @@ -1772,42 +1750,38 @@ const WasiOpenOptions = struct { |
| 1772 | }; | 1750 | }; |
| 1773 | 1751 | ||
| 1774 | /// Compute rights + flags corresponding to the provided POSIX access mode. | 1752 | /// Compute rights + flags corresponding to the provided POSIX access mode. |
| 1775 | fn openOptionsFromFlagsWasi(fd: fd_t, oflag: u32) OpenError!WasiOpenOptions { | 1753 | fn openOptionsFromFlagsWasi(oflag: O) OpenError!WasiOpenOptions { |
| 1776 | const w = std.os.wasi; | 1754 | const w = std.os.wasi; |
| 1777 | 1755 | ||
| 1778 | // First, discover the rights that we can derive from `fd` | ||
| 1779 | var fsb_cur: wasi.fdstat_t = undefined; | ||
| 1780 | _ = switch (w.fd_fdstat_get(fd, &fsb_cur)) { | ||
| 1781 | .SUCCESS => .{}, | ||
| 1782 | .BADF => return error.InvalidHandle, | ||
| 1783 | else => |err| return unexpectedErrno(err), | ||
| 1784 | }; | ||
| 1785 | |||
| 1786 | // Next, calculate the read/write rights to request, depending on the | 1756 | // Next, calculate the read/write rights to request, depending on the |
| 1787 | // provided POSIX access mode | 1757 | // provided POSIX access mode |
| 1788 | var rights: w.rights_t = 0; | 1758 | var rights: w.rights_t = .{}; |
| 1789 | if (oflag & O.RDONLY != 0) { | 1759 | if (oflag.read) { |
| 1790 | rights |= w.RIGHT.FD_READ | w.RIGHT.FD_READDIR; | 1760 | rights.FD_READ = true; |
| 1761 | rights.FD_READDIR = true; | ||
| 1791 | } | 1762 | } |
| 1792 | if (oflag & O.WRONLY != 0) { | 1763 | if (oflag.write) { |
| 1793 | rights |= w.RIGHT.FD_DATASYNC | w.RIGHT.FD_WRITE | | 1764 | rights.FD_DATASYNC = true; |
| 1794 | w.RIGHT.FD_ALLOCATE | w.RIGHT.FD_FILESTAT_SET_SIZE; | 1765 | rights.FD_WRITE = true; |
| 1766 | rights.FD_ALLOCATE = true; | ||
| 1767 | rights.FD_FILESTAT_SET_SIZE = true; | ||
| 1795 | } | 1768 | } |
| 1796 | 1769 | ||
| 1797 | // Request all other rights unconditionally | 1770 | // https://github.com/ziglang/zig/issues/18882 |
| 1798 | rights |= ~(w.RIGHT.FD_DATASYNC | w.RIGHT.FD_READ | | 1771 | const flag_bits: u32 = @bitCast(oflag); |
| 1799 | w.RIGHT.FD_WRITE | w.RIGHT.FD_ALLOCATE | | 1772 | const oflags_int: u16 = @as(u12, @truncate(flag_bits >> 12)); |
| 1800 | w.RIGHT.FD_READDIR | w.RIGHT.FD_FILESTAT_SET_SIZE); | 1773 | const fs_flags_int: u16 = @as(u12, @truncate(flag_bits)); |
| 1801 | |||
| 1802 | // But only take rights that we can actually inherit | ||
| 1803 | rights &= fsb_cur.fs_rights_inheriting; | ||
| 1804 | 1774 | ||
| 1805 | return WasiOpenOptions{ | 1775 | return .{ |
| 1806 | .oflags = @as(w.oflags_t, @truncate((oflag >> 12))) & 0xfff, | 1776 | // https://github.com/ziglang/zig/issues/18882 |
| 1807 | .lookup_flags = if (oflag & O.NOFOLLOW == 0) w.LOOKUP_SYMLINK_FOLLOW else 0, | 1777 | .oflags = @bitCast(oflags_int), |
| 1778 | .lookup_flags = .{ | ||
| 1779 | .SYMLINK_FOLLOW = !oflag.NOFOLLOW, | ||
| 1780 | }, | ||
| 1808 | .fs_rights_base = rights, | 1781 | .fs_rights_base = rights, |
| 1809 | .fs_rights_inheriting = fsb_cur.fs_rights_inheriting, | 1782 | .fs_rights_inheriting = rights, |
| 1810 | .fs_flags = @as(w.fdflags_t, @truncate(oflag & 0xfff)), | 1783 | // https://github.com/ziglang/zig/issues/18882 |
| 1784 | .fs_flags = @bitCast(fs_flags_int), | ||
| 1811 | }; | 1785 | }; |
| 1812 | } | 1786 | } |
| 1813 | 1787 | ||
| ... | @@ -1815,11 +1789,11 @@ fn openOptionsFromFlagsWasi(fd: fd_t, oflag: u32) OpenError!WasiOpenOptions { | ... | @@ -1815,11 +1789,11 @@ fn openOptionsFromFlagsWasi(fd: fd_t, oflag: u32) OpenError!WasiOpenOptions { |
| 1815 | pub fn openatWasi( | 1789 | pub fn openatWasi( |
| 1816 | dir_fd: fd_t, | 1790 | dir_fd: fd_t, |
| 1817 | file_path: []const u8, | 1791 | file_path: []const u8, |
| 1818 | lookup_flags: lookupflags_t, | 1792 | lookup_flags: wasi.lookupflags_t, |
| 1819 | oflags: oflags_t, | 1793 | oflags: wasi.oflags_t, |
| 1820 | fdflags: fdflags_t, | 1794 | fdflags: wasi.fdflags_t, |
| 1821 | base: rights_t, | 1795 | base: wasi.rights_t, |
| 1822 | inheriting: rights_t, | 1796 | inheriting: wasi.rights_t, |
| 1823 | ) OpenError!fd_t { | 1797 | ) OpenError!fd_t { |
| 1824 | while (true) { | 1798 | while (true) { |
| 1825 | var fd: fd_t = undefined; | 1799 | var fd: fd_t = undefined; |
| ... | @@ -1829,6 +1803,7 @@ pub fn openatWasi( | ... | @@ -1829,6 +1803,7 @@ pub fn openatWasi( |
| 1829 | 1803 | ||
| 1830 | .FAULT => unreachable, | 1804 | .FAULT => unreachable, |
| 1831 | .INVAL => unreachable, | 1805 | .INVAL => unreachable, |
| 1806 | .BADF => unreachable, | ||
| 1832 | .ACCES => return error.AccessDenied, | 1807 | .ACCES => return error.AccessDenied, |
| 1833 | .FBIG => return error.FileTooBig, | 1808 | .FBIG => return error.FileTooBig, |
| 1834 | .OVERFLOW => return error.FileTooBig, | 1809 | .OVERFLOW => return error.FileTooBig, |
| ... | @@ -1854,10 +1829,9 @@ pub fn openatWasi( | ... | @@ -1854,10 +1829,9 @@ pub fn openatWasi( |
| 1854 | /// Open and possibly create a file. Keeps trying if it gets interrupted. | 1829 | /// Open and possibly create a file. Keeps trying if it gets interrupted. |
| 1855 | /// `file_path` is relative to the open directory handle `dir_fd`. | 1830 | /// `file_path` is relative to the open directory handle `dir_fd`. |
| 1856 | /// See also `openat`. | 1831 | /// See also `openat`. |
| 1857 | pub fn openatZ(dir_fd: fd_t, file_path: [*:0]const u8, flags: u32, mode: mode_t) OpenError!fd_t { | 1832 | pub fn openatZ(dir_fd: fd_t, file_path: [*:0]const u8, flags: O, mode: mode_t) OpenError!fd_t { |
| 1858 | if (builtin.os.tag == .windows) { | 1833 | if (builtin.os.tag == .windows) { |
| 1859 | const file_path_w = try windows.cStrToPrefixedFileW(dir_fd, file_path); | 1834 | @compileError("Windows does not support POSIX; use Windows-specific API or cross-platform std.fs API"); |
| 1860 | return openatW(dir_fd, file_path_w.span(), flags, mode); | ||
| 1861 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 1835 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 1862 | return openat(dir_fd, mem.sliceTo(file_path, 0), flags, mode); | 1836 | return openat(dir_fd, mem.sliceTo(file_path, 0), flags, mode); |
| 1863 | } | 1837 | } |
| ... | @@ -1897,21 +1871,6 @@ pub fn openatZ(dir_fd: fd_t, file_path: [*:0]const u8, flags: u32, mode: mode_t) | ... | @@ -1897,21 +1871,6 @@ pub fn openatZ(dir_fd: fd_t, file_path: [*:0]const u8, flags: u32, mode: mode_t) |
| 1897 | } | 1871 | } |
| 1898 | } | 1872 | } |
| 1899 | 1873 | ||
| 1900 | /// Windows-only. Similar to `openat` but with pathname argument null-terminated | ||
| 1901 | /// WTF16 encoded. | ||
| 1902 | /// TODO currently, this function does not handle all flag combinations | ||
| 1903 | /// or makes use of perm argument. | ||
| 1904 | pub fn openatW(dir_fd: fd_t, file_path_w: []const u16, flags: u32, mode: mode_t) OpenError!fd_t { | ||
| 1905 | _ = mode; | ||
| 1906 | var options = openOptionsFromFlagsWindows(flags); | ||
| 1907 | options.dir = dir_fd; | ||
| 1908 | return windows.OpenFile(file_path_w, options) catch |err| switch (err) { | ||
| 1909 | error.WouldBlock => unreachable, | ||
| 1910 | error.PipeBusy => unreachable, | ||
| 1911 | else => |e| return e, | ||
| 1912 | }; | ||
| 1913 | } | ||
| 1914 | |||
| 1915 | pub fn dup(old_fd: fd_t) !fd_t { | 1874 | pub fn dup(old_fd: fd_t) !fd_t { |
| 1916 | const rc = system.dup(old_fd); | 1875 | const rc = system.dup(old_fd); |
| 1917 | return switch (errno(rc)) { | 1876 | return switch (errno(rc)) { |
| ... | @@ -2403,42 +2362,43 @@ pub fn linkat( | ... | @@ -2403,42 +2362,43 @@ pub fn linkat( |
| 2403 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 2362 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 2404 | const old: RelativePathWasi = .{ .dir_fd = olddir, .relative_path = oldpath }; | 2363 | const old: RelativePathWasi = .{ .dir_fd = olddir, .relative_path = oldpath }; |
| 2405 | const new: RelativePathWasi = .{ .dir_fd = newdir, .relative_path = newpath }; | 2364 | const new: RelativePathWasi = .{ .dir_fd = newdir, .relative_path = newpath }; |
| 2406 | return linkatWasi(old, new, flags); | 2365 | const old_flags: wasi.lookupflags_t = .{ |
| 2366 | .SYMLINK_FOLLOW = (flags & AT.SYMLINK_FOLLOW) != 0, | ||
| 2367 | }; | ||
| 2368 | switch (wasi.path_link( | ||
| 2369 | old.dir_fd, | ||
| 2370 | old_flags, | ||
| 2371 | old.relative_path.ptr, | ||
| 2372 | old.relative_path.len, | ||
| 2373 | new.dir_fd, | ||
| 2374 | new.relative_path.ptr, | ||
| 2375 | new.relative_path.len, | ||
| 2376 | )) { | ||
| 2377 | .SUCCESS => return, | ||
| 2378 | .ACCES => return error.AccessDenied, | ||
| 2379 | .DQUOT => return error.DiskQuota, | ||
| 2380 | .EXIST => return error.PathAlreadyExists, | ||
| 2381 | .FAULT => unreachable, | ||
| 2382 | .IO => return error.FileSystem, | ||
| 2383 | .LOOP => return error.SymLinkLoop, | ||
| 2384 | .MLINK => return error.LinkQuotaExceeded, | ||
| 2385 | .NAMETOOLONG => return error.NameTooLong, | ||
| 2386 | .NOENT => return error.FileNotFound, | ||
| 2387 | .NOMEM => return error.SystemResources, | ||
| 2388 | .NOSPC => return error.NoSpaceLeft, | ||
| 2389 | .NOTDIR => return error.NotDir, | ||
| 2390 | .PERM => return error.AccessDenied, | ||
| 2391 | .ROFS => return error.ReadOnlyFileSystem, | ||
| 2392 | .XDEV => return error.NotSameFileSystem, | ||
| 2393 | .INVAL => unreachable, | ||
| 2394 | else => |err| return unexpectedErrno(err), | ||
| 2395 | } | ||
| 2407 | } | 2396 | } |
| 2408 | const old = try toPosixPath(oldpath); | 2397 | const old = try toPosixPath(oldpath); |
| 2409 | const new = try toPosixPath(newpath); | 2398 | const new = try toPosixPath(newpath); |
| 2410 | return try linkatZ(olddir, &old, newdir, &new, flags); | 2399 | return try linkatZ(olddir, &old, newdir, &new, flags); |
| 2411 | } | 2400 | } |
| 2412 | 2401 | ||
| 2413 | /// WASI-only. The same as `linkat` but targeting WASI. | ||
| 2414 | /// See also `linkat`. | ||
| 2415 | pub fn linkatWasi(old: RelativePathWasi, new: RelativePathWasi, flags: i32) LinkatError!void { | ||
| 2416 | var old_flags: wasi.lookupflags_t = 0; | ||
| 2417 | // TODO: Why is this not defined in wasi-libc? | ||
| 2418 | if (flags & linux.AT.SYMLINK_FOLLOW != 0) old_flags |= wasi.LOOKUP_SYMLINK_FOLLOW; | ||
| 2419 | |||
| 2420 | switch (wasi.path_link(old.dir_fd, old_flags, old.relative_path.ptr, old.relative_path.len, new.dir_fd, new.relative_path.ptr, new.relative_path.len)) { | ||
| 2421 | .SUCCESS => return, | ||
| 2422 | .ACCES => return error.AccessDenied, | ||
| 2423 | .DQUOT => return error.DiskQuota, | ||
| 2424 | .EXIST => return error.PathAlreadyExists, | ||
| 2425 | .FAULT => unreachable, | ||
| 2426 | .IO => return error.FileSystem, | ||
| 2427 | .LOOP => return error.SymLinkLoop, | ||
| 2428 | .MLINK => return error.LinkQuotaExceeded, | ||
| 2429 | .NAMETOOLONG => return error.NameTooLong, | ||
| 2430 | .NOENT => return error.FileNotFound, | ||
| 2431 | .NOMEM => return error.SystemResources, | ||
| 2432 | .NOSPC => return error.NoSpaceLeft, | ||
| 2433 | .NOTDIR => return error.NotDir, | ||
| 2434 | .PERM => return error.AccessDenied, | ||
| 2435 | .ROFS => return error.ReadOnlyFileSystem, | ||
| 2436 | .XDEV => return error.NotSameFileSystem, | ||
| 2437 | .INVAL => unreachable, | ||
| 2438 | else => |err| return unexpectedErrno(err), | ||
| 2439 | } | ||
| 2440 | } | ||
| 2441 | |||
| 2442 | pub const UnlinkError = error{ | 2402 | pub const UnlinkError = error{ |
| 2443 | FileNotFound, | 2403 | FileNotFound, |
| 2444 | 2404 | ||
| ... | @@ -3404,20 +3364,16 @@ pub fn isatty(handle: fd_t) bool { | ... | @@ -3404,20 +3364,16 @@ pub fn isatty(handle: fd_t) bool { |
| 3404 | return system.isatty(handle) != 0; | 3364 | return system.isatty(handle) != 0; |
| 3405 | } | 3365 | } |
| 3406 | if (builtin.os.tag == .wasi) { | 3366 | if (builtin.os.tag == .wasi) { |
| 3407 | var statbuf: fdstat_t = undefined; | 3367 | var statbuf: wasi.fdstat_t = undefined; |
| 3408 | const err = system.fd_fdstat_get(handle, &statbuf); | 3368 | const err = wasi.fd_fdstat_get(handle, &statbuf); |
| 3409 | if (err != .SUCCESS) { | 3369 | if (err != .SUCCESS) |
| 3410 | // errno = err; | ||
| 3411 | return false; | 3370 | return false; |
| 3412 | } | ||
| 3413 | 3371 | ||
| 3414 | // A tty is a character device that we can't seek or tell on. | 3372 | // A tty is a character device that we can't seek or tell on. |
| 3415 | if (statbuf.fs_filetype != .CHARACTER_DEVICE or | 3373 | if (statbuf.fs_filetype != .CHARACTER_DEVICE) |
| 3416 | (statbuf.fs_rights_base & (RIGHT.FD_SEEK | RIGHT.FD_TELL)) != 0) | 3374 | return false; |
| 3417 | { | 3375 | if (statbuf.fs_rights_base.FD_SEEK or statbuf.fs_rights_base.FD_TELL) |
| 3418 | // errno = ENOTTY; | ||
| 3419 | return false; | 3376 | return false; |
| 3420 | } | ||
| 3421 | 3377 | ||
| 3422 | return true; | 3378 | return true; |
| 3423 | } | 3379 | } |
| ... | @@ -3838,11 +3794,11 @@ pub fn accept( | ... | @@ -3838,11 +3794,11 @@ pub fn accept( |
| 3838 | /// will return a value greater than was supplied to the call. | 3794 | /// will return a value greater than was supplied to the call. |
| 3839 | addr_size: ?*socklen_t, | 3795 | addr_size: ?*socklen_t, |
| 3840 | /// The following values can be bitwise ORed in flags to obtain different behavior: | 3796 | /// The following values can be bitwise ORed in flags to obtain different behavior: |
| 3841 | /// * `SOCK.NONBLOCK` - Set the `O.NONBLOCK` file status flag on the open file description (see `open`) | 3797 | /// * `SOCK.NONBLOCK` - Set the `NONBLOCK` file status flag on the open file description (see `open`) |
| 3842 | /// referred to by the new file descriptor. Using this flag saves extra calls to `fcntl` to achieve | 3798 | /// referred to by the new file descriptor. Using this flag saves extra calls to `fcntl` to achieve |
| 3843 | /// the same result. | 3799 | /// the same result. |
| 3844 | /// * `SOCK.CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor. See the | 3800 | /// * `SOCK.CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor. See the |
| 3845 | /// description of the `O.CLOEXEC` flag in `open` for reasons why this may be useful. | 3801 | /// description of the `CLOEXEC` flag in `open` for reasons why this may be useful. |
| 3846 | flags: u32, | 3802 | flags: u32, |
| 3847 | ) AcceptError!socket_t { | 3803 | ) AcceptError!socket_t { |
| 3848 | const have_accept4 = comptime !(builtin.target.isDarwin() or builtin.os.tag == .windows); | 3804 | const have_accept4 = comptime !(builtin.target.isDarwin() or builtin.os.tag == .windows); |
| ... | @@ -4278,16 +4234,7 @@ pub const FStatError = error{ | ... | @@ -4278,16 +4234,7 @@ pub const FStatError = error{ |
| 4278 | /// Return information about a file descriptor. | 4234 | /// Return information about a file descriptor. |
| 4279 | pub fn fstat(fd: fd_t) FStatError!Stat { | 4235 | pub fn fstat(fd: fd_t) FStatError!Stat { |
| 4280 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 4236 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 4281 | var stat: wasi.filestat_t = undefined; | 4237 | return Stat.fromFilestat(try fstat_wasi(fd)); |
| 4282 | switch (wasi.fd_filestat_get(fd, &stat)) { | ||
| 4283 | .SUCCESS => return Stat.fromFilestat(stat), | ||
| 4284 | .INVAL => unreachable, | ||
| 4285 | .BADF => unreachable, // Always a race condition. | ||
| 4286 | .NOMEM => return error.SystemResources, | ||
| 4287 | .ACCES => return error.AccessDenied, | ||
| 4288 | .NOTCAPABLE => return error.AccessDenied, | ||
| 4289 | else => |err| return unexpectedErrno(err), | ||
| 4290 | } | ||
| 4291 | } | 4238 | } |
| 4292 | if (builtin.os.tag == .windows) { | 4239 | if (builtin.os.tag == .windows) { |
| 4293 | @compileError("fstat is not yet implemented on Windows"); | 4240 | @compileError("fstat is not yet implemented on Windows"); |
| ... | @@ -4306,15 +4253,30 @@ pub fn fstat(fd: fd_t) FStatError!Stat { | ... | @@ -4306,15 +4253,30 @@ pub fn fstat(fd: fd_t) FStatError!Stat { |
| 4306 | } | 4253 | } |
| 4307 | } | 4254 | } |
| 4308 | 4255 | ||
| 4256 | pub fn fstat_wasi(fd: fd_t) FStatError!wasi.filestat_t { | ||
| 4257 | var stat: wasi.filestat_t = undefined; | ||
| 4258 | switch (wasi.fd_filestat_get(fd, &stat)) { | ||
| 4259 | .SUCCESS => return stat, | ||
| 4260 | .INVAL => unreachable, | ||
| 4261 | .BADF => unreachable, // Always a race condition. | ||
| 4262 | .NOMEM => return error.SystemResources, | ||
| 4263 | .ACCES => return error.AccessDenied, | ||
| 4264 | .NOTCAPABLE => return error.AccessDenied, | ||
| 4265 | else => |err| return unexpectedErrno(err), | ||
| 4266 | } | ||
| 4267 | } | ||
| 4268 | |||
| 4309 | pub const FStatAtError = FStatError || error{ NameTooLong, FileNotFound, SymLinkLoop }; | 4269 | pub const FStatAtError = FStatError || error{ NameTooLong, FileNotFound, SymLinkLoop }; |
| 4310 | 4270 | ||
| 4311 | /// Similar to `fstat`, but returns stat of a resource pointed to by `pathname` | 4271 | /// Similar to `fstat`, but returns stat of a resource pointed to by `pathname` |
| 4312 | /// which is relative to `dirfd` handle. | 4272 | /// which is relative to `dirfd` handle. |
| 4313 | /// See also `fstatatZ` and `fstatatWasi`. | 4273 | /// See also `fstatatZ` and `fstatat_wasi`. |
| 4314 | pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat { | 4274 | pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat { |
| 4315 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 4275 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 4316 | const wasi_flags = if (flags & linux.AT.SYMLINK_NOFOLLOW == 0) wasi.LOOKUP_SYMLINK_FOLLOW else 0; | 4276 | const filestat = try fstatat_wasi(dirfd, pathname, .{ |
| 4317 | return fstatatWasi(dirfd, pathname, wasi_flags); | 4277 | .SYMLINK_FOLLOW = (flags & AT.SYMLINK_NOFOLLOW) == 0, |
| 4278 | }); | ||
| 4279 | return Stat.fromFilestat(filestat); | ||
| 4318 | } else if (builtin.os.tag == .windows) { | 4280 | } else if (builtin.os.tag == .windows) { |
| 4319 | @compileError("fstatat is not yet implemented on Windows"); | 4281 | @compileError("fstatat is not yet implemented on Windows"); |
| 4320 | } else { | 4282 | } else { |
| ... | @@ -4325,10 +4287,10 @@ pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat | ... | @@ -4325,10 +4287,10 @@ pub fn fstatat(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat |
| 4325 | 4287 | ||
| 4326 | /// WASI-only. Same as `fstatat` but targeting WASI. | 4288 | /// WASI-only. Same as `fstatat` but targeting WASI. |
| 4327 | /// See also `fstatat`. | 4289 | /// See also `fstatat`. |
| 4328 | pub fn fstatatWasi(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!Stat { | 4290 | pub fn fstatat_wasi(dirfd: fd_t, pathname: []const u8, flags: wasi.lookupflags_t) FStatAtError!wasi.filestat_t { |
| 4329 | var stat: wasi.filestat_t = undefined; | 4291 | var stat: wasi.filestat_t = undefined; |
| 4330 | switch (wasi.path_filestat_get(dirfd, flags, pathname.ptr, pathname.len, &stat)) { | 4292 | switch (wasi.path_filestat_get(dirfd, flags, pathname.ptr, pathname.len, &stat)) { |
| 4331 | .SUCCESS => return Stat.fromFilestat(stat), | 4293 | .SUCCESS => return stat, |
| 4332 | .INVAL => unreachable, | 4294 | .INVAL => unreachable, |
| 4333 | .BADF => unreachable, // Always a race condition. | 4295 | .BADF => unreachable, // Always a race condition. |
| 4334 | .NOMEM => return error.SystemResources, | 4296 | .NOMEM => return error.SystemResources, |
| ... | @@ -4346,7 +4308,10 @@ pub fn fstatatWasi(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!S | ... | @@ -4346,7 +4308,10 @@ pub fn fstatatWasi(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!S |
| 4346 | /// See also `fstatat`. | 4308 | /// See also `fstatat`. |
| 4347 | pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!Stat { | 4309 | pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!Stat { |
| 4348 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 4310 | if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 4349 | return fstatatWasi(dirfd, mem.sliceTo(pathname), flags); | 4311 | const filestat = try fstatat_wasi(dirfd, mem.sliceTo(pathname, 0), .{ |
| 4312 | .SYMLINK_FOLLOW = (flags & AT.SYMLINK_NOFOLLOW) == 0, | ||
| 4313 | }); | ||
| 4314 | return Stat.fromFilestat(filestat); | ||
| 4350 | } | 4315 | } |
| 4351 | 4316 | ||
| 4352 | const fstatat_sym = if (lfs64_abi) system.fstatat64 else system.fstatat; | 4317 | const fstatat_sym = if (lfs64_abi) system.fstatat64 else system.fstatat; |
| ... | @@ -4627,7 +4592,7 @@ pub const MMapError = error{ | ... | @@ -4627,7 +4592,7 @@ pub const MMapError = error{ |
| 4627 | 4592 | ||
| 4628 | /// A file descriptor refers to a non-regular file. Or a file mapping was requested, | 4593 | /// A file descriptor refers to a non-regular file. Or a file mapping was requested, |
| 4629 | /// but the file descriptor is not open for reading. Or `MAP.SHARED` was requested | 4594 | /// but the file descriptor is not open for reading. Or `MAP.SHARED` was requested |
| 4630 | /// and `PROT_WRITE` is set, but the file descriptor is not open in `O.RDWR` mode. | 4595 | /// and `PROT_WRITE` is set, but the file descriptor is not open in `RDWR` mode. |
| 4631 | /// Or `PROT_WRITE` is set, but the file is append-only. | 4596 | /// Or `PROT_WRITE` is set, but the file is append-only. |
| 4632 | AccessDenied, | 4597 | AccessDenied, |
| 4633 | 4598 | ||
| ... | @@ -4795,10 +4760,12 @@ pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessErr | ... | @@ -4795,10 +4760,12 @@ pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessErr |
| 4795 | const path_w = try windows.sliceToPrefixedFileW(dirfd, path); | 4760 | const path_w = try windows.sliceToPrefixedFileW(dirfd, path); |
| 4796 | return faccessatW(dirfd, path_w.span().ptr, mode, flags); | 4761 | return faccessatW(dirfd, path_w.span().ptr, mode, flags); |
| 4797 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { | 4762 | } else if (builtin.os.tag == .wasi and !builtin.link_libc) { |
| 4798 | const resolved = RelativePathWasi{ .dir_fd = dirfd, .relative_path = path }; | 4763 | const resolved: RelativePathWasi = .{ .dir_fd = dirfd, .relative_path = path }; |
| 4799 | 4764 | ||
| 4800 | const file = blk: { | 4765 | const st = blk: { |
| 4801 | break :blk fstatat(dirfd, path, flags); | 4766 | break :blk fstatat_wasi(dirfd, path, .{ |
| 4767 | .SYMLINK_FOLLOW = (flags & AT.SYMLINK_NOFOLLOW) == 0, | ||
| 4768 | }); | ||
| 4802 | } catch |err| switch (err) { | 4769 | } catch |err| switch (err) { |
| 4803 | error.AccessDenied => return error.PermissionDenied, | 4770 | error.AccessDenied => return error.PermissionDenied, |
| 4804 | else => |e| return e, | 4771 | else => |e| return e, |
| ... | @@ -4810,19 +4777,23 @@ pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessErr | ... | @@ -4810,19 +4777,23 @@ pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessErr |
| 4810 | return error.PermissionDenied; | 4777 | return error.PermissionDenied; |
| 4811 | } | 4778 | } |
| 4812 | 4779 | ||
| 4813 | var rights: wasi.rights_t = 0; | 4780 | var rights: wasi.rights_t = .{}; |
| 4814 | if (mode & R_OK != 0) { | 4781 | if (mode & R_OK != 0) { |
| 4815 | rights |= if (file.filetype == .DIRECTORY) | 4782 | if (st.filetype == .DIRECTORY) { |
| 4816 | wasi.RIGHT.FD_READDIR | 4783 | rights.FD_READDIR = true; |
| 4817 | else | 4784 | } else { |
| 4818 | wasi.RIGHT.FD_READ; | 4785 | rights.FD_READ = true; |
| 4786 | } | ||
| 4819 | } | 4787 | } |
| 4820 | if (mode & W_OK != 0) { | 4788 | if (mode & W_OK != 0) { |
| 4821 | rights |= wasi.RIGHT.FD_WRITE; | 4789 | rights.FD_WRITE = true; |
| 4822 | } | 4790 | } |
| 4823 | // No validation for X_OK | 4791 | // No validation for X_OK |
| 4824 | 4792 | ||
| 4825 | if ((rights & directory.fs_rights_inheriting) != rights) { | 4793 | // https://github.com/ziglang/zig/issues/18882 |
| 4794 | const rights_int: u64 = @bitCast(rights); | ||
| 4795 | const inheriting_int: u64 = @bitCast(directory.fs_rights_inheriting); | ||
| 4796 | if ((rights_int & inheriting_int) != rights_int) { | ||
| 4826 | return error.PermissionDenied; | 4797 | return error.PermissionDenied; |
| 4827 | } | 4798 | } |
| 4828 | } | 4799 | } |
| ... | @@ -4915,7 +4886,7 @@ pub fn pipe() PipeError![2]fd_t { | ... | @@ -4915,7 +4886,7 @@ pub fn pipe() PipeError![2]fd_t { |
| 4915 | } | 4886 | } |
| 4916 | } | 4887 | } |
| 4917 | 4888 | ||
| 4918 | pub fn pipe2(flags: u32) PipeError![2]fd_t { | 4889 | pub fn pipe2(flags: O) PipeError![2]fd_t { |
| 4919 | if (@hasDecl(system, "pipe2")) { | 4890 | if (@hasDecl(system, "pipe2")) { |
| 4920 | var fds: [2]fd_t = undefined; | 4891 | var fds: [2]fd_t = undefined; |
| 4921 | switch (errno(system.pipe2(&fds, flags))) { | 4892 | switch (errno(system.pipe2(&fds, flags))) { |
| ... | @@ -4934,12 +4905,13 @@ pub fn pipe2(flags: u32) PipeError![2]fd_t { | ... | @@ -4934,12 +4905,13 @@ pub fn pipe2(flags: u32) PipeError![2]fd_t { |
| 4934 | close(fds[1]); | 4905 | close(fds[1]); |
| 4935 | } | 4906 | } |
| 4936 | 4907 | ||
| 4937 | if (flags == 0) | 4908 | // https://github.com/ziglang/zig/issues/18882 |
| 4909 | if (@as(u32, @bitCast(flags)) == 0) | ||
| 4938 | return fds; | 4910 | return fds; |
| 4939 | 4911 | ||
| 4940 | // O.CLOEXEC is special, it's a file descriptor flag and must be set using | 4912 | // CLOEXEC is special, it's a file descriptor flag and must be set using |
| 4941 | // F.SETFD. | 4913 | // F.SETFD. |
| 4942 | if (flags & O.CLOEXEC != 0) { | 4914 | if (flags.CLOEXEC) { |
| 4943 | for (fds) |fd| { | 4915 | for (fds) |fd| { |
| 4944 | switch (errno(system.fcntl(fd, F.SETFD, @as(u32, FD_CLOEXEC)))) { | 4916 | switch (errno(system.fcntl(fd, F.SETFD, @as(u32, FD_CLOEXEC)))) { |
| 4945 | .SUCCESS => {}, | 4917 | .SUCCESS => {}, |
| ... | @@ -4950,7 +4922,11 @@ pub fn pipe2(flags: u32) PipeError![2]fd_t { | ... | @@ -4950,7 +4922,11 @@ pub fn pipe2(flags: u32) PipeError![2]fd_t { |
| 4950 | } | 4922 | } |
| 4951 | } | 4923 | } |
| 4952 | 4924 | ||
| 4953 | const new_flags = flags & ~@as(u32, O.CLOEXEC); | 4925 | const new_flags: u32 = f: { |
| 4926 | var new_flags = flags; | ||
| 4927 | new_flags.CLOEXEC = false; | ||
| 4928 | break :f @bitCast(new_flags); | ||
| 4929 | }; | ||
| 4954 | // Set every other flag affecting the file status using F.SETFL. | 4930 | // Set every other flag affecting the file status using F.SETFL. |
| 4955 | if (new_flags != 0) { | 4931 | if (new_flags != 0) { |
| 4956 | for (fds) |fd| { | 4932 | for (fds) |fd| { |
| ... | @@ -5289,7 +5265,7 @@ fn setSockFlags(sock: socket_t, flags: u32) !void { | ... | @@ -5289,7 +5265,7 @@ fn setSockFlags(sock: socket_t, flags: u32) !void { |
| 5289 | error.LockedRegionLimitExceeded => unreachable, | 5265 | error.LockedRegionLimitExceeded => unreachable, |
| 5290 | else => |e| return e, | 5266 | else => |e| return e, |
| 5291 | }; | 5267 | }; |
| 5292 | fl_flags |= O.NONBLOCK; | 5268 | fl_flags |= 1 << @bitOffsetOf(O, "NONBLOCK"); |
| 5293 | _ = fcntl(sock, F.SETFL, fl_flags) catch |err| switch (err) { | 5269 | _ = fcntl(sock, F.SETFL, fl_flags) catch |err| switch (err) { |
| 5294 | error.FileBusy => unreachable, | 5270 | error.FileBusy => unreachable, |
| 5295 | error.Locked => unreachable, | 5271 | error.Locked => unreachable, |
| ... | @@ -5389,7 +5365,17 @@ pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP | ... | @@ -5389,7 +5365,17 @@ pub fn realpathZ(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealP |
| 5389 | return realpath(mem.sliceTo(pathname, 0), out_buffer); | 5365 | return realpath(mem.sliceTo(pathname, 0), out_buffer); |
| 5390 | } | 5366 | } |
| 5391 | if (!builtin.link_libc) { | 5367 | if (!builtin.link_libc) { |
| 5392 | const flags = if (builtin.os.tag == .linux) O.PATH | O.NONBLOCK | O.CLOEXEC else O.NONBLOCK | O.CLOEXEC; | 5368 | const flags: O = switch (builtin.os.tag) { |
| 5369 | .linux => .{ | ||
| 5370 | .NONBLOCK = true, | ||
| 5371 | .CLOEXEC = true, | ||
| 5372 | .PATH = true, | ||
| 5373 | }, | ||
| 5374 | else => .{ | ||
| 5375 | .NONBLOCK = true, | ||
| 5376 | .CLOEXEC = true, | ||
| 5377 | }, | ||
| 5378 | }; | ||
| 5393 | const fd = openZ(pathname, flags, 0) catch |err| switch (err) { | 5379 | const fd = openZ(pathname, flags, 0) catch |err| switch (err) { |
| 5394 | error.FileLocksNotSupported => unreachable, | 5380 | error.FileLocksNotSupported => unreachable, |
| 5395 | error.WouldBlock => unreachable, | 5381 | error.WouldBlock => unreachable, |
| ... | @@ -5893,7 +5879,10 @@ pub fn futimens(fd: fd_t, times: *const [2]timespec) FutimensError!void { | ... | @@ -5893,7 +5879,10 @@ pub fn futimens(fd: fd_t, times: *const [2]timespec) FutimensError!void { |
| 5893 | // this here, but we should really handle it somehow. | 5879 | // this here, but we should really handle it somehow. |
| 5894 | const atim = times[0].toTimestamp(); | 5880 | const atim = times[0].toTimestamp(); |
| 5895 | const mtim = times[1].toTimestamp(); | 5881 | const mtim = times[1].toTimestamp(); |
| 5896 | switch (wasi.fd_filestat_set_times(fd, atim, mtim, wasi.FILESTAT_SET_ATIM | wasi.FILESTAT_SET_MTIM)) { | 5882 | switch (wasi.fd_filestat_set_times(fd, atim, mtim, .{ |
| 5883 | .ATIM = true, | ||
| 5884 | .MTIM = true, | ||
| 5885 | })) { | ||
| 5897 | .SUCCESS => return, | 5886 | .SUCCESS => return, |
| 5898 | .ACCES => return error.AccessDenied, | 5887 | .ACCES => return error.AccessDenied, |
| 5899 | .PERM => return error.PermissionDenied, | 5888 | .PERM => return error.PermissionDenied, |
| ... | @@ -6390,7 +6379,7 @@ pub fn sendfile( | ... | @@ -6390,7 +6379,7 @@ pub fn sendfile( |
| 6390 | // * Descriptor is not valid or locked | 6379 | // * Descriptor is not valid or locked |
| 6391 | // * an mmap(2)-like operation is not available for in_fd | 6380 | // * an mmap(2)-like operation is not available for in_fd |
| 6392 | // * count is negative | 6381 | // * count is negative |
| 6393 | // * out_fd has the O.APPEND flag set | 6382 | // * out_fd has the APPEND flag set |
| 6394 | // Because of the "mmap(2)-like operation" possibility, we fall back to doing read/write | 6383 | // Because of the "mmap(2)-like operation" possibility, we fall back to doing read/write |
| 6395 | // manually, the same as ENOSYS. | 6384 | // manually, the same as ENOSYS. |
| 6396 | break :sf; | 6385 | break :sf; |
| ... | @@ -6588,7 +6577,7 @@ pub const CopyFileRangeError = error{ | ... | @@ -6588,7 +6577,7 @@ pub const CopyFileRangeError = error{ |
| 6588 | FileTooBig, | 6577 | FileTooBig, |
| 6589 | InputOutput, | 6578 | InputOutput, |
| 6590 | /// `fd_in` is not open for reading; or `fd_out` is not open for writing; | 6579 | /// `fd_in` is not open for reading; or `fd_out` is not open for writing; |
| 6591 | /// or the `O.APPEND` flag is set for `fd_out`. | 6580 | /// or the `APPEND` flag is set for `fd_out`. |
| 6592 | FilesOpenedWithWrongFlags, | 6581 | FilesOpenedWithWrongFlags, |
| 6593 | IsDir, | 6582 | IsDir, |
| 6594 | OutOfMemory, | 6583 | OutOfMemory, |
| ... | @@ -7425,7 +7414,7 @@ pub const TimerFdCreateError = error{ | ... | @@ -7425,7 +7414,7 @@ pub const TimerFdCreateError = error{ |
| 7425 | pub const TimerFdGetError = error{InvalidHandle} || UnexpectedError; | 7414 | pub const TimerFdGetError = error{InvalidHandle} || UnexpectedError; |
| 7426 | pub const TimerFdSetError = TimerFdGetError || error{Canceled}; | 7415 | pub const TimerFdSetError = TimerFdGetError || error{Canceled}; |
| 7427 | 7416 | ||
| 7428 | pub fn timerfd_create(clokid: i32, flags: u32) TimerFdCreateError!fd_t { | 7417 | pub fn timerfd_create(clokid: i32, flags: linux.TFD) TimerFdCreateError!fd_t { |
| 7429 | const rc = linux.timerfd_create(clokid, flags); | 7418 | const rc = linux.timerfd_create(clokid, flags); |
| 7430 | return switch (errno(rc)) { | 7419 | return switch (errno(rc)) { |
| 7431 | .SUCCESS => @as(fd_t, @intCast(rc)), | 7420 | .SUCCESS => @as(fd_t, @intCast(rc)), |
| ... | @@ -7439,7 +7428,12 @@ pub fn timerfd_create(clokid: i32, flags: u32) TimerFdCreateError!fd_t { | ... | @@ -7439,7 +7428,12 @@ pub fn timerfd_create(clokid: i32, flags: u32) TimerFdCreateError!fd_t { |
| 7439 | }; | 7428 | }; |
| 7440 | } | 7429 | } |
| 7441 | 7430 | ||
| 7442 | pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const linux.itimerspec, old_value: ?*linux.itimerspec) TimerFdSetError!void { | 7431 | pub fn timerfd_settime( |
| 7432 | fd: i32, | ||
| 7433 | flags: linux.TFD.TIMER, | ||
| 7434 | new_value: *const linux.itimerspec, | ||
| 7435 | old_value: ?*linux.itimerspec, | ||
| 7436 | ) TimerFdSetError!void { | ||
| 7443 | const rc = linux.timerfd_settime(fd, flags, new_value, old_value); | 7437 | const rc = linux.timerfd_settime(fd, flags, new_value, old_value); |
| 7444 | return switch (errno(rc)) { | 7438 | return switch (errno(rc)) { |
| 7445 | .SUCCESS => {}, | 7439 | .SUCCESS => {}, |
lib/std/os/emscripten.zig-41| ... | @@ -127,20 +127,6 @@ pub const AF = struct { | ... | @@ -127,20 +127,6 @@ pub const AF = struct { |
| 127 | pub const MAX = PF.MAX; | 127 | pub const MAX = PF.MAX; |
| 128 | }; | 128 | }; |
| 129 | 129 | ||
| 130 | pub const AT = struct { | ||
| 131 | pub const FDCWD = -100; | ||
| 132 | pub const SYMLINK_NOFOLLOW = 0x100; | ||
| 133 | pub const REMOVEDIR = 0x200; | ||
| 134 | pub const SYMLINK_FOLLOW = 0x400; | ||
| 135 | pub const NO_AUTOMOUNT = 0x800; | ||
| 136 | pub const EMPTY_PATH = 0x1000; | ||
| 137 | pub const STATX_SYNC_TYPE = 0x6000; | ||
| 138 | pub const STATX_SYNC_AS_STAT = 0x0000; | ||
| 139 | pub const STATX_FORCE_SYNC = 0x2000; | ||
| 140 | pub const STATX_DONT_SYNC = 0x4000; | ||
| 141 | pub const RECURSIVE = 0x8000; | ||
| 142 | }; | ||
| 143 | |||
| 144 | pub const CLOCK = struct { | 130 | pub const CLOCK = struct { |
| 145 | pub const REALTIME = 0; | 131 | pub const REALTIME = 0; |
| 146 | pub const MONOTONIC = 1; | 132 | pub const MONOTONIC = 1; |
| ... | @@ -479,33 +465,6 @@ pub const MSG = struct { | ... | @@ -479,33 +465,6 @@ pub const MSG = struct { |
| 479 | pub const CMSG_CLOEXEC = 0x40000000; | 465 | pub const CMSG_CLOEXEC = 0x40000000; |
| 480 | }; | 466 | }; |
| 481 | 467 | ||
| 482 | pub const O = struct { | ||
| 483 | pub const RDONLY = 0o0; | ||
| 484 | pub const WRONLY = 0o1; | ||
| 485 | pub const RDWR = 0o2; | ||
| 486 | |||
| 487 | pub const CREAT = 0o100; | ||
| 488 | pub const EXCL = 0o200; | ||
| 489 | pub const NOCTTY = 0o400; | ||
| 490 | pub const TRUNC = 0o1000; | ||
| 491 | pub const APPEND = 0o2000; | ||
| 492 | pub const NONBLOCK = 0o4000; | ||
| 493 | pub const DSYNC = 0o10000; | ||
| 494 | pub const SYNC = 0o4010000; | ||
| 495 | pub const RSYNC = 0o4010000; | ||
| 496 | pub const DIRECTORY = 0o200000; | ||
| 497 | pub const NOFOLLOW = 0o400000; | ||
| 498 | pub const CLOEXEC = 0o2000000; | ||
| 499 | |||
| 500 | pub const ASYNC = 0o20000; | ||
| 501 | pub const DIRECT = 0o40000; | ||
| 502 | pub const LARGEFILE = 0o100000; | ||
| 503 | pub const NOATIME = 0o1000000; | ||
| 504 | pub const PATH = 0o10000000; | ||
| 505 | pub const TMPFILE = 0o20200000; | ||
| 506 | pub const NDELAY = NONBLOCK; | ||
| 507 | }; | ||
| 508 | |||
| 509 | pub const POLL = struct { | 468 | pub const POLL = struct { |
| 510 | pub const IN = 0x001; | 469 | pub const IN = 0x001; |
| 511 | pub const PRI = 0x002; | 470 | pub const PRI = 0x002; |
lib/std/os/linux.zig+206-57| ... | @@ -20,6 +20,7 @@ const is_ppc64 = native_arch.isPPC64(); | ... | @@ -20,6 +20,7 @@ const is_ppc64 = native_arch.isPPC64(); |
| 20 | const is_sparc = native_arch.isSPARC(); | 20 | const is_sparc = native_arch.isSPARC(); |
| 21 | const iovec = std.os.iovec; | 21 | const iovec = std.os.iovec; |
| 22 | const iovec_const = std.os.iovec_const; | 22 | const iovec_const = std.os.iovec_const; |
| 23 | const ACCMODE = std.os.ACCMODE; | ||
| 23 | 24 | ||
| 24 | test { | 25 | test { |
| 25 | if (builtin.os.tag == .linux) { | 26 | if (builtin.os.tag == .linux) { |
| ... | @@ -241,12 +242,145 @@ pub const MAP = switch (native_arch) { | ... | @@ -241,12 +242,145 @@ pub const MAP = switch (native_arch) { |
| 241 | else => @compileError("missing std.os.linux.MAP constants for this architecture"), | 242 | else => @compileError("missing std.os.linux.MAP constants for this architecture"), |
| 242 | }; | 243 | }; |
| 243 | 244 | ||
| 244 | pub const O = struct { | 245 | pub const O = switch (native_arch) { |
| 245 | pub usingnamespace arch_bits.O; | 246 | .x86_64 => packed struct(u32) { |
| 246 | 247 | ACCMODE: ACCMODE = .RDONLY, | |
| 247 | pub const RDONLY = 0o0; | 248 | _2: u4 = 0, |
| 248 | pub const WRONLY = 0o1; | 249 | CREAT: bool = false, |
| 249 | pub const RDWR = 0o2; | 250 | EXCL: bool = false, |
| 251 | NOCTTY: bool = false, | ||
| 252 | TRUNC: bool = false, | ||
| 253 | APPEND: bool = false, | ||
| 254 | NONBLOCK: bool = false, | ||
| 255 | DSYNC: bool = false, | ||
| 256 | ASYNC: bool = false, | ||
| 257 | DIRECT: bool = false, | ||
| 258 | _15: u1 = 0, | ||
| 259 | DIRECTORY: bool = false, | ||
| 260 | NOFOLLOW: bool = false, | ||
| 261 | NOATIME: bool = false, | ||
| 262 | CLOEXEC: bool = false, | ||
| 263 | SYNC: bool = false, | ||
| 264 | PATH: bool = false, | ||
| 265 | TMPFILE: bool = false, | ||
| 266 | _: u9 = 0, | ||
| 267 | }, | ||
| 268 | .x86, .riscv64 => packed struct(u32) { | ||
| 269 | ACCMODE: ACCMODE = .RDONLY, | ||
| 270 | _2: u4 = 0, | ||
| 271 | CREAT: bool = false, | ||
| 272 | EXCL: bool = false, | ||
| 273 | NOCTTY: bool = false, | ||
| 274 | TRUNC: bool = false, | ||
| 275 | APPEND: bool = false, | ||
| 276 | NONBLOCK: bool = false, | ||
| 277 | DSYNC: bool = false, | ||
| 278 | ASYNC: bool = false, | ||
| 279 | DIRECT: bool = false, | ||
| 280 | LARGEFILE: bool = false, | ||
| 281 | DIRECTORY: bool = false, | ||
| 282 | NOFOLLOW: bool = false, | ||
| 283 | NOATIME: bool = false, | ||
| 284 | CLOEXEC: bool = false, | ||
| 285 | SYNC: bool = false, | ||
| 286 | PATH: bool = false, | ||
| 287 | TMPFILE: bool = false, | ||
| 288 | _: u9 = 0, | ||
| 289 | }, | ||
| 290 | .aarch64, .aarch64_be, .arm, .thumb => packed struct(u32) { | ||
| 291 | ACCMODE: ACCMODE = .RDONLY, | ||
| 292 | _2: u4 = 0, | ||
| 293 | CREAT: bool = false, | ||
| 294 | EXCL: bool = false, | ||
| 295 | NOCTTY: bool = false, | ||
| 296 | TRUNC: bool = false, | ||
| 297 | APPEND: bool = false, | ||
| 298 | NONBLOCK: bool = false, | ||
| 299 | DSYNC: bool = false, | ||
| 300 | ASYNC: bool = false, | ||
| 301 | DIRECTORY: bool = false, | ||
| 302 | NOFOLLOW: bool = false, | ||
| 303 | DIRECT: bool = false, | ||
| 304 | LARGEFILE: bool = false, | ||
| 305 | NOATIME: bool = false, | ||
| 306 | CLOEXEC: bool = false, | ||
| 307 | SYNC: bool = false, | ||
| 308 | PATH: bool = false, | ||
| 309 | TMPFILE: bool = false, | ||
| 310 | _: u9 = 0, | ||
| 311 | }, | ||
| 312 | .sparc64 => packed struct(u32) { | ||
| 313 | ACCMODE: ACCMODE = .RDONLY, | ||
| 314 | _2: u1 = 0, | ||
| 315 | APPEND: bool = false, | ||
| 316 | _4: u2 = 0, | ||
| 317 | ASYNC: bool = false, | ||
| 318 | _7: u2 = 0, | ||
| 319 | CREAT: bool = false, | ||
| 320 | TRUNC: bool = false, | ||
| 321 | EXCL: bool = false, | ||
| 322 | _12: u1 = 0, | ||
| 323 | DSYNC: bool = false, | ||
| 324 | NONBLOCK: bool = false, | ||
| 325 | NOCTTY: bool = false, | ||
| 326 | DIRECTORY: bool = false, | ||
| 327 | NOFOLLOW: bool = false, | ||
| 328 | _18: u2 = 0, | ||
| 329 | DIRECT: bool = false, | ||
| 330 | NOATIME: bool = false, | ||
| 331 | CLOEXEC: bool = false, | ||
| 332 | SYNC: bool = false, | ||
| 333 | PATH: bool = false, | ||
| 334 | TMPFILE: bool = false, | ||
| 335 | _: u6 = 0, | ||
| 336 | }, | ||
| 337 | .mips, .mipsel, .mips64, .mips64el => packed struct(u32) { | ||
| 338 | ACCMODE: ACCMODE = .RDONLY, | ||
| 339 | _2: u1 = 0, | ||
| 340 | APPEND: bool = false, | ||
| 341 | DSYNC: bool = false, | ||
| 342 | _5: u2 = 0, | ||
| 343 | NONBLOCK: bool = false, | ||
| 344 | CREAT: bool = false, | ||
| 345 | TRUNC: bool = false, | ||
| 346 | EXCL: bool = false, | ||
| 347 | NOCTTY: bool = false, | ||
| 348 | ASYNC: bool = false, | ||
| 349 | LARGEFILE: bool = false, | ||
| 350 | SYNC: bool = false, | ||
| 351 | DIRECT: bool = false, | ||
| 352 | DIRECTORY: bool = false, | ||
| 353 | NOFOLLOW: bool = false, | ||
| 354 | NOATIME: bool = false, | ||
| 355 | CLOEXEC: bool = false, | ||
| 356 | _20: u1 = 0, | ||
| 357 | PATH: bool = false, | ||
| 358 | TMPFILE: bool = false, | ||
| 359 | _: u9 = 0, | ||
| 360 | }, | ||
| 361 | .powerpc, .powerpcle, .powerpc64, .powerpc64le => packed struct(u32) { | ||
| 362 | ACCMODE: ACCMODE = .RDONLY, | ||
| 363 | _2: u4 = 0, | ||
| 364 | CREAT: bool = false, | ||
| 365 | EXCL: bool = false, | ||
| 366 | NOCTTY: bool = false, | ||
| 367 | TRUNC: bool = false, | ||
| 368 | APPEND: bool = false, | ||
| 369 | NONBLOCK: bool = false, | ||
| 370 | DSYNC: bool = false, | ||
| 371 | ASYNC: bool = false, | ||
| 372 | DIRECTORY: bool = false, | ||
| 373 | NOFOLLOW: bool = false, | ||
| 374 | LARGEFILE: bool = false, | ||
| 375 | DIRECT: bool = false, | ||
| 376 | NOATIME: bool = false, | ||
| 377 | CLOEXEC: bool = false, | ||
| 378 | SYNC: bool = false, | ||
| 379 | PATH: bool = false, | ||
| 380 | TMPFILE: bool = false, | ||
| 381 | _: u9 = 0, | ||
| 382 | }, | ||
| 383 | else => @compileError("missing std.os.linux.O constants for this architecture"), | ||
| 250 | }; | 384 | }; |
| 251 | 385 | ||
| 252 | pub usingnamespace @import("linux/io_uring.zig"); | 386 | pub usingnamespace @import("linux/io_uring.zig"); |
| ... | @@ -620,20 +754,20 @@ pub fn umount2(special: [*:0]const u8, flags: u32) usize { | ... | @@ -620,20 +754,20 @@ pub fn umount2(special: [*:0]const u8, flags: u32) usize { |
| 620 | return syscall2(.umount2, @intFromPtr(special), flags); | 754 | return syscall2(.umount2, @intFromPtr(special), flags); |
| 621 | } | 755 | } |
| 622 | 756 | ||
| 623 | pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: i64) usize { | 757 | pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: MAP, fd: i32, offset: i64) usize { |
| 624 | if (@hasField(SYS, "mmap2")) { | 758 | if (@hasField(SYS, "mmap2")) { |
| 625 | // Make sure the offset is also specified in multiples of page size | 759 | // Make sure the offset is also specified in multiples of page size |
| 626 | if ((offset & (MMAP2_UNIT - 1)) != 0) | 760 | if ((offset & (MMAP2_UNIT - 1)) != 0) |
| 627 | return @as(usize, @bitCast(-@as(isize, @intFromEnum(E.INVAL)))); | 761 | return @bitCast(-@as(isize, @intFromEnum(E.INVAL))); |
| 628 | 762 | ||
| 629 | return syscall6( | 763 | return syscall6( |
| 630 | .mmap2, | 764 | .mmap2, |
| 631 | @intFromPtr(address), | 765 | @intFromPtr(address), |
| 632 | length, | 766 | length, |
| 633 | prot, | 767 | prot, |
| 634 | flags, | 768 | @as(u32, @bitCast(flags)), |
| 635 | @as(usize, @bitCast(@as(isize, fd))), | 769 | @bitCast(@as(isize, fd)), |
| 636 | @as(usize, @truncate(@as(u64, @bitCast(offset)) / MMAP2_UNIT)), | 770 | @truncate(@as(u64, @bitCast(offset)) / MMAP2_UNIT), |
| 637 | ); | 771 | ); |
| 638 | } else { | 772 | } else { |
| 639 | return syscall6( | 773 | return syscall6( |
| ... | @@ -641,8 +775,8 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, of | ... | @@ -641,8 +775,8 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, of |
| 641 | @intFromPtr(address), | 775 | @intFromPtr(address), |
| 642 | length, | 776 | length, |
| 643 | prot, | 777 | prot, |
| 644 | flags, | 778 | @as(u32, @bitCast(flags)), |
| 645 | @as(usize, @bitCast(@as(isize, fd))), | 779 | @bitCast(@as(isize, fd)), |
| 646 | @as(u64, @bitCast(offset)), | 780 | @as(u64, @bitCast(offset)), |
| 647 | ); | 781 | ); |
| 648 | } | 782 | } |
| ... | @@ -840,12 +974,12 @@ pub fn pipe(fd: *[2]i32) usize { | ... | @@ -840,12 +974,12 @@ pub fn pipe(fd: *[2]i32) usize { |
| 840 | } | 974 | } |
| 841 | } | 975 | } |
| 842 | 976 | ||
| 843 | pub fn pipe2(fd: *[2]i32, flags: u32) usize { | 977 | pub fn pipe2(fd: *[2]i32, flags: O) usize { |
| 844 | return syscall2(.pipe2, @intFromPtr(fd), flags); | 978 | return syscall2(.pipe2, @intFromPtr(fd), @as(u32, @bitCast(flags))); |
| 845 | } | 979 | } |
| 846 | 980 | ||
| 847 | pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { | 981 | pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { |
| 848 | return syscall3(.write, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(buf), count); | 982 | return syscall3(.write, @bitCast(@as(isize, fd)), @intFromPtr(buf), count); |
| 849 | } | 983 | } |
| 850 | 984 | ||
| 851 | pub fn ftruncate(fd: i32, length: i64) usize { | 985 | pub fn ftruncate(fd: i32, length: i64) usize { |
| ... | @@ -958,15 +1092,15 @@ pub fn renameat2(oldfd: i32, oldpath: [*:0]const u8, newfd: i32, newpath: [*:0]c | ... | @@ -958,15 +1092,15 @@ pub fn renameat2(oldfd: i32, oldpath: [*:0]const u8, newfd: i32, newpath: [*:0]c |
| 958 | ); | 1092 | ); |
| 959 | } | 1093 | } |
| 960 | 1094 | ||
| 961 | pub fn open(path: [*:0]const u8, flags: u32, perm: mode_t) usize { | 1095 | pub fn open(path: [*:0]const u8, flags: O, perm: mode_t) usize { |
| 962 | if (@hasField(SYS, "open")) { | 1096 | if (@hasField(SYS, "open")) { |
| 963 | return syscall3(.open, @intFromPtr(path), flags, perm); | 1097 | return syscall3(.open, @intFromPtr(path), @as(u32, @bitCast(flags)), perm); |
| 964 | } else { | 1098 | } else { |
| 965 | return syscall4( | 1099 | return syscall4( |
| 966 | .openat, | 1100 | .openat, |
| 967 | @as(usize, @bitCast(@as(isize, AT.FDCWD))), | 1101 | @bitCast(@as(isize, AT.FDCWD)), |
| 968 | @intFromPtr(path), | 1102 | @intFromPtr(path), |
| 969 | flags, | 1103 | @as(u32, @bitCast(flags)), |
| 970 | perm, | 1104 | perm, |
| 971 | ); | 1105 | ); |
| 972 | } | 1106 | } |
| ... | @@ -976,9 +1110,9 @@ pub fn create(path: [*:0]const u8, perm: mode_t) usize { | ... | @@ -976,9 +1110,9 @@ pub fn create(path: [*:0]const u8, perm: mode_t) usize { |
| 976 | return syscall2(.creat, @intFromPtr(path), perm); | 1110 | return syscall2(.creat, @intFromPtr(path), perm); |
| 977 | } | 1111 | } |
| 978 | 1112 | ||
| 979 | pub fn openat(dirfd: i32, path: [*:0]const u8, flags: u32, mode: mode_t) usize { | 1113 | pub fn openat(dirfd: i32, path: [*:0]const u8, flags: O, mode: mode_t) usize { |
| 980 | // dirfd could be negative, for example AT.FDCWD is -100 | 1114 | // dirfd could be negative, for example AT.FDCWD is -100 |
| 981 | return syscall4(.openat, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), flags, mode); | 1115 | return syscall4(.openat, @bitCast(@as(isize, dirfd)), @intFromPtr(path), @as(u32, @bitCast(flags)), mode); |
| 982 | } | 1116 | } |
| 983 | 1117 | ||
| 984 | /// See also `clone` (from the arch-specific include) | 1118 | /// See also `clone` (from the arch-specific include) |
| ... | @@ -1800,8 +1934,8 @@ pub fn eventfd(count: u32, flags: u32) usize { | ... | @@ -1800,8 +1934,8 @@ pub fn eventfd(count: u32, flags: u32) usize { |
| 1800 | return syscall2(.eventfd2, count, flags); | 1934 | return syscall2(.eventfd2, count, flags); |
| 1801 | } | 1935 | } |
| 1802 | 1936 | ||
| 1803 | pub fn timerfd_create(clockid: i32, flags: u32) usize { | 1937 | pub fn timerfd_create(clockid: i32, flags: TFD) usize { |
| 1804 | return syscall2(.timerfd_create, @as(usize, @bitCast(@as(isize, clockid))), flags); | 1938 | return syscall2(.timerfd_create, @bitCast(@as(isize, clockid)), @as(u32, @bitCast(flags))); |
| 1805 | } | 1939 | } |
| 1806 | 1940 | ||
| 1807 | pub const itimerspec = extern struct { | 1941 | pub const itimerspec = extern struct { |
| ... | @@ -1810,11 +1944,11 @@ pub const itimerspec = extern struct { | ... | @@ -1810,11 +1944,11 @@ pub const itimerspec = extern struct { |
| 1810 | }; | 1944 | }; |
| 1811 | 1945 | ||
| 1812 | pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize { | 1946 | pub fn timerfd_gettime(fd: i32, curr_value: *itimerspec) usize { |
| 1813 | return syscall2(.timerfd_gettime, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(curr_value)); | 1947 | return syscall2(.timerfd_gettime, @bitCast(@as(isize, fd)), @intFromPtr(curr_value)); |
| 1814 | } | 1948 | } |
| 1815 | 1949 | ||
| 1816 | pub fn timerfd_settime(fd: i32, flags: u32, new_value: *const itimerspec, old_value: ?*itimerspec) usize { | 1950 | pub fn timerfd_settime(fd: i32, flags: TFD.TIMER, new_value: *const itimerspec, old_value: ?*itimerspec) usize { |
| 1817 | return syscall4(.timerfd_settime, @as(usize, @bitCast(@as(isize, fd))), flags, @intFromPtr(new_value), @intFromPtr(old_value)); | 1951 | return syscall4(.timerfd_settime, @bitCast(@as(isize, fd)), @as(u32, @bitCast(flags)), @intFromPtr(new_value), @intFromPtr(old_value)); |
| 1818 | } | 1952 | } |
| 1819 | 1953 | ||
| 1820 | // Flags for the 'setitimer' system call | 1954 | // Flags for the 'setitimer' system call |
| ... | @@ -2478,19 +2612,10 @@ pub const SIG = if (is_mips) struct { | ... | @@ -2478,19 +2612,10 @@ pub const SIG = if (is_mips) struct { |
| 2478 | pub const kernel_rwf = u32; | 2612 | pub const kernel_rwf = u32; |
| 2479 | 2613 | ||
| 2480 | pub const RWF = struct { | 2614 | pub const RWF = struct { |
| 2481 | /// high priority request, poll if possible | ||
| 2482 | pub const HIPRI: kernel_rwf = 0x00000001; | 2615 | pub const HIPRI: kernel_rwf = 0x00000001; |
| 2483 | |||
| 2484 | /// per-IO O.DSYNC | ||
| 2485 | pub const DSYNC: kernel_rwf = 0x00000002; | 2616 | pub const DSYNC: kernel_rwf = 0x00000002; |
| 2486 | |||
| 2487 | /// per-IO O.SYNC | ||
| 2488 | pub const SYNC: kernel_rwf = 0x00000004; | 2617 | pub const SYNC: kernel_rwf = 0x00000004; |
| 2489 | |||
| 2490 | /// per-IO, return -EAGAIN if operation would block | ||
| 2491 | pub const NOWAIT: kernel_rwf = 0x00000008; | 2618 | pub const NOWAIT: kernel_rwf = 0x00000008; |
| 2492 | |||
| 2493 | /// per-IO O.APPEND | ||
| 2494 | pub const APPEND: kernel_rwf = 0x00000010; | 2619 | pub const APPEND: kernel_rwf = 0x00000010; |
| 2495 | }; | 2620 | }; |
| 2496 | 2621 | ||
| ... | @@ -3257,7 +3382,7 @@ pub const T = struct { | ... | @@ -3257,7 +3382,7 @@ pub const T = struct { |
| 3257 | }; | 3382 | }; |
| 3258 | 3383 | ||
| 3259 | pub const EPOLL = struct { | 3384 | pub const EPOLL = struct { |
| 3260 | pub const CLOEXEC = O.CLOEXEC; | 3385 | pub const CLOEXEC = 1 << @bitOffsetOf(O, "CLOEXEC"); |
| 3261 | 3386 | ||
| 3262 | pub const CTL_ADD = 1; | 3387 | pub const CTL_ADD = 1; |
| 3263 | pub const CTL_DEL = 2; | 3388 | pub const CTL_DEL = 2; |
| ... | @@ -3338,8 +3463,8 @@ pub const CLONE = struct { | ... | @@ -3338,8 +3463,8 @@ pub const CLONE = struct { |
| 3338 | 3463 | ||
| 3339 | pub const EFD = struct { | 3464 | pub const EFD = struct { |
| 3340 | pub const SEMAPHORE = 1; | 3465 | pub const SEMAPHORE = 1; |
| 3341 | pub const CLOEXEC = O.CLOEXEC; | 3466 | pub const CLOEXEC = 1 << @bitOffsetOf(O, "CLOEXEC"); |
| 3342 | pub const NONBLOCK = O.NONBLOCK; | 3467 | pub const NONBLOCK = 1 << @bitOffsetOf(O, "NONBLOCK"); |
| 3343 | }; | 3468 | }; |
| 3344 | 3469 | ||
| 3345 | pub const MS = struct { | 3470 | pub const MS = struct { |
| ... | @@ -3388,8 +3513,8 @@ pub const MNT = struct { | ... | @@ -3388,8 +3513,8 @@ pub const MNT = struct { |
| 3388 | pub const UMOUNT_NOFOLLOW = 8; | 3513 | pub const UMOUNT_NOFOLLOW = 8; |
| 3389 | 3514 | ||
| 3390 | pub const IN = struct { | 3515 | pub const IN = struct { |
| 3391 | pub const CLOEXEC = O.CLOEXEC; | 3516 | pub const CLOEXEC = 1 << @bitOffsetOf(O, "CLOEXEC"); |
| 3392 | pub const NONBLOCK = O.NONBLOCK; | 3517 | pub const NONBLOCK = 1 << @bitOffsetOf(O, "NONBLOCK"); |
| 3393 | 3518 | ||
| 3394 | pub const ACCESS = 0x00000001; | 3519 | pub const ACCESS = 0x00000001; |
| 3395 | pub const MODIFY = 0x00000002; | 3520 | pub const MODIFY = 0x00000002; |
| ... | @@ -3534,12 +3659,40 @@ pub const UTIME = struct { | ... | @@ -3534,12 +3659,40 @@ pub const UTIME = struct { |
| 3534 | pub const OMIT = 0x3ffffffe; | 3659 | pub const OMIT = 0x3ffffffe; |
| 3535 | }; | 3660 | }; |
| 3536 | 3661 | ||
| 3537 | pub const TFD = struct { | 3662 | const TFD_TIMER = packed struct(u32) { |
| 3538 | pub const NONBLOCK = O.NONBLOCK; | 3663 | ABSTIME: bool = false, |
| 3539 | pub const CLOEXEC = O.CLOEXEC; | 3664 | CANCEL_ON_SET: bool = false, |
| 3665 | _: u30 = 0, | ||
| 3666 | }; | ||
| 3667 | |||
| 3668 | pub const TFD = switch (native_arch) { | ||
| 3669 | .sparc64 => packed struct(u32) { | ||
| 3670 | _0: u14 = 0, | ||
| 3671 | NONBLOCK: bool = false, | ||
| 3672 | _15: u7 = 0, | ||
| 3673 | CLOEXEC: bool = false, | ||
| 3674 | _: u9 = 0, | ||
| 3675 | |||
| 3676 | pub const TIMER = TFD_TIMER; | ||
| 3677 | }, | ||
| 3678 | .mips, .mipsel, .mips64, .mips64el => packed struct(u32) { | ||
| 3679 | _0: u7 = 0, | ||
| 3680 | NONBLOCK: bool = false, | ||
| 3681 | _8: u11 = 0, | ||
| 3682 | CLOEXEC: bool = false, | ||
| 3683 | _: u12 = 0, | ||
| 3684 | |||
| 3685 | pub const TIMER = TFD_TIMER; | ||
| 3686 | }, | ||
| 3687 | else => packed struct(u32) { | ||
| 3688 | _0: u11 = 0, | ||
| 3689 | NONBLOCK: bool = false, | ||
| 3690 | _12: u7 = 0, | ||
| 3691 | CLOEXEC: bool = false, | ||
| 3692 | _: u12 = 0, | ||
| 3540 | 3693 | ||
| 3541 | pub const TIMER_ABSTIME = 1; | 3694 | pub const TIMER = TFD_TIMER; |
| 3542 | pub const TIMER_CANCEL_ON_SET = (1 << 1); | 3695 | }, |
| 3543 | }; | 3696 | }; |
| 3544 | 3697 | ||
| 3545 | pub const winsize = extern struct { | 3698 | pub const winsize = extern struct { |
| ... | @@ -3603,8 +3756,8 @@ pub const empty_sigset = [_]u32{0} ** sigset_len; | ... | @@ -3603,8 +3756,8 @@ pub const empty_sigset = [_]u32{0} ** sigset_len; |
| 3603 | pub const filled_sigset = [_]u32{(1 << (31 & (usize_bits - 1))) - 1} ++ [_]u32{0} ** (sigset_len - 1); | 3756 | pub const filled_sigset = [_]u32{(1 << (31 & (usize_bits - 1))) - 1} ++ [_]u32{0} ** (sigset_len - 1); |
| 3604 | 3757 | ||
| 3605 | pub const SFD = struct { | 3758 | pub const SFD = struct { |
| 3606 | pub const CLOEXEC = O.CLOEXEC; | 3759 | pub const CLOEXEC = 1 << @bitOffsetOf(O, "CLOEXEC"); |
| 3607 | pub const NONBLOCK = O.NONBLOCK; | 3760 | pub const NONBLOCK = 1 << @bitOffsetOf(O, "NONBLOCK"); |
| 3608 | }; | 3761 | }; |
| 3609 | 3762 | ||
| 3610 | pub const signalfd_siginfo = extern struct { | 3763 | pub const signalfd_siginfo = extern struct { |
| ... | @@ -3865,15 +4018,11 @@ pub const inotify_event = extern struct { | ... | @@ -3865,15 +4018,11 @@ pub const inotify_event = extern struct { |
| 3865 | }; | 4018 | }; |
| 3866 | 4019 | ||
| 3867 | pub const dirent64 = extern struct { | 4020 | pub const dirent64 = extern struct { |
| 3868 | d_ino: u64, | 4021 | ino: u64, |
| 3869 | d_off: u64, | 4022 | off: u64, |
| 3870 | d_reclen: u16, | 4023 | reclen: u16, |
| 3871 | d_type: u8, | 4024 | type: u8, |
| 3872 | d_name: u8, // field address is the address of first byte of name https://github.com/ziglang/zig/issues/173 | 4025 | name: u8, // field address is the address of first byte of name https://github.com/ziglang/zig/issues/173 |
| 3873 | |||
| 3874 | pub fn reclen(self: dirent64) u16 { | ||
| 3875 | return self.d_reclen; | ||
| 3876 | } | ||
| 3877 | }; | 4026 | }; |
| 3878 | 4027 | ||
| 3879 | pub const dl_phdr_info = extern struct { | 4028 | pub const dl_phdr_info = extern struct { |
lib/std/os/linux/arm-eabi.zig-23| ... | @@ -141,29 +141,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { | ... | @@ -141,29 +141,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { |
| 141 | 141 | ||
| 142 | pub const MMAP2_UNIT = 4096; | 142 | pub const MMAP2_UNIT = 4096; |
| 143 | 143 | ||
| 144 | pub const O = struct { | ||
| 145 | pub const CREAT = 0o100; | ||
| 146 | pub const EXCL = 0o200; | ||
| 147 | pub const NOCTTY = 0o400; | ||
| 148 | pub const TRUNC = 0o1000; | ||
| 149 | pub const APPEND = 0o2000; | ||
| 150 | pub const NONBLOCK = 0o4000; | ||
| 151 | pub const DSYNC = 0o10000; | ||
| 152 | pub const SYNC = 0o4010000; | ||
| 153 | pub const RSYNC = 0o4010000; | ||
| 154 | pub const DIRECTORY = 0o40000; | ||
| 155 | pub const NOFOLLOW = 0o100000; | ||
| 156 | pub const CLOEXEC = 0o2000000; | ||
| 157 | |||
| 158 | pub const ASYNC = 0o20000; | ||
| 159 | pub const DIRECT = 0o200000; | ||
| 160 | pub const LARGEFILE = 0o400000; | ||
| 161 | pub const NOATIME = 0o1000000; | ||
| 162 | pub const PATH = 0o10000000; | ||
| 163 | pub const TMPFILE = 0o20040000; | ||
| 164 | pub const NDELAY = NONBLOCK; | ||
| 165 | }; | ||
| 166 | |||
| 167 | pub const F = struct { | 144 | pub const F = struct { |
| 168 | pub const DUPFD = 0; | 145 | pub const DUPFD = 0; |
| 169 | pub const GETFD = 1; | 146 | pub const GETFD = 1; |
lib/std/os/linux/arm64.zig-23| ... | @@ -123,29 +123,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { | ... | @@ -123,29 +123,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { |
| 123 | } | 123 | } |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | pub const O = struct { | ||
| 127 | pub const CREAT = 0o100; | ||
| 128 | pub const EXCL = 0o200; | ||
| 129 | pub const NOCTTY = 0o400; | ||
| 130 | pub const TRUNC = 0o1000; | ||
| 131 | pub const APPEND = 0o2000; | ||
| 132 | pub const NONBLOCK = 0o4000; | ||
| 133 | pub const DSYNC = 0o10000; | ||
| 134 | pub const SYNC = 0o4010000; | ||
| 135 | pub const RSYNC = 0o4010000; | ||
| 136 | pub const DIRECTORY = 0o40000; | ||
| 137 | pub const NOFOLLOW = 0o100000; | ||
| 138 | pub const CLOEXEC = 0o2000000; | ||
| 139 | |||
| 140 | pub const ASYNC = 0o20000; | ||
| 141 | pub const DIRECT = 0o200000; | ||
| 142 | pub const LARGEFILE = 0o400000; | ||
| 143 | pub const NOATIME = 0o1000000; | ||
| 144 | pub const PATH = 0o10000000; | ||
| 145 | pub const TMPFILE = 0o20040000; | ||
| 146 | pub const NDELAY = NONBLOCK; | ||
| 147 | }; | ||
| 148 | |||
| 149 | pub const F = struct { | 126 | pub const F = struct { |
| 150 | pub const DUPFD = 0; | 127 | pub const DUPFD = 0; |
| 151 | pub const GETFD = 1; | 128 | pub const GETFD = 1; |
lib/std/os/linux/io_uring.zig+13-13| ... | @@ -760,7 +760,7 @@ pub const IO_Uring = struct { | ... | @@ -760,7 +760,7 @@ pub const IO_Uring = struct { |
| 760 | user_data: u64, | 760 | user_data: u64, |
| 761 | fd: os.fd_t, | 761 | fd: os.fd_t, |
| 762 | path: [*:0]const u8, | 762 | path: [*:0]const u8, |
| 763 | flags: u32, | 763 | flags: linux.O, |
| 764 | mode: os.mode_t, | 764 | mode: os.mode_t, |
| 765 | ) !*linux.io_uring_sqe { | 765 | ) !*linux.io_uring_sqe { |
| 766 | const sqe = try self.get_sqe(); | 766 | const sqe = try self.get_sqe(); |
| ... | @@ -785,7 +785,7 @@ pub const IO_Uring = struct { | ... | @@ -785,7 +785,7 @@ pub const IO_Uring = struct { |
| 785 | user_data: u64, | 785 | user_data: u64, |
| 786 | fd: os.fd_t, | 786 | fd: os.fd_t, |
| 787 | path: [*:0]const u8, | 787 | path: [*:0]const u8, |
| 788 | flags: u32, | 788 | flags: linux.O, |
| 789 | mode: os.mode_t, | 789 | mode: os.mode_t, |
| 790 | file_index: u32, | 790 | file_index: u32, |
| 791 | ) !*linux.io_uring_sqe { | 791 | ) !*linux.io_uring_sqe { |
| ... | @@ -1658,18 +1658,18 @@ pub fn io_uring_prep_openat( | ... | @@ -1658,18 +1658,18 @@ pub fn io_uring_prep_openat( |
| 1658 | sqe: *linux.io_uring_sqe, | 1658 | sqe: *linux.io_uring_sqe, |
| 1659 | fd: os.fd_t, | 1659 | fd: os.fd_t, |
| 1660 | path: [*:0]const u8, | 1660 | path: [*:0]const u8, |
| 1661 | flags: u32, | 1661 | flags: linux.O, |
| 1662 | mode: os.mode_t, | 1662 | mode: os.mode_t, |
| 1663 | ) void { | 1663 | ) void { |
| 1664 | io_uring_prep_rw(.OPENAT, sqe, fd, @intFromPtr(path), mode, 0); | 1664 | io_uring_prep_rw(.OPENAT, sqe, fd, @intFromPtr(path), mode, 0); |
| 1665 | sqe.rw_flags = flags; | 1665 | sqe.rw_flags = @bitCast(flags); |
| 1666 | } | 1666 | } |
| 1667 | 1667 | ||
| 1668 | pub fn io_uring_prep_openat_direct( | 1668 | pub fn io_uring_prep_openat_direct( |
| 1669 | sqe: *linux.io_uring_sqe, | 1669 | sqe: *linux.io_uring_sqe, |
| 1670 | fd: os.fd_t, | 1670 | fd: os.fd_t, |
| 1671 | path: [*:0]const u8, | 1671 | path: [*:0]const u8, |
| 1672 | flags: u32, | 1672 | flags: linux.O, |
| 1673 | mode: os.mode_t, | 1673 | mode: os.mode_t, |
| 1674 | file_index: u32, | 1674 | file_index: u32, |
| 1675 | ) void { | 1675 | ) void { |
| ... | @@ -2054,7 +2054,7 @@ test "readv" { | ... | @@ -2054,7 +2054,7 @@ test "readv" { |
| 2054 | }; | 2054 | }; |
| 2055 | defer ring.deinit(); | 2055 | defer ring.deinit(); |
| 2056 | 2056 | ||
| 2057 | const fd = try os.openZ("/dev/zero", os.O.RDONLY | os.O.CLOEXEC, 0); | 2057 | const fd = try os.openZ("/dev/zero", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); |
| 2058 | defer os.close(fd); | 2058 | defer os.close(fd); |
| 2059 | 2059 | ||
| 2060 | // Linux Kernel 5.4 supports IORING_REGISTER_FILES but not sparse fd sets (i.e. an fd of -1). | 2060 | // Linux Kernel 5.4 supports IORING_REGISTER_FILES but not sparse fd sets (i.e. an fd of -1). |
| ... | @@ -2361,7 +2361,7 @@ test "openat" { | ... | @@ -2361,7 +2361,7 @@ test "openat" { |
| 2361 | break :p @intFromPtr(workaround); | 2361 | break :p @intFromPtr(workaround); |
| 2362 | } else @intFromPtr(path); | 2362 | } else @intFromPtr(path); |
| 2363 | 2363 | ||
| 2364 | const flags: u32 = os.O.CLOEXEC | os.O.RDWR | os.O.CREAT; | 2364 | const flags: linux.O = .{ .CLOEXEC = true, .ACCMODE = .RDWR, .CREAT = true }; |
| 2365 | const mode: os.mode_t = 0o666; | 2365 | const mode: os.mode_t = 0o666; |
| 2366 | const sqe_openat = try ring.openat(0x33333333, tmp.dir.fd, path, flags, mode); | 2366 | const sqe_openat = try ring.openat(0x33333333, tmp.dir.fd, path, flags, mode); |
| 2367 | try testing.expectEqual(linux.io_uring_sqe{ | 2367 | try testing.expectEqual(linux.io_uring_sqe{ |
| ... | @@ -2372,7 +2372,7 @@ test "openat" { | ... | @@ -2372,7 +2372,7 @@ test "openat" { |
| 2372 | .off = 0, | 2372 | .off = 0, |
| 2373 | .addr = path_addr, | 2373 | .addr = path_addr, |
| 2374 | .len = mode, | 2374 | .len = mode, |
| 2375 | .rw_flags = flags, | 2375 | .rw_flags = @bitCast(flags), |
| 2376 | .user_data = 0x33333333, | 2376 | .user_data = 0x33333333, |
| 2377 | .buf_index = 0, | 2377 | .buf_index = 0, |
| 2378 | .personality = 0, | 2378 | .personality = 0, |
| ... | @@ -2888,7 +2888,7 @@ test "register_files_update" { | ... | @@ -2888,7 +2888,7 @@ test "register_files_update" { |
| 2888 | }; | 2888 | }; |
| 2889 | defer ring.deinit(); | 2889 | defer ring.deinit(); |
| 2890 | 2890 | ||
| 2891 | const fd = try os.openZ("/dev/zero", os.O.RDONLY | os.O.CLOEXEC, 0); | 2891 | const fd = try os.openZ("/dev/zero", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); |
| 2892 | defer os.close(fd); | 2892 | defer os.close(fd); |
| 2893 | 2893 | ||
| 2894 | var registered_fds = [_]os.fd_t{0} ** 2; | 2894 | var registered_fds = [_]os.fd_t{0} ** 2; |
| ... | @@ -2906,7 +2906,7 @@ test "register_files_update" { | ... | @@ -2906,7 +2906,7 @@ test "register_files_update" { |
| 2906 | // Test IORING_REGISTER_FILES_UPDATE | 2906 | // Test IORING_REGISTER_FILES_UPDATE |
| 2907 | // Only available since Linux 5.5 | 2907 | // Only available since Linux 5.5 |
| 2908 | 2908 | ||
| 2909 | const fd2 = try os.openZ("/dev/zero", os.O.RDONLY | os.O.CLOEXEC, 0); | 2909 | const fd2 = try os.openZ("/dev/zero", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); |
| 2910 | defer os.close(fd2); | 2910 | defer os.close(fd2); |
| 2911 | 2911 | ||
| 2912 | registered_fds[fd_index] = fd2; | 2912 | registered_fds[fd_index] = fd2; |
| ... | @@ -3311,7 +3311,7 @@ test "provide_buffers: read" { | ... | @@ -3311,7 +3311,7 @@ test "provide_buffers: read" { |
| 3311 | }; | 3311 | }; |
| 3312 | defer ring.deinit(); | 3312 | defer ring.deinit(); |
| 3313 | 3313 | ||
| 3314 | const fd = try os.openZ("/dev/zero", os.O.RDONLY | os.O.CLOEXEC, 0); | 3314 | const fd = try os.openZ("/dev/zero", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); |
| 3315 | defer os.close(fd); | 3315 | defer os.close(fd); |
| 3316 | 3316 | ||
| 3317 | const group_id = 1337; | 3317 | const group_id = 1337; |
| ... | @@ -3443,7 +3443,7 @@ test "remove_buffers" { | ... | @@ -3443,7 +3443,7 @@ test "remove_buffers" { |
| 3443 | }; | 3443 | }; |
| 3444 | defer ring.deinit(); | 3444 | defer ring.deinit(); |
| 3445 | 3445 | ||
| 3446 | const fd = try os.openZ("/dev/zero", os.O.RDONLY | os.O.CLOEXEC, 0); | 3446 | const fd = try os.openZ("/dev/zero", .{ .ACCMODE = .RDONLY, .CLOEXEC = true }, 0); |
| 3447 | defer os.close(fd); | 3447 | defer os.close(fd); |
| 3448 | 3448 | ||
| 3449 | const group_id = 1337; | 3449 | const group_id = 1337; |
| ... | @@ -4113,7 +4113,7 @@ test "openat_direct/close_direct" { | ... | @@ -4113,7 +4113,7 @@ test "openat_direct/close_direct" { |
| 4113 | var tmp = std.testing.tmpDir(.{}); | 4113 | var tmp = std.testing.tmpDir(.{}); |
| 4114 | defer tmp.cleanup(); | 4114 | defer tmp.cleanup(); |
| 4115 | const path = "test_io_uring_close_direct"; | 4115 | const path = "test_io_uring_close_direct"; |
| 4116 | const flags: u32 = os.O.RDWR | os.O.CREAT; | 4116 | const flags: linux.O = .{ .ACCMODE = .RDWR, .CREAT = true }; |
| 4117 | const mode: os.mode_t = 0o666; | 4117 | const mode: os.mode_t = 0o666; |
| 4118 | const user_data: u64 = 0; | 4118 | const user_data: u64 = 0; |
| 4119 | 4119 |
lib/std/os/linux/mips.zig-23| ... | @@ -213,29 +213,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { | ... | @@ -213,29 +213,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { |
| 213 | ); | 213 | ); |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | pub const O = struct { | ||
| 217 | pub const CREAT = 0o0400; | ||
| 218 | pub const EXCL = 0o02000; | ||
| 219 | pub const NOCTTY = 0o04000; | ||
| 220 | pub const TRUNC = 0o01000; | ||
| 221 | pub const APPEND = 0o0010; | ||
| 222 | pub const NONBLOCK = 0o0200; | ||
| 223 | pub const DSYNC = 0o0020; | ||
| 224 | pub const SYNC = 0o040020; | ||
| 225 | pub const RSYNC = 0o040020; | ||
| 226 | pub const DIRECTORY = 0o0200000; | ||
| 227 | pub const NOFOLLOW = 0o0400000; | ||
| 228 | pub const CLOEXEC = 0o02000000; | ||
| 229 | |||
| 230 | pub const ASYNC = 0o010000; | ||
| 231 | pub const DIRECT = 0o0100000; | ||
| 232 | pub const LARGEFILE = 0o020000; | ||
| 233 | pub const NOATIME = 0o01000000; | ||
| 234 | pub const PATH = 0o010000000; | ||
| 235 | pub const TMPFILE = 0o020200000; | ||
| 236 | pub const NDELAY = NONBLOCK; | ||
| 237 | }; | ||
| 238 | |||
| 239 | pub const F = struct { | 216 | pub const F = struct { |
| 240 | pub const DUPFD = 0; | 217 | pub const DUPFD = 0; |
| 241 | pub const GETFD = 1; | 218 | pub const GETFD = 1; |
lib/std/os/linux/mips64.zig-23| ... | @@ -198,29 +198,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { | ... | @@ -198,29 +198,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { |
| 198 | ); | 198 | ); |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | pub const O = struct { | ||
| 202 | pub const CREAT = 0o0400; | ||
| 203 | pub const EXCL = 0o02000; | ||
| 204 | pub const NOCTTY = 0o04000; | ||
| 205 | pub const TRUNC = 0o01000; | ||
| 206 | pub const APPEND = 0o0010; | ||
| 207 | pub const NONBLOCK = 0o0200; | ||
| 208 | pub const DSYNC = 0o0020; | ||
| 209 | pub const SYNC = 0o040020; | ||
| 210 | pub const RSYNC = 0o040020; | ||
| 211 | pub const DIRECTORY = 0o0200000; | ||
| 212 | pub const NOFOLLOW = 0o0400000; | ||
| 213 | pub const CLOEXEC = 0o02000000; | ||
| 214 | |||
| 215 | pub const ASYNC = 0o010000; | ||
| 216 | pub const DIRECT = 0o0100000; | ||
| 217 | pub const LARGEFILE = 0o020000; | ||
| 218 | pub const NOATIME = 0o01000000; | ||
| 219 | pub const PATH = 0o010000000; | ||
| 220 | pub const TMPFILE = 0o020200000; | ||
| 221 | pub const NDELAY = NONBLOCK; | ||
| 222 | }; | ||
| 223 | |||
| 224 | pub const F = struct { | 201 | pub const F = struct { |
| 225 | pub const DUPFD = 0; | 202 | pub const DUPFD = 0; |
| 226 | pub const GETFD = 1; | 203 | pub const GETFD = 1; |
lib/std/os/linux/powerpc.zig-23| ... | @@ -142,29 +142,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { | ... | @@ -142,29 +142,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { |
| 142 | ); | 142 | ); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | pub const O = struct { | ||
| 146 | pub const CREAT = 0o100; | ||
| 147 | pub const EXCL = 0o200; | ||
| 148 | pub const NOCTTY = 0o400; | ||
| 149 | pub const TRUNC = 0o1000; | ||
| 150 | pub const APPEND = 0o2000; | ||
| 151 | pub const NONBLOCK = 0o4000; | ||
| 152 | pub const DSYNC = 0o10000; | ||
| 153 | pub const SYNC = 0o4010000; | ||
| 154 | pub const RSYNC = 0o4010000; | ||
| 155 | pub const DIRECTORY = 0o40000; | ||
| 156 | pub const NOFOLLOW = 0o100000; | ||
| 157 | pub const CLOEXEC = 0o2000000; | ||
| 158 | |||
| 159 | pub const ASYNC = 0o20000; | ||
| 160 | pub const DIRECT = 0o400000; | ||
| 161 | pub const LARGEFILE = 0o200000; | ||
| 162 | pub const NOATIME = 0o1000000; | ||
| 163 | pub const PATH = 0o10000000; | ||
| 164 | pub const TMPFILE = 0o20040000; | ||
| 165 | pub const NDELAY = NONBLOCK; | ||
| 166 | }; | ||
| 167 | |||
| 168 | pub const F = struct { | 145 | pub const F = struct { |
| 169 | pub const DUPFD = 0; | 146 | pub const DUPFD = 0; |
| 170 | pub const GETFD = 1; | 147 | pub const GETFD = 1; |
lib/std/os/linux/powerpc64.zig-23| ... | @@ -142,29 +142,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { | ... | @@ -142,29 +142,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { |
| 142 | ); | 142 | ); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | pub const O = struct { | ||
| 146 | pub const CREAT = 0o100; | ||
| 147 | pub const EXCL = 0o200; | ||
| 148 | pub const NOCTTY = 0o400; | ||
| 149 | pub const TRUNC = 0o1000; | ||
| 150 | pub const APPEND = 0o2000; | ||
| 151 | pub const NONBLOCK = 0o4000; | ||
| 152 | pub const DSYNC = 0o10000; | ||
| 153 | pub const SYNC = 0o4010000; | ||
| 154 | pub const RSYNC = 0o4010000; | ||
| 155 | pub const DIRECTORY = 0o40000; | ||
| 156 | pub const NOFOLLOW = 0o100000; | ||
| 157 | pub const CLOEXEC = 0o2000000; | ||
| 158 | |||
| 159 | pub const ASYNC = 0o20000; | ||
| 160 | pub const DIRECT = 0o400000; | ||
| 161 | pub const LARGEFILE = 0o200000; | ||
| 162 | pub const NOATIME = 0o1000000; | ||
| 163 | pub const PATH = 0o10000000; | ||
| 164 | pub const TMPFILE = 0o20200000; | ||
| 165 | pub const NDELAY = NONBLOCK; | ||
| 166 | }; | ||
| 167 | |||
| 168 | pub const F = struct { | 145 | pub const F = struct { |
| 169 | pub const DUPFD = 0; | 146 | pub const DUPFD = 0; |
| 170 | pub const GETFD = 1; | 147 | pub const GETFD = 1; |
lib/std/os/linux/riscv64.zig-23| ... | @@ -110,29 +110,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { | ... | @@ -110,29 +110,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { |
| 110 | ); | 110 | ); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | pub const O = struct { | ||
| 114 | pub const CREAT = 0o100; | ||
| 115 | pub const EXCL = 0o200; | ||
| 116 | pub const NOCTTY = 0o400; | ||
| 117 | pub const TRUNC = 0o1000; | ||
| 118 | pub const APPEND = 0o2000; | ||
| 119 | pub const NONBLOCK = 0o4000; | ||
| 120 | pub const DSYNC = 0o10000; | ||
| 121 | pub const SYNC = 0o4010000; | ||
| 122 | pub const RSYNC = 0o4010000; | ||
| 123 | pub const DIRECTORY = 0o200000; | ||
| 124 | pub const NOFOLLOW = 0o400000; | ||
| 125 | pub const CLOEXEC = 0o2000000; | ||
| 126 | |||
| 127 | pub const ASYNC = 0o20000; | ||
| 128 | pub const DIRECT = 0o40000; | ||
| 129 | pub const LARGEFILE = 0o100000; | ||
| 130 | pub const NOATIME = 0o1000000; | ||
| 131 | pub const PATH = 0o10000000; | ||
| 132 | pub const TMPFILE = 0o20200000; | ||
| 133 | pub const NDELAY = NONBLOCK; | ||
| 134 | }; | ||
| 135 | |||
| 136 | pub const F = struct { | 113 | pub const F = struct { |
| 137 | pub const DUPFD = 0; | 114 | pub const DUPFD = 0; |
| 138 | pub const GETFD = 1; | 115 | pub const GETFD = 1; |
lib/std/os/linux/sparc64.zig-23| ... | @@ -195,29 +195,6 @@ pub fn restore_rt() callconv(.C) void { | ... | @@ -195,29 +195,6 @@ pub fn restore_rt() callconv(.C) void { |
| 195 | ); | 195 | ); |
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | pub const O = struct { | ||
| 199 | pub const CREAT = 0x200; | ||
| 200 | pub const EXCL = 0x800; | ||
| 201 | pub const NOCTTY = 0x8000; | ||
| 202 | pub const TRUNC = 0x400; | ||
| 203 | pub const APPEND = 0x8; | ||
| 204 | pub const NONBLOCK = 0x4000; | ||
| 205 | pub const SYNC = 0x802000; | ||
| 206 | pub const DSYNC = 0x2000; | ||
| 207 | pub const RSYNC = SYNC; | ||
| 208 | pub const DIRECTORY = 0x10000; | ||
| 209 | pub const NOFOLLOW = 0x20000; | ||
| 210 | pub const CLOEXEC = 0x400000; | ||
| 211 | |||
| 212 | pub const ASYNC = 0x40; | ||
| 213 | pub const DIRECT = 0x100000; | ||
| 214 | pub const LARGEFILE = 0; | ||
| 215 | pub const NOATIME = 0x200000; | ||
| 216 | pub const PATH = 0x1000000; | ||
| 217 | pub const TMPFILE = 0x2010000; | ||
| 218 | pub const NDELAY = NONBLOCK | 0x4; | ||
| 219 | }; | ||
| 220 | |||
| 221 | pub const F = struct { | 198 | pub const F = struct { |
| 222 | pub const DUPFD = 0; | 199 | pub const DUPFD = 0; |
| 223 | pub const GETFD = 1; | 200 | pub const GETFD = 1; |
lib/std/os/linux/test.zig+2-2| ... | @@ -37,7 +37,7 @@ test "timer" { | ... | @@ -37,7 +37,7 @@ test "timer" { |
| 37 | var err: linux.E = linux.getErrno(epoll_fd); | 37 | var err: linux.E = linux.getErrno(epoll_fd); |
| 38 | try expect(err == .SUCCESS); | 38 | try expect(err == .SUCCESS); |
| 39 | 39 | ||
| 40 | const timer_fd = linux.timerfd_create(linux.CLOCK.MONOTONIC, 0); | 40 | const timer_fd = linux.timerfd_create(linux.CLOCK.MONOTONIC, .{}); |
| 41 | try expect(linux.getErrno(timer_fd) == .SUCCESS); | 41 | try expect(linux.getErrno(timer_fd) == .SUCCESS); |
| 42 | 42 | ||
| 43 | const time_interval = linux.timespec{ | 43 | const time_interval = linux.timespec{ |
| ... | @@ -50,7 +50,7 @@ test "timer" { | ... | @@ -50,7 +50,7 @@ test "timer" { |
| 50 | .it_value = time_interval, | 50 | .it_value = time_interval, |
| 51 | }; | 51 | }; |
| 52 | 52 | ||
| 53 | err = linux.getErrno(linux.timerfd_settime(@as(i32, @intCast(timer_fd)), 0, &new_time, null)); | 53 | err = linux.getErrno(linux.timerfd_settime(@as(i32, @intCast(timer_fd)), .{}, &new_time, null)); |
| 54 | try expect(err == .SUCCESS); | 54 | try expect(err == .SUCCESS); |
| 55 | 55 | ||
| 56 | var event = linux.epoll_event{ | 56 | var event = linux.epoll_event{ |
lib/std/os/linux/x86.zig-23| ... | @@ -159,29 +159,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { | ... | @@ -159,29 +159,6 @@ pub fn restore_rt() callconv(.Naked) noreturn { |
| 159 | } | 159 | } |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | pub const O = struct { | ||
| 163 | pub const CREAT = 0o100; | ||
| 164 | pub const EXCL = 0o200; | ||
| 165 | pub const NOCTTY = 0o400; | ||
| 166 | pub const TRUNC = 0o1000; | ||
| 167 | pub const APPEND = 0o2000; | ||
| 168 | pub const NONBLOCK = 0o4000; | ||
| 169 | pub const DSYNC = 0o10000; | ||
| 170 | pub const SYNC = 0o4010000; | ||
| 171 | pub const RSYNC = 0o4010000; | ||
| 172 | pub const DIRECTORY = 0o200000; | ||
| 173 | pub const NOFOLLOW = 0o400000; | ||
| 174 | pub const CLOEXEC = 0o2000000; | ||
| 175 | |||
| 176 | pub const ASYNC = 0o20000; | ||
| 177 | pub const DIRECT = 0o40000; | ||
| 178 | pub const LARGEFILE = 0o100000; | ||
| 179 | pub const NOATIME = 0o1000000; | ||
| 180 | pub const PATH = 0o10000000; | ||
| 181 | pub const TMPFILE = 0o20200000; | ||
| 182 | pub const NDELAY = NONBLOCK; | ||
| 183 | }; | ||
| 184 | |||
| 185 | pub const F = struct { | 162 | pub const F = struct { |
| 186 | pub const DUPFD = 0; | 163 | pub const DUPFD = 0; |
| 187 | pub const GETFD = 1; | 164 | pub const GETFD = 1; |
lib/std/os/linux/x86_64.zig-23| ... | @@ -131,29 +131,6 @@ pub const nlink_t = usize; | ... | @@ -131,29 +131,6 @@ pub const nlink_t = usize; |
| 131 | pub const blksize_t = isize; | 131 | pub const blksize_t = isize; |
| 132 | pub const blkcnt_t = isize; | 132 | pub const blkcnt_t = isize; |
| 133 | 133 | ||
| 134 | pub const O = struct { | ||
| 135 | pub const CREAT = 0o100; | ||
| 136 | pub const EXCL = 0o200; | ||
| 137 | pub const NOCTTY = 0o400; | ||
| 138 | pub const TRUNC = 0o1000; | ||
| 139 | pub const APPEND = 0o2000; | ||
| 140 | pub const NONBLOCK = 0o4000; | ||
| 141 | pub const DSYNC = 0o10000; | ||
| 142 | pub const SYNC = 0o4010000; | ||
| 143 | pub const RSYNC = 0o4010000; | ||
| 144 | pub const DIRECTORY = 0o200000; | ||
| 145 | pub const NOFOLLOW = 0o400000; | ||
| 146 | pub const CLOEXEC = 0o2000000; | ||
| 147 | |||
| 148 | pub const ASYNC = 0o20000; | ||
| 149 | pub const DIRECT = 0o40000; | ||
| 150 | pub const LARGEFILE = 0; | ||
| 151 | pub const NOATIME = 0o1000000; | ||
| 152 | pub const PATH = 0o10000000; | ||
| 153 | pub const TMPFILE = 0o20200000; | ||
| 154 | pub const NDELAY = NONBLOCK; | ||
| 155 | }; | ||
| 156 | |||
| 157 | pub const F = struct { | 134 | pub const F = struct { |
| 158 | pub const DUPFD = 0; | 135 | pub const DUPFD = 0; |
| 159 | pub const GETFD = 1; | 136 | pub const GETFD = 1; |
lib/std/os/plan9.zig+17-11| ... | @@ -242,17 +242,23 @@ pub fn close(fd: i32) usize { | ... | @@ -242,17 +242,23 @@ pub fn close(fd: i32) usize { |
| 242 | return syscall_bits.syscall1(.CLOSE, @bitCast(@as(isize, fd))); | 242 | return syscall_bits.syscall1(.CLOSE, @bitCast(@as(isize, fd))); |
| 243 | } | 243 | } |
| 244 | pub const mode_t = i32; | 244 | pub const mode_t = i32; |
| 245 | pub const O = struct { | 245 | |
| 246 | pub const READ = 0; // open for read | 246 | pub const AccessMode = enum(u2) { |
| 247 | pub const RDONLY = 0; | 247 | RDONLY, |
| 248 | pub const WRITE = 1; // write | 248 | WRONLY, |
| 249 | pub const WRONLY = 1; | 249 | RDWR, |
| 250 | pub const RDWR = 2; // read and write | 250 | EXEC, |
| 251 | pub const EXEC = 3; // execute, == read but check execute permission | 251 | }; |
| 252 | pub const TRUNC = 16; // or'ed in (except for exec), truncate file first | 252 | |
| 253 | pub const CEXEC = 32; // or'ed in (per file descriptor), close on exec | 253 | pub const O = packed struct(u32) { |
| 254 | pub const RCLOSE = 64; // or'ed in, remove on close | 254 | access: AccessMode, |
| 255 | pub const EXCL = 0x1000; // or'ed in, exclusive create | 255 | _2: u2 = 0, |
| 256 | TRUNC: bool = false, | ||
| 257 | CEXEC: bool = false, | ||
| 258 | RCLOSE: bool = false, | ||
| 259 | _7: u5 = 0, | ||
| 260 | EXCL: bool = false, | ||
| 261 | _: u19 = 0, | ||
| 256 | }; | 262 | }; |
| 257 | 263 | ||
| 258 | pub const ExecData = struct { | 264 | pub const ExecData = struct { |
lib/std/os/test.zig+49-27| ... | @@ -87,6 +87,7 @@ test "chdir smoke test" { | ... | @@ -87,6 +87,7 @@ test "chdir smoke test" { |
| 87 | 87 | ||
| 88 | test "open smoke test" { | 88 | test "open smoke test" { |
| 89 | if (native_os == .wasi) return error.SkipZigTest; | 89 | if (native_os == .wasi) return error.SkipZigTest; |
| 90 | if (native_os == .windows) return error.SkipZigTest; | ||
| 90 | 91 | ||
| 91 | // TODO verify file attributes using `fstat` | 92 | // TODO verify file attributes using `fstat` |
| 92 | 93 | ||
| ... | @@ -109,21 +110,21 @@ test "open smoke test" { | ... | @@ -109,21 +110,21 @@ test "open smoke test" { |
| 109 | 110 | ||
| 110 | // Create some file using `open`. | 111 | // Create some file using `open`. |
| 111 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" }); | 112 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" }); |
| 112 | fd = try os.open(file_path, os.O.RDWR | os.O.CREAT | os.O.EXCL, mode); | 113 | fd = try os.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode); |
| 113 | os.close(fd); | 114 | os.close(fd); |
| 114 | 115 | ||
| 115 | // Try this again with the same flags. This op should fail with error.PathAlreadyExists. | 116 | // Try this again with the same flags. This op should fail with error.PathAlreadyExists. |
| 116 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" }); | 117 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" }); |
| 117 | try expectError(error.PathAlreadyExists, os.open(file_path, os.O.RDWR | os.O.CREAT | os.O.EXCL, mode)); | 118 | try expectError(error.PathAlreadyExists, os.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode)); |
| 118 | 119 | ||
| 119 | // Try opening without `O.EXCL` flag. | 120 | // Try opening without `EXCL` flag. |
| 120 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" }); | 121 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" }); |
| 121 | fd = try os.open(file_path, os.O.RDWR | os.O.CREAT, mode); | 122 | fd = try os.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true }, mode); |
| 122 | os.close(fd); | 123 | os.close(fd); |
| 123 | 124 | ||
| 124 | // Try opening as a directory which should fail. | 125 | // Try opening as a directory which should fail. |
| 125 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" }); | 126 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" }); |
| 126 | try expectError(error.NotDir, os.open(file_path, os.O.RDWR | os.O.DIRECTORY, mode)); | 127 | try expectError(error.NotDir, os.open(file_path, .{ .ACCMODE = .RDWR, .DIRECTORY = true }, mode)); |
| 127 | 128 | ||
| 128 | // Create some directory | 129 | // Create some directory |
| 129 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" }); | 130 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" }); |
| ... | @@ -131,16 +132,17 @@ test "open smoke test" { | ... | @@ -131,16 +132,17 @@ test "open smoke test" { |
| 131 | 132 | ||
| 132 | // Open dir using `open` | 133 | // Open dir using `open` |
| 133 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" }); | 134 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" }); |
| 134 | fd = try os.open(file_path, os.O.RDONLY | os.O.DIRECTORY, mode); | 135 | fd = try os.open(file_path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, mode); |
| 135 | os.close(fd); | 136 | os.close(fd); |
| 136 | 137 | ||
| 137 | // Try opening as file which should fail. | 138 | // Try opening as file which should fail. |
| 138 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" }); | 139 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" }); |
| 139 | try expectError(error.IsDir, os.open(file_path, os.O.RDWR, mode)); | 140 | try expectError(error.IsDir, os.open(file_path, .{ .ACCMODE = .RDWR }, mode)); |
| 140 | } | 141 | } |
| 141 | 142 | ||
| 142 | test "openat smoke test" { | 143 | test "openat smoke test" { |
| 143 | if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest; | 144 | if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest; |
| 145 | if (native_os == .windows) return error.SkipZigTest; | ||
| 144 | 146 | ||
| 145 | // TODO verify file attributes using `fstatat` | 147 | // TODO verify file attributes using `fstatat` |
| 146 | 148 | ||
| ... | @@ -151,28 +153,47 @@ test "openat smoke test" { | ... | @@ -151,28 +153,47 @@ test "openat smoke test" { |
| 151 | const mode: os.mode_t = if (native_os == .windows) 0 else 0o666; | 153 | const mode: os.mode_t = if (native_os == .windows) 0 else 0o666; |
| 152 | 154 | ||
| 153 | // Create some file using `openat`. | 155 | // Create some file using `openat`. |
| 154 | fd = try os.openat(tmp.dir.fd, "some_file", os.O.RDWR | os.O.CREAT | os.O.EXCL, mode); | 156 | fd = try os.openat(tmp.dir.fd, "some_file", os.CommonOpenFlags.lower(.{ |
| 157 | .ACCMODE = .RDWR, | ||
| 158 | .CREAT = true, | ||
| 159 | .EXCL = true, | ||
| 160 | }), mode); | ||
| 155 | os.close(fd); | 161 | os.close(fd); |
| 156 | 162 | ||
| 157 | // Try this again with the same flags. This op should fail with error.PathAlreadyExists. | 163 | // Try this again with the same flags. This op should fail with error.PathAlreadyExists. |
| 158 | try expectError(error.PathAlreadyExists, os.openat(tmp.dir.fd, "some_file", os.O.RDWR | os.O.CREAT | os.O.EXCL, mode)); | 164 | try expectError(error.PathAlreadyExists, os.openat(tmp.dir.fd, "some_file", os.CommonOpenFlags.lower(.{ |
| 159 | 165 | .ACCMODE = .RDWR, | |
| 160 | // Try opening without `O.EXCL` flag. | 166 | .CREAT = true, |
| 161 | fd = try os.openat(tmp.dir.fd, "some_file", os.O.RDWR | os.O.CREAT, mode); | 167 | .EXCL = true, |
| 168 | }), mode)); | ||
| 169 | |||
| 170 | // Try opening without `EXCL` flag. | ||
| 171 | fd = try os.openat(tmp.dir.fd, "some_file", os.CommonOpenFlags.lower(.{ | ||
| 172 | .ACCMODE = .RDWR, | ||
| 173 | .CREAT = true, | ||
| 174 | }), mode); | ||
| 162 | os.close(fd); | 175 | os.close(fd); |
| 163 | 176 | ||
| 164 | // Try opening as a directory which should fail. | 177 | // Try opening as a directory which should fail. |
| 165 | try expectError(error.NotDir, os.openat(tmp.dir.fd, "some_file", os.O.RDWR | os.O.DIRECTORY, mode)); | 178 | try expectError(error.NotDir, os.openat(tmp.dir.fd, "some_file", os.CommonOpenFlags.lower(.{ |
| 179 | .ACCMODE = .RDWR, | ||
| 180 | .DIRECTORY = true, | ||
| 181 | }), mode)); | ||
| 166 | 182 | ||
| 167 | // Create some directory | 183 | // Create some directory |
| 168 | try os.mkdirat(tmp.dir.fd, "some_dir", mode); | 184 | try os.mkdirat(tmp.dir.fd, "some_dir", mode); |
| 169 | 185 | ||
| 170 | // Open dir using `open` | 186 | // Open dir using `open` |
| 171 | fd = try os.openat(tmp.dir.fd, "some_dir", os.O.RDONLY | os.O.DIRECTORY, mode); | 187 | fd = try os.openat(tmp.dir.fd, "some_dir", os.CommonOpenFlags.lower(.{ |
| 188 | .ACCMODE = .RDONLY, | ||
| 189 | .DIRECTORY = true, | ||
| 190 | }), mode); | ||
| 172 | os.close(fd); | 191 | os.close(fd); |
| 173 | 192 | ||
| 174 | // Try opening as file which should fail. | 193 | // Try opening as file which should fail. |
| 175 | try expectError(error.IsDir, os.openat(tmp.dir.fd, "some_dir", os.O.RDWR, mode)); | 194 | try expectError(error.IsDir, os.openat(tmp.dir.fd, "some_dir", os.CommonOpenFlags.lower(.{ |
| 195 | .ACCMODE = .RDWR, | ||
| 196 | }), mode)); | ||
| 176 | } | 197 | } |
| 177 | 198 | ||
| 178 | test "symlink with relative paths" { | 199 | test "symlink with relative paths" { |
| ... | @@ -688,7 +709,7 @@ test "fcntl" { | ... | @@ -688,7 +709,7 @@ test "fcntl" { |
| 688 | tmp.dir.deleteFile(test_out_file) catch {}; | 709 | tmp.dir.deleteFile(test_out_file) catch {}; |
| 689 | } | 710 | } |
| 690 | 711 | ||
| 691 | // Note: The test assumes createFile opens the file with O.CLOEXEC | 712 | // Note: The test assumes createFile opens the file with CLOEXEC |
| 692 | { | 713 | { |
| 693 | const flags = try os.fcntl(file.handle, os.F.GETFD, 0); | 714 | const flags = try os.fcntl(file.handle, os.F.GETFD, 0); |
| 694 | try expect((flags & os.FD_CLOEXEC) != 0); | 715 | try expect((flags & os.FD_CLOEXEC) != 0); |
| ... | @@ -987,6 +1008,7 @@ test "POSIX file locking with fcntl" { | ... | @@ -987,6 +1008,7 @@ test "POSIX file locking with fcntl" { |
| 987 | 1008 | ||
| 988 | test "rename smoke test" { | 1009 | test "rename smoke test" { |
| 989 | if (native_os == .wasi) return error.SkipZigTest; | 1010 | if (native_os == .wasi) return error.SkipZigTest; |
| 1011 | if (native_os == .windows) return error.SkipZigTest; | ||
| 990 | 1012 | ||
| 991 | var tmp = tmpDir(.{}); | 1013 | var tmp = tmpDir(.{}); |
| 992 | defer tmp.cleanup(); | 1014 | defer tmp.cleanup(); |
| ... | @@ -1007,7 +1029,7 @@ test "rename smoke test" { | ... | @@ -1007,7 +1029,7 @@ test "rename smoke test" { |
| 1007 | 1029 | ||
| 1008 | // Create some file using `open`. | 1030 | // Create some file using `open`. |
| 1009 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" }); | 1031 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" }); |
| 1010 | fd = try os.open(file_path, os.O.RDWR | os.O.CREAT | os.O.EXCL, mode); | 1032 | fd = try os.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode); |
| 1011 | os.close(fd); | 1033 | os.close(fd); |
| 1012 | 1034 | ||
| 1013 | // Rename the file | 1035 | // Rename the file |
| ... | @@ -1016,12 +1038,12 @@ test "rename smoke test" { | ... | @@ -1016,12 +1038,12 @@ test "rename smoke test" { |
| 1016 | 1038 | ||
| 1017 | // Try opening renamed file | 1039 | // Try opening renamed file |
| 1018 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_other_file" }); | 1040 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_other_file" }); |
| 1019 | fd = try os.open(file_path, os.O.RDWR, mode); | 1041 | fd = try os.open(file_path, .{ .ACCMODE = .RDWR }, mode); |
| 1020 | os.close(fd); | 1042 | os.close(fd); |
| 1021 | 1043 | ||
| 1022 | // Try opening original file - should fail with error.FileNotFound | 1044 | // Try opening original file - should fail with error.FileNotFound |
| 1023 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" }); | 1045 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" }); |
| 1024 | try expectError(error.FileNotFound, os.open(file_path, os.O.RDWR, mode)); | 1046 | try expectError(error.FileNotFound, os.open(file_path, .{ .ACCMODE = .RDWR }, mode)); |
| 1025 | 1047 | ||
| 1026 | // Create some directory | 1048 | // Create some directory |
| 1027 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" }); | 1049 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" }); |
| ... | @@ -1033,16 +1055,17 @@ test "rename smoke test" { | ... | @@ -1033,16 +1055,17 @@ test "rename smoke test" { |
| 1033 | 1055 | ||
| 1034 | // Try opening renamed directory | 1056 | // Try opening renamed directory |
| 1035 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_other_dir" }); | 1057 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_other_dir" }); |
| 1036 | fd = try os.open(file_path, os.O.RDONLY | os.O.DIRECTORY, mode); | 1058 | fd = try os.open(file_path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, mode); |
| 1037 | os.close(fd); | 1059 | os.close(fd); |
| 1038 | 1060 | ||
| 1039 | // Try opening original directory - should fail with error.FileNotFound | 1061 | // Try opening original directory - should fail with error.FileNotFound |
| 1040 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" }); | 1062 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_dir" }); |
| 1041 | try expectError(error.FileNotFound, os.open(file_path, os.O.RDONLY | os.O.DIRECTORY, mode)); | 1063 | try expectError(error.FileNotFound, os.open(file_path, .{ .ACCMODE = .RDONLY, .DIRECTORY = true }, mode)); |
| 1042 | } | 1064 | } |
| 1043 | 1065 | ||
| 1044 | test "access smoke test" { | 1066 | test "access smoke test" { |
| 1045 | if (native_os == .wasi) return error.SkipZigTest; | 1067 | if (native_os == .wasi) return error.SkipZigTest; |
| 1068 | if (native_os == .windows) return error.SkipZigTest; | ||
| 1046 | 1069 | ||
| 1047 | var tmp = tmpDir(.{}); | 1070 | var tmp = tmpDir(.{}); |
| 1048 | defer tmp.cleanup(); | 1071 | defer tmp.cleanup(); |
| ... | @@ -1063,7 +1086,7 @@ test "access smoke test" { | ... | @@ -1063,7 +1086,7 @@ test "access smoke test" { |
| 1063 | 1086 | ||
| 1064 | // Create some file using `open`. | 1087 | // Create some file using `open`. |
| 1065 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" }); | 1088 | file_path = try fs.path.join(allocator, &[_][]const u8{ base_path, "some_file" }); |
| 1066 | fd = try os.open(file_path, os.O.RDWR | os.O.CREAT | os.O.EXCL, mode); | 1089 | fd = try os.open(file_path, .{ .ACCMODE = .RDWR, .CREAT = true, .EXCL = true }, mode); |
| 1067 | os.close(fd); | 1090 | os.close(fd); |
| 1068 | 1091 | ||
| 1069 | // Try to access() the file | 1092 | // Try to access() the file |
| ... | @@ -1088,16 +1111,15 @@ test "access smoke test" { | ... | @@ -1088,16 +1111,15 @@ test "access smoke test" { |
| 1088 | } | 1111 | } |
| 1089 | 1112 | ||
| 1090 | test "timerfd" { | 1113 | test "timerfd" { |
| 1091 | if (native_os != .linux) | 1114 | if (native_os != .linux) return error.SkipZigTest; |
| 1092 | return error.SkipZigTest; | ||
| 1093 | 1115 | ||
| 1094 | const linux = os.linux; | 1116 | const linux = os.linux; |
| 1095 | const tfd = try os.timerfd_create(linux.CLOCK.MONOTONIC, linux.TFD.CLOEXEC); | 1117 | const tfd = try os.timerfd_create(linux.CLOCK.MONOTONIC, .{ .CLOEXEC = true }); |
| 1096 | defer os.close(tfd); | 1118 | defer os.close(tfd); |
| 1097 | 1119 | ||
| 1098 | // Fire event 10_000_000ns = 10ms after the os.timerfd_settime call. | 1120 | // Fire event 10_000_000ns = 10ms after the os.timerfd_settime call. |
| 1099 | var sit: linux.itimerspec = .{ .it_interval = .{ .tv_sec = 0, .tv_nsec = 0 }, .it_value = .{ .tv_sec = 0, .tv_nsec = 10 * (1000 * 1000) } }; | 1121 | var sit: linux.itimerspec = .{ .it_interval = .{ .tv_sec = 0, .tv_nsec = 0 }, .it_value = .{ .tv_sec = 0, .tv_nsec = 10 * (1000 * 1000) } }; |
| 1100 | try os.timerfd_settime(tfd, 0, &sit, null); | 1122 | try os.timerfd_settime(tfd, .{}, &sit, null); |
| 1101 | 1123 | ||
| 1102 | var fds: [1]os.pollfd = .{.{ .fd = tfd, .events = os.linux.POLL.IN, .revents = 0 }}; | 1124 | var fds: [1]os.pollfd = .{.{ .fd = tfd, .events = os.linux.POLL.IN, .revents = 0 }}; |
| 1103 | try expectEqual(@as(usize, 1), try os.poll(&fds, -1)); // -1 => infinite waiting | 1125 | try expectEqual(@as(usize, 1), try os.poll(&fds, -1)); // -1 => infinite waiting |
| ... | @@ -1232,7 +1254,7 @@ test "fchmodat smoke test" { | ... | @@ -1232,7 +1254,7 @@ test "fchmodat smoke test" { |
| 1232 | const fd = try os.openat( | 1254 | const fd = try os.openat( |
| 1233 | tmp.dir.fd, | 1255 | tmp.dir.fd, |
| 1234 | "regfile", | 1256 | "regfile", |
| 1235 | os.O.WRONLY | os.O.CREAT | os.O.EXCL | os.O.TRUNC, | 1257 | .{ .ACCMODE = .WRONLY, .CREAT = true, .EXCL = true, .TRUNC = true }, |
| 1236 | 0o644, | 1258 | 0o644, |
| 1237 | ); | 1259 | ); |
| 1238 | os.close(fd); | 1260 | os.close(fd); |
lib/std/os/wasi.zig+121-268| ... | @@ -1,6 +1,7 @@ | ... | @@ -1,6 +1,7 @@ |
| 1 | // wasi_snapshot_preview1 spec available (in witx format) here: | 1 | //! wasi_snapshot_preview1 spec available (in witx format) here: |
| 2 | // * typenames -- https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/witx/typenames.witx | 2 | //! * typenames -- https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/witx/typenames.witx |
| 3 | // * module -- https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/witx/wasi_snapshot_preview1.witx | 3 | //! * module -- https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/witx/wasi_snapshot_preview1.witx |
| 4 | //! Note that libc API does *not* go in this file. wasi libc API goes into std/c/wasi.zig instead. | ||
| 4 | const builtin = @import("builtin"); | 5 | const builtin = @import("builtin"); |
| 5 | const std = @import("std"); | 6 | const std = @import("std"); |
| 6 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| ... | @@ -16,11 +17,6 @@ comptime { | ... | @@ -16,11 +17,6 @@ comptime { |
| 16 | // assert(@alignOf(u64) == 8); | 17 | // assert(@alignOf(u64) == 8); |
| 17 | } | 18 | } |
| 18 | 19 | ||
| 19 | pub const F_OK = 0; | ||
| 20 | pub const X_OK = 1; | ||
| 21 | pub const W_OK = 2; | ||
| 22 | pub const R_OK = 4; | ||
| 23 | |||
| 24 | pub const iovec_t = std.os.iovec; | 20 | pub const iovec_t = std.os.iovec; |
| 25 | pub const ciovec_t = std.os.iovec_const; | 21 | pub const ciovec_t = std.os.iovec_const; |
| 26 | 22 | ||
| ... | @@ -82,106 +78,22 @@ pub extern "wasi_snapshot_preview1" fn sock_recv(sock: fd_t, ri_data: [*]iovec_t | ... | @@ -82,106 +78,22 @@ pub extern "wasi_snapshot_preview1" fn sock_recv(sock: fd_t, ri_data: [*]iovec_t |
| 82 | pub extern "wasi_snapshot_preview1" fn sock_send(sock: fd_t, si_data: [*]const ciovec_t, si_data_len: usize, si_flags: siflags_t, so_datalen: *usize) errno_t; | 78 | pub extern "wasi_snapshot_preview1" fn sock_send(sock: fd_t, si_data: [*]const ciovec_t, si_data_len: usize, si_flags: siflags_t, so_datalen: *usize) errno_t; |
| 83 | pub extern "wasi_snapshot_preview1" fn sock_shutdown(sock: fd_t, how: sdflags_t) errno_t; | 79 | pub extern "wasi_snapshot_preview1" fn sock_shutdown(sock: fd_t, how: sdflags_t) errno_t; |
| 84 | 80 | ||
| 85 | /// Get the errno from a syscall return value, or 0 for no error. | ||
| 86 | pub fn getErrno(r: errno_t) errno_t { | ||
| 87 | return r; | ||
| 88 | } | ||
| 89 | |||
| 90 | pub const STDIN_FILENO = 0; | ||
| 91 | pub const STDOUT_FILENO = 1; | ||
| 92 | pub const STDERR_FILENO = 2; | ||
| 93 | |||
| 94 | pub const mode_t = u32; | ||
| 95 | |||
| 96 | pub const time_t = i64; // match https://github.com/CraneStation/wasi-libc | ||
| 97 | |||
| 98 | pub const timespec = extern struct { | ||
| 99 | tv_sec: time_t, | ||
| 100 | tv_nsec: isize, | ||
| 101 | |||
| 102 | pub fn fromTimestamp(tm: timestamp_t) timespec { | ||
| 103 | const tv_sec: timestamp_t = tm / 1_000_000_000; | ||
| 104 | const tv_nsec = tm - tv_sec * 1_000_000_000; | ||
| 105 | return timespec{ | ||
| 106 | .tv_sec = @as(time_t, @intCast(tv_sec)), | ||
| 107 | .tv_nsec = @as(isize, @intCast(tv_nsec)), | ||
| 108 | }; | ||
| 109 | } | ||
| 110 | |||
| 111 | pub fn toTimestamp(ts: timespec) timestamp_t { | ||
| 112 | const tm = @as(timestamp_t, @intCast(ts.tv_sec * 1_000_000_000)) + @as(timestamp_t, @intCast(ts.tv_nsec)); | ||
| 113 | return tm; | ||
| 114 | } | ||
| 115 | }; | ||
| 116 | |||
| 117 | pub const Stat = struct { | ||
| 118 | dev: device_t, | ||
| 119 | ino: inode_t, | ||
| 120 | mode: mode_t, | ||
| 121 | filetype: filetype_t, | ||
| 122 | nlink: linkcount_t, | ||
| 123 | size: filesize_t, | ||
| 124 | atim: timespec, | ||
| 125 | mtim: timespec, | ||
| 126 | ctim: timespec, | ||
| 127 | |||
| 128 | const Self = @This(); | ||
| 129 | |||
| 130 | pub fn fromFilestat(stat: filestat_t) Self { | ||
| 131 | return Self{ | ||
| 132 | .dev = stat.dev, | ||
| 133 | .ino = stat.ino, | ||
| 134 | .mode = 0, | ||
| 135 | .filetype = stat.filetype, | ||
| 136 | .nlink = stat.nlink, | ||
| 137 | .size = stat.size, | ||
| 138 | .atim = stat.atime(), | ||
| 139 | .mtim = stat.mtime(), | ||
| 140 | .ctim = stat.ctime(), | ||
| 141 | }; | ||
| 142 | } | ||
| 143 | |||
| 144 | pub fn atime(self: Self) timespec { | ||
| 145 | return self.atim; | ||
| 146 | } | ||
| 147 | |||
| 148 | pub fn mtime(self: Self) timespec { | ||
| 149 | return self.mtim; | ||
| 150 | } | ||
| 151 | |||
| 152 | pub fn ctime(self: Self) timespec { | ||
| 153 | return self.ctim; | ||
| 154 | } | ||
| 155 | }; | ||
| 156 | |||
| 157 | pub const IOV_MAX = 1024; | ||
| 158 | |||
| 159 | pub const AT = struct { | ||
| 160 | pub const REMOVEDIR: u32 = 0x4; | ||
| 161 | /// When linking libc, we follow their convention and use -2 for current working directory. | ||
| 162 | /// However, without libc, Zig does a different convention: it assumes the | ||
| 163 | /// current working directory is the first preopen. This behavior can be | ||
| 164 | /// overridden with a public function called `wasi_cwd` in the root source | ||
| 165 | /// file. | ||
| 166 | pub const FDCWD: fd_t = if (builtin.link_libc) -2 else 3; | ||
| 167 | }; | ||
| 168 | |||
| 169 | // As defined in the wasi_snapshot_preview1 spec file: | 81 | // As defined in the wasi_snapshot_preview1 spec file: |
| 170 | // https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/typenames.witx | 82 | // https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/witx/typenames.witx |
| 171 | pub const advice_t = u8; | 83 | pub const advice_t = enum(u8) { |
| 172 | pub const ADVICE_NORMAL: advice_t = 0; | 84 | NORMAL = 0, |
| 173 | pub const ADVICE_SEQUENTIAL: advice_t = 1; | 85 | SEQUENTIAL = 1, |
| 174 | pub const ADVICE_RANDOM: advice_t = 2; | 86 | RANDOM = 2, |
| 175 | pub const ADVICE_WILLNEED: advice_t = 3; | 87 | WILLNEED = 3, |
| 176 | pub const ADVICE_DONTNEED: advice_t = 4; | 88 | DONTNEED = 4, |
| 177 | pub const ADVICE_NOREUSE: advice_t = 5; | 89 | NOREUSE = 5, |
| 178 | 90 | }; | |
| 179 | pub const clockid_t = u32; | 91 | |
| 180 | pub const CLOCK = struct { | 92 | pub const clockid_t = enum(u32) { |
| 181 | pub const REALTIME: clockid_t = 0; | 93 | REALTIME = 0, |
| 182 | pub const MONOTONIC: clockid_t = 1; | 94 | MONOTONIC = 1, |
| 183 | pub const PROCESS_CPUTIME_ID: clockid_t = 2; | 95 | PROCESS_CPUTIME_ID = 2, |
| 184 | pub const THREAD_CPUTIME_ID: clockid_t = 3; | 96 | THREAD_CPUTIME_ID = 3, |
| 185 | }; | 97 | }; |
| 186 | 98 | ||
| 187 | pub const device_t = u64; | 99 | pub const device_t = u64; |
| ... | @@ -192,10 +104,10 @@ pub const DIRCOOKIE_START: dircookie_t = 0; | ... | @@ -192,10 +104,10 @@ pub const DIRCOOKIE_START: dircookie_t = 0; |
| 192 | pub const dirnamlen_t = u32; | 104 | pub const dirnamlen_t = u32; |
| 193 | 105 | ||
| 194 | pub const dirent_t = extern struct { | 106 | pub const dirent_t = extern struct { |
| 195 | d_next: dircookie_t, | 107 | next: dircookie_t, |
| 196 | d_ino: inode_t, | 108 | ino: inode_t, |
| 197 | d_namlen: dirnamlen_t, | 109 | namlen: dirnamlen_t, |
| 198 | d_type: filetype_t, | 110 | type: filetype_t, |
| 199 | }; | 111 | }; |
| 200 | 112 | ||
| 201 | pub const errno_t = enum(u16) { | 113 | pub const errno_t = enum(u16) { |
| ... | @@ -280,7 +192,6 @@ pub const errno_t = enum(u16) { | ... | @@ -280,7 +192,6 @@ pub const errno_t = enum(u16) { |
| 280 | NOTCAPABLE = 76, | 192 | NOTCAPABLE = 76, |
| 281 | _, | 193 | _, |
| 282 | }; | 194 | }; |
| 283 | pub const E = errno_t; | ||
| 284 | 195 | ||
| 285 | pub const event_t = extern struct { | 196 | pub const event_t = extern struct { |
| 286 | userdata: userdata_t, | 197 | userdata: userdata_t, |
| ... | @@ -297,22 +208,23 @@ pub const eventfdreadwrite_t = extern struct { | ... | @@ -297,22 +208,23 @@ pub const eventfdreadwrite_t = extern struct { |
| 297 | pub const eventrwflags_t = u16; | 208 | pub const eventrwflags_t = u16; |
| 298 | pub const EVENT_FD_READWRITE_HANGUP: eventrwflags_t = 0x0001; | 209 | pub const EVENT_FD_READWRITE_HANGUP: eventrwflags_t = 0x0001; |
| 299 | 210 | ||
| 300 | pub const eventtype_t = u8; | 211 | pub const eventtype_t = enum(u8) { |
| 301 | pub const EVENTTYPE_CLOCK: eventtype_t = 0; | 212 | CLOCK = 0, |
| 302 | pub const EVENTTYPE_FD_READ: eventtype_t = 1; | 213 | FD_READ = 1, |
| 303 | pub const EVENTTYPE_FD_WRITE: eventtype_t = 2; | 214 | FD_WRITE = 2, |
| 215 | }; | ||
| 304 | 216 | ||
| 305 | pub const exitcode_t = u32; | 217 | pub const exitcode_t = u32; |
| 306 | 218 | ||
| 307 | pub const fd_t = i32; | 219 | pub const fd_t = i32; |
| 308 | 220 | ||
| 309 | pub const fdflags_t = u16; | 221 | pub const fdflags_t = packed struct(u16) { |
| 310 | pub const FDFLAG = struct { | 222 | APPEND: bool = false, |
| 311 | pub const APPEND: fdflags_t = 0x0001; | 223 | DSYNC: bool = false, |
| 312 | pub const DSYNC: fdflags_t = 0x0002; | 224 | NONBLOCK: bool = false, |
| 313 | pub const NONBLOCK: fdflags_t = 0x0004; | 225 | RSYNC: bool = false, |
| 314 | pub const RSYNC: fdflags_t = 0x0008; | 226 | SYNC: bool = false, |
| 315 | pub const SYNC: fdflags_t = 0x0010; | 227 | _: u11 = 0, |
| 316 | }; | 228 | }; |
| 317 | 229 | ||
| 318 | pub const fdstat_t = extern struct { | 230 | pub const fdstat_t = extern struct { |
| ... | @@ -335,21 +247,8 @@ pub const filestat_t = extern struct { | ... | @@ -335,21 +247,8 @@ pub const filestat_t = extern struct { |
| 335 | atim: timestamp_t, | 247 | atim: timestamp_t, |
| 336 | mtim: timestamp_t, | 248 | mtim: timestamp_t, |
| 337 | ctim: timestamp_t, | 249 | ctim: timestamp_t, |
| 338 | |||
| 339 | pub fn atime(self: filestat_t) timespec { | ||
| 340 | return timespec.fromTimestamp(self.atim); | ||
| 341 | } | ||
| 342 | |||
| 343 | pub fn mtime(self: filestat_t) timespec { | ||
| 344 | return timespec.fromTimestamp(self.mtim); | ||
| 345 | } | ||
| 346 | |||
| 347 | pub fn ctime(self: filestat_t) timespec { | ||
| 348 | return timespec.fromTimestamp(self.ctim); | ||
| 349 | } | ||
| 350 | }; | 250 | }; |
| 351 | 251 | ||
| 352 | /// Also known as `FILETYPE`. | ||
| 353 | pub const filetype_t = enum(u8) { | 252 | pub const filetype_t = enum(u8) { |
| 354 | UNKNOWN, | 253 | UNKNOWN, |
| 355 | BLOCK_DEVICE, | 254 | BLOCK_DEVICE, |
| ... | @@ -362,26 +261,29 @@ pub const filetype_t = enum(u8) { | ... | @@ -362,26 +261,29 @@ pub const filetype_t = enum(u8) { |
| 362 | _, | 261 | _, |
| 363 | }; | 262 | }; |
| 364 | 263 | ||
| 365 | pub const fstflags_t = u16; | 264 | pub const fstflags_t = packed struct(u16) { |
| 366 | pub const FILESTAT_SET_ATIM: fstflags_t = 0x0001; | 265 | ATIM: bool = false, |
| 367 | pub const FILESTAT_SET_ATIM_NOW: fstflags_t = 0x0002; | 266 | ATIM_NOW: bool = false, |
| 368 | pub const FILESTAT_SET_MTIM: fstflags_t = 0x0004; | 267 | MTIM: bool = false, |
| 369 | pub const FILESTAT_SET_MTIM_NOW: fstflags_t = 0x0008; | 268 | MTIM_NOW: bool = false, |
| 269 | _: u12 = 0, | ||
| 270 | }; | ||
| 370 | 271 | ||
| 371 | pub const inode_t = u64; | 272 | pub const inode_t = u64; |
| 372 | pub const ino_t = inode_t; | ||
| 373 | 273 | ||
| 374 | pub const linkcount_t = u64; | 274 | pub const linkcount_t = u64; |
| 375 | 275 | ||
| 376 | pub const lookupflags_t = u32; | 276 | pub const lookupflags_t = packed struct(u32) { |
| 377 | pub const LOOKUP_SYMLINK_FOLLOW: lookupflags_t = 0x00000001; | 277 | SYMLINK_FOLLOW: bool = false, |
| 278 | _: u31 = 0, | ||
| 279 | }; | ||
| 378 | 280 | ||
| 379 | pub const oflags_t = u16; | 281 | pub const oflags_t = packed struct(u16) { |
| 380 | pub const O = struct { | 282 | CREAT: bool = false, |
| 381 | pub const CREAT: oflags_t = 0x0001; | 283 | DIRECTORY: bool = false, |
| 382 | pub const DIRECTORY: oflags_t = 0x0002; | 284 | EXCL: bool = false, |
| 383 | pub const EXCL: oflags_t = 0x0004; | 285 | TRUNC: bool = false, |
| 384 | pub const TRUNC: oflags_t = 0x0008; | 286 | _: u12 = 0, |
| 385 | }; | 287 | }; |
| 386 | 288 | ||
| 387 | pub const preopentype_t = u8; | 289 | pub const preopentype_t = u8; |
| ... | @@ -410,110 +312,81 @@ pub const SOCK = struct { | ... | @@ -410,110 +312,81 @@ pub const SOCK = struct { |
| 410 | pub const RECV_DATA_TRUNCATED: roflags_t = 0x0001; | 312 | pub const RECV_DATA_TRUNCATED: roflags_t = 0x0001; |
| 411 | }; | 313 | }; |
| 412 | 314 | ||
| 413 | pub const rights_t = u64; | 315 | pub const rights_t = packed struct(u64) { |
| 414 | pub const RIGHT = struct { | 316 | FD_DATASYNC: bool = false, |
| 415 | pub const FD_DATASYNC: rights_t = 0x0000000000000001; | 317 | FD_READ: bool = false, |
| 416 | pub const FD_READ: rights_t = 0x0000000000000002; | 318 | FD_SEEK: bool = false, |
| 417 | pub const FD_SEEK: rights_t = 0x0000000000000004; | 319 | FD_FDSTAT_SET_FLAGS: bool = false, |
| 418 | pub const FD_FDSTAT_SET_FLAGS: rights_t = 0x0000000000000008; | 320 | FD_SYNC: bool = false, |
| 419 | pub const FD_SYNC: rights_t = 0x0000000000000010; | 321 | FD_TELL: bool = false, |
| 420 | pub const FD_TELL: rights_t = 0x0000000000000020; | 322 | FD_WRITE: bool = false, |
| 421 | pub const FD_WRITE: rights_t = 0x0000000000000040; | 323 | FD_ADVISE: bool = false, |
| 422 | pub const FD_ADVISE: rights_t = 0x0000000000000080; | 324 | FD_ALLOCATE: bool = false, |
| 423 | pub const FD_ALLOCATE: rights_t = 0x0000000000000100; | 325 | PATH_CREATE_DIRECTORY: bool = false, |
| 424 | pub const PATH_CREATE_DIRECTORY: rights_t = 0x0000000000000200; | 326 | PATH_CREATE_FILE: bool = false, |
| 425 | pub const PATH_CREATE_FILE: rights_t = 0x0000000000000400; | 327 | PATH_LINK_SOURCE: bool = false, |
| 426 | pub const PATH_LINK_SOURCE: rights_t = 0x0000000000000800; | 328 | PATH_LINK_TARGET: bool = false, |
| 427 | pub const PATH_LINK_TARGET: rights_t = 0x0000000000001000; | 329 | PATH_OPEN: bool = false, |
| 428 | pub const PATH_OPEN: rights_t = 0x0000000000002000; | 330 | FD_READDIR: bool = false, |
| 429 | pub const FD_READDIR: rights_t = 0x0000000000004000; | 331 | PATH_READLINK: bool = false, |
| 430 | pub const PATH_READLINK: rights_t = 0x0000000000008000; | 332 | PATH_RENAME_SOURCE: bool = false, |
| 431 | pub const PATH_RENAME_SOURCE: rights_t = 0x0000000000010000; | 333 | PATH_RENAME_TARGET: bool = false, |
| 432 | pub const PATH_RENAME_TARGET: rights_t = 0x0000000000020000; | 334 | PATH_FILESTAT_GET: bool = false, |
| 433 | pub const PATH_FILESTAT_GET: rights_t = 0x0000000000040000; | 335 | PATH_FILESTAT_SET_SIZE: bool = false, |
| 434 | pub const PATH_FILESTAT_SET_SIZE: rights_t = 0x0000000000080000; | 336 | PATH_FILESTAT_SET_TIMES: bool = false, |
| 435 | pub const PATH_FILESTAT_SET_TIMES: rights_t = 0x0000000000100000; | 337 | FD_FILESTAT_GET: bool = false, |
| 436 | pub const FD_FILESTAT_GET: rights_t = 0x0000000000200000; | 338 | FD_FILESTAT_SET_SIZE: bool = false, |
| 437 | pub const FD_FILESTAT_SET_SIZE: rights_t = 0x0000000000400000; | 339 | FD_FILESTAT_SET_TIMES: bool = false, |
| 438 | pub const FD_FILESTAT_SET_TIMES: rights_t = 0x0000000000800000; | 340 | PATH_SYMLINK: bool = false, |
| 439 | pub const PATH_SYMLINK: rights_t = 0x0000000001000000; | 341 | PATH_REMOVE_DIRECTORY: bool = false, |
| 440 | pub const PATH_REMOVE_DIRECTORY: rights_t = 0x0000000002000000; | 342 | PATH_UNLINK_FILE: bool = false, |
| 441 | pub const PATH_UNLINK_FILE: rights_t = 0x0000000004000000; | 343 | POLL_FD_READWRITE: bool = false, |
| 442 | pub const POLL_FD_READWRITE: rights_t = 0x0000000008000000; | 344 | SOCK_SHUTDOWN: bool = false, |
| 443 | pub const SOCK_SHUTDOWN: rights_t = 0x0000000010000000; | 345 | SOCK_ACCEPT: bool = false, |
| 444 | pub const SOCK_ACCEPT: rights_t = 0x0000000020000000; | 346 | _: u34 = 0, |
| 445 | pub const ALL: rights_t = FD_DATASYNC | | ||
| 446 | FD_READ | | ||
| 447 | FD_SEEK | | ||
| 448 | FD_FDSTAT_SET_FLAGS | | ||
| 449 | FD_SYNC | | ||
| 450 | FD_TELL | | ||
| 451 | FD_WRITE | | ||
| 452 | FD_ADVISE | | ||
| 453 | FD_ALLOCATE | | ||
| 454 | PATH_CREATE_DIRECTORY | | ||
| 455 | PATH_CREATE_FILE | | ||
| 456 | PATH_LINK_SOURCE | | ||
| 457 | PATH_LINK_TARGET | | ||
| 458 | PATH_OPEN | | ||
| 459 | FD_READDIR | | ||
| 460 | PATH_READLINK | | ||
| 461 | PATH_RENAME_SOURCE | | ||
| 462 | PATH_RENAME_TARGET | | ||
| 463 | PATH_FILESTAT_GET | | ||
| 464 | PATH_FILESTAT_SET_SIZE | | ||
| 465 | PATH_FILESTAT_SET_TIMES | | ||
| 466 | FD_FILESTAT_GET | | ||
| 467 | FD_FILESTAT_SET_SIZE | | ||
| 468 | FD_FILESTAT_SET_TIMES | | ||
| 469 | PATH_SYMLINK | | ||
| 470 | PATH_REMOVE_DIRECTORY | | ||
| 471 | PATH_UNLINK_FILE | | ||
| 472 | POLL_FD_READWRITE | | ||
| 473 | SOCK_SHUTDOWN | | ||
| 474 | SOCK_ACCEPT; | ||
| 475 | }; | 347 | }; |
| 476 | 348 | ||
| 477 | pub const sdflags_t = u8; | 349 | pub const sdflags_t = packed struct(u8) { |
| 478 | pub const SHUT = struct { | 350 | RD: bool = false, |
| 479 | pub const RD: sdflags_t = 0x01; | 351 | WR: bool = false, |
| 480 | pub const WR: sdflags_t = 0x02; | 352 | _: u6 = 0, |
| 481 | }; | 353 | }; |
| 482 | 354 | ||
| 483 | pub const siflags_t = u16; | 355 | pub const siflags_t = u16; |
| 484 | 356 | ||
| 485 | pub const signal_t = u8; | 357 | pub const signal_t = enum(u8) { |
| 486 | pub const SIGNONE: signal_t = 0; | 358 | NONE = 0, |
| 487 | pub const SIGHUP: signal_t = 1; | 359 | HUP = 1, |
| 488 | pub const SIGINT: signal_t = 2; | 360 | INT = 2, |
| 489 | pub const SIGQUIT: signal_t = 3; | 361 | QUIT = 3, |
| 490 | pub const SIGILL: signal_t = 4; | 362 | ILL = 4, |
| 491 | pub const SIGTRAP: signal_t = 5; | 363 | TRAP = 5, |
| 492 | pub const SIGABRT: signal_t = 6; | 364 | ABRT = 6, |
| 493 | pub const SIGBUS: signal_t = 7; | 365 | BUS = 7, |
| 494 | pub const SIGFPE: signal_t = 8; | 366 | FPE = 8, |
| 495 | pub const SIGKILL: signal_t = 9; | 367 | KILL = 9, |
| 496 | pub const SIGUSR1: signal_t = 10; | 368 | USR1 = 10, |
| 497 | pub const SIGSEGV: signal_t = 11; | 369 | SEGV = 11, |
| 498 | pub const SIGUSR2: signal_t = 12; | 370 | USR2 = 12, |
| 499 | pub const SIGPIPE: signal_t = 13; | 371 | PIPE = 13, |
| 500 | pub const SIGALRM: signal_t = 14; | 372 | ALRM = 14, |
| 501 | pub const SIGTERM: signal_t = 15; | 373 | TERM = 15, |
| 502 | pub const SIGCHLD: signal_t = 16; | 374 | CHLD = 16, |
| 503 | pub const SIGCONT: signal_t = 17; | 375 | CONT = 17, |
| 504 | pub const SIGSTOP: signal_t = 18; | 376 | STOP = 18, |
| 505 | pub const SIGTSTP: signal_t = 19; | 377 | TSTP = 19, |
| 506 | pub const SIGTTIN: signal_t = 20; | 378 | TTIN = 20, |
| 507 | pub const SIGTTOU: signal_t = 21; | 379 | TTOU = 21, |
| 508 | pub const SIGURG: signal_t = 22; | 380 | URG = 22, |
| 509 | pub const SIGXCPU: signal_t = 23; | 381 | XCPU = 23, |
| 510 | pub const SIGXFSZ: signal_t = 24; | 382 | XFSZ = 24, |
| 511 | pub const SIGVTALRM: signal_t = 25; | 383 | VTALRM = 25, |
| 512 | pub const SIGPROF: signal_t = 26; | 384 | PROF = 26, |
| 513 | pub const SIGWINCH: signal_t = 27; | 385 | WINCH = 27, |
| 514 | pub const SIGPOLL: signal_t = 28; | 386 | POLL = 28, |
| 515 | pub const SIGPWR: signal_t = 29; | 387 | PWR = 29, |
| 516 | pub const SIGSYS: signal_t = 30; | 388 | SYS = 30, |
| 389 | }; | ||
| 517 | 390 | ||
| 518 | pub const subclockflags_t = u16; | 391 | pub const subclockflags_t = u16; |
| 519 | pub const SUBSCRIPTION_CLOCK_ABSTIME: subclockflags_t = 0x0001; | 392 | pub const SUBSCRIPTION_CLOCK_ABSTIME: subclockflags_t = 0x0001; |
| ... | @@ -545,29 +418,9 @@ pub const subscription_u_u_t = extern union { | ... | @@ -545,29 +418,9 @@ pub const subscription_u_u_t = extern union { |
| 545 | fd_write: subscription_fd_readwrite_t, | 418 | fd_write: subscription_fd_readwrite_t, |
| 546 | }; | 419 | }; |
| 547 | 420 | ||
| 421 | /// Nanoseconds. | ||
| 548 | pub const timestamp_t = u64; | 422 | pub const timestamp_t = u64; |
| 549 | 423 | ||
| 550 | pub const userdata_t = u64; | 424 | pub const userdata_t = u64; |
| 551 | 425 | ||
| 552 | /// Also known as `WHENCE`. | ||
| 553 | pub const whence_t = enum(u8) { SET, CUR, END }; | 426 | pub const whence_t = enum(u8) { SET, CUR, END }; |
| 554 | |||
| 555 | pub const S = struct { | ||
| 556 | pub const IEXEC = @compileError("TODO audit this"); | ||
| 557 | pub const IFBLK = 0x6000; | ||
| 558 | pub const IFCHR = 0x2000; | ||
| 559 | pub const IFDIR = 0x4000; | ||
| 560 | pub const IFIFO = 0xc000; | ||
| 561 | pub const IFLNK = 0xa000; | ||
| 562 | pub const IFMT = IFBLK | IFCHR | IFDIR | IFIFO | IFLNK | IFREG | IFSOCK; | ||
| 563 | pub const IFREG = 0x8000; | ||
| 564 | // There's no concept of UNIX domain socket but we define this value here in order to line with other OSes. | ||
| 565 | pub const IFSOCK = 0x1; | ||
| 566 | }; | ||
| 567 | |||
| 568 | pub const LOCK = struct { | ||
| 569 | pub const SH = 0x1; | ||
| 570 | pub const EX = 0x2; | ||
| 571 | pub const NB = 0x4; | ||
| 572 | pub const UN = 0x8; | ||
| 573 | }; |
lib/std/std.zig+4-1| ... | @@ -142,7 +142,10 @@ pub const meta = @import("meta.zig"); | ... | @@ -142,7 +142,10 @@ pub const meta = @import("meta.zig"); |
| 142 | /// Networking. | 142 | /// Networking. |
| 143 | pub const net = @import("net.zig"); | 143 | pub const net = @import("net.zig"); |
| 144 | 144 | ||
| 145 | /// Wrappers around OS-specific APIs. | 145 | /// POSIX-like API layer. |
| 146 | pub const posix = @import("os.zig"); | ||
| 147 | |||
| 148 | /// Non-portable Operating System-specific API. | ||
| 146 | pub const os = @import("os.zig"); | 149 | pub const os = @import("os.zig"); |
| 147 | 150 | ||
| 148 | pub const once = @import("once.zig").once; | 151 | pub const once = @import("once.zig").once; |
lib/std/time.zig+63-64| ... | @@ -19,19 +19,17 @@ pub fn sleep(nanoseconds: u64) void { | ... | @@ -19,19 +19,17 @@ pub fn sleep(nanoseconds: u64) void { |
| 19 | if (builtin.os.tag == .wasi) { | 19 | if (builtin.os.tag == .wasi) { |
| 20 | const w = std.os.wasi; | 20 | const w = std.os.wasi; |
| 21 | const userdata: w.userdata_t = 0x0123_45678; | 21 | const userdata: w.userdata_t = 0x0123_45678; |
| 22 | const clock = w.subscription_clock_t{ | 22 | const clock: w.subscription_clock_t = .{ |
| 23 | .id = w.CLOCK.MONOTONIC, | 23 | .id = .MONOTONIC, |
| 24 | .timeout = nanoseconds, | 24 | .timeout = nanoseconds, |
| 25 | .precision = 0, | 25 | .precision = 0, |
| 26 | .flags = 0, | 26 | .flags = 0, |
| 27 | }; | 27 | }; |
| 28 | const in = w.subscription_t{ | 28 | const in: w.subscription_t = .{ |
| 29 | .userdata = userdata, | 29 | .userdata = userdata, |
| 30 | .u = w.subscription_u_t{ | 30 | .u = .{ |
| 31 | .tag = w.EVENTTYPE_CLOCK, | 31 | .tag = .CLOCK, |
| 32 | .u = w.subscription_u_u_t{ | 32 | .u = .{ .clock = clock }, |
| 33 | .clock = clock, | ||
| 34 | }, | ||
| 35 | }, | 33 | }, |
| 36 | }; | 34 | }; |
| 37 | 35 | ||
| ... | @@ -92,35 +90,36 @@ pub fn microTimestamp() i64 { | ... | @@ -92,35 +90,36 @@ pub fn microTimestamp() i64 { |
| 92 | /// before the epoch. | 90 | /// before the epoch. |
| 93 | /// See `std.os.clock_gettime` for a POSIX timestamp. | 91 | /// See `std.os.clock_gettime` for a POSIX timestamp. |
| 94 | pub fn nanoTimestamp() i128 { | 92 | pub fn nanoTimestamp() i128 { |
| 95 | if (builtin.os.tag == .windows) { | 93 | switch (builtin.os.tag) { |
| 96 | // FileTime has a granularity of 100 nanoseconds and uses the NTFS/Windows epoch, | 94 | .windows => { |
| 97 | // which is 1601-01-01. | 95 | // FileTime has a granularity of 100 nanoseconds and uses the NTFS/Windows epoch, |
| 98 | const epoch_adj = epoch.windows * (ns_per_s / 100); | 96 | // which is 1601-01-01. |
| 99 | var ft: os.windows.FILETIME = undefined; | 97 | const epoch_adj = epoch.windows * (ns_per_s / 100); |
| 100 | os.windows.kernel32.GetSystemTimeAsFileTime(&ft); | 98 | var ft: os.windows.FILETIME = undefined; |
| 101 | const ft64 = (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime; | 99 | os.windows.kernel32.GetSystemTimeAsFileTime(&ft); |
| 102 | return @as(i128, @as(i64, @bitCast(ft64)) + epoch_adj) * 100; | 100 | const ft64 = (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime; |
| 103 | } | 101 | return @as(i128, @as(i64, @bitCast(ft64)) + epoch_adj) * 100; |
| 104 | 102 | }, | |
| 105 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 103 | .wasi => { |
| 106 | var ns: os.wasi.timestamp_t = undefined; | 104 | var ns: os.wasi.timestamp_t = undefined; |
| 107 | const err = os.wasi.clock_time_get(os.wasi.CLOCK.REALTIME, 1, &ns); | 105 | const err = os.wasi.clock_time_get(.REALTIME, 1, &ns); |
| 108 | assert(err == .SUCCESS); | 106 | assert(err == .SUCCESS); |
| 109 | return ns; | 107 | return ns; |
| 110 | } | 108 | }, |
| 111 | 109 | .uefi => { | |
| 112 | if (builtin.os.tag == .uefi) { | 110 | var value: std.os.uefi.Time = undefined; |
| 113 | var value: std.os.uefi.Time = undefined; | 111 | const status = std.os.uefi.system_table.runtime_services.getTime(&value, null); |
| 114 | const status = std.os.uefi.system_table.runtime_services.getTime(&value, null); | 112 | assert(status == .Success); |
| 115 | assert(status == .Success); | 113 | return value.toEpoch(); |
| 116 | return value.toEpoch(); | 114 | }, |
| 115 | else => { | ||
| 116 | var ts: os.timespec = undefined; | ||
| 117 | os.clock_gettime(os.CLOCK.REALTIME, &ts) catch |err| switch (err) { | ||
| 118 | error.UnsupportedClock, error.Unexpected => return 0, // "Precision of timing depends on hardware and OS". | ||
| 119 | }; | ||
| 120 | return (@as(i128, ts.tv_sec) * ns_per_s) + ts.tv_nsec; | ||
| 121 | }, | ||
| 117 | } | 122 | } |
| 118 | |||
| 119 | var ts: os.timespec = undefined; | ||
| 120 | os.clock_gettime(os.CLOCK.REALTIME, &ts) catch |err| switch (err) { | ||
| 121 | error.UnsupportedClock, error.Unexpected => return 0, // "Precision of timing depends on hardware and OS". | ||
| 122 | }; | ||
| 123 | return (@as(i128, ts.tv_sec) * ns_per_s) + ts.tv_nsec; | ||
| 124 | } | 123 | } |
| 125 | 124 | ||
| 126 | test "timestamp" { | 125 | test "timestamp" { |
| ... | @@ -177,43 +176,43 @@ pub const Instant = struct { | ... | @@ -177,43 +176,43 @@ pub const Instant = struct { |
| 177 | 176 | ||
| 178 | // true if we should use clock_gettime() | 177 | // true if we should use clock_gettime() |
| 179 | const is_posix = switch (builtin.os.tag) { | 178 | const is_posix = switch (builtin.os.tag) { |
| 180 | .wasi => builtin.link_libc, | 179 | .windows, .uefi, .wasi => false, |
| 181 | .windows, .uefi => false, | ||
| 182 | else => true, | 180 | else => true, |
| 183 | }; | 181 | }; |
| 184 | 182 | ||
| 185 | /// Queries the system for the current moment of time as an Instant. | 183 | /// Queries the system for the current moment of time as an Instant. |
| 186 | /// This is not guaranteed to be monotonic or steadily increasing, but for most implementations it is. | 184 | /// This is not guaranteed to be monotonic or steadily increasing, but for |
| 185 | /// most implementations it is. | ||
| 187 | /// Returns `error.Unsupported` when a suitable clock is not detected. | 186 | /// Returns `error.Unsupported` when a suitable clock is not detected. |
| 188 | pub fn now() error{Unsupported}!Instant { | 187 | pub fn now() error{Unsupported}!Instant { |
| 189 | // QPC on windows doesn't fail on >= XP/2000 and includes time suspended. | ||
| 190 | if (builtin.os.tag == .windows) { | ||
| 191 | return Instant{ .timestamp = os.windows.QueryPerformanceCounter() }; | ||
| 192 | } | ||
| 193 | |||
| 194 | // On WASI without libc, use clock_time_get directly. | ||
| 195 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | ||
| 196 | var ns: os.wasi.timestamp_t = undefined; | ||
| 197 | const rc = os.wasi.clock_time_get(os.wasi.CLOCK.MONOTONIC, 1, &ns); | ||
| 198 | if (rc != .SUCCESS) return error.Unsupported; | ||
| 199 | return Instant{ .timestamp = ns }; | ||
| 200 | } | ||
| 201 | |||
| 202 | if (builtin.os.tag == .uefi) { | ||
| 203 | var value: std.os.uefi.Time = undefined; | ||
| 204 | const status = std.os.uefi.system_table.runtime_services.getTime(&value, null); | ||
| 205 | if (status != .Success) return error.Unsupported; | ||
| 206 | return Instant{ .timestamp = value.toEpoch() }; | ||
| 207 | } | ||
| 208 | |||
| 209 | // On darwin, use UPTIME_RAW instead of MONOTONIC as it ticks while suspended. | ||
| 210 | // On linux, use BOOTTIME instead of MONOTONIC as it ticks while suspended. | ||
| 211 | // On freebsd derivatives, use MONOTONIC_FAST as currently there's no precision tradeoff. | ||
| 212 | // On other posix systems, MONOTONIC is generally the fastest and ticks while suspended. | ||
| 213 | const clock_id = switch (builtin.os.tag) { | 188 | const clock_id = switch (builtin.os.tag) { |
| 189 | .windows => { | ||
| 190 | // QPC on windows doesn't fail on >= XP/2000 and includes time suspended. | ||
| 191 | return Instant{ .timestamp = os.windows.QueryPerformanceCounter() }; | ||
| 192 | }, | ||
| 193 | .wasi => { | ||
| 194 | var ns: os.wasi.timestamp_t = undefined; | ||
| 195 | const rc = os.wasi.clock_time_get(.MONOTONIC, 1, &ns); | ||
| 196 | if (rc != .SUCCESS) return error.Unsupported; | ||
| 197 | return .{ .timestamp = ns }; | ||
| 198 | }, | ||
| 199 | .uefi => { | ||
| 200 | var value: std.os.uefi.Time = undefined; | ||
| 201 | const status = std.os.uefi.system_table.runtime_services.getTime(&value, null); | ||
| 202 | if (status != .Success) return error.Unsupported; | ||
| 203 | return Instant{ .timestamp = value.toEpoch() }; | ||
| 204 | }, | ||
| 205 | // On darwin, use UPTIME_RAW instead of MONOTONIC as it ticks while | ||
| 206 | // suspended. | ||
| 214 | .macos, .ios, .tvos, .watchos => os.CLOCK.UPTIME_RAW, | 207 | .macos, .ios, .tvos, .watchos => os.CLOCK.UPTIME_RAW, |
| 208 | // On freebsd derivatives, use MONOTONIC_FAST as currently there's | ||
| 209 | // no precision tradeoff. | ||
| 215 | .freebsd, .dragonfly => os.CLOCK.MONOTONIC_FAST, | 210 | .freebsd, .dragonfly => os.CLOCK.MONOTONIC_FAST, |
| 211 | // On linux, use BOOTTIME instead of MONOTONIC as it ticks while | ||
| 212 | // suspended. | ||
| 216 | .linux => os.CLOCK.BOOTTIME, | 213 | .linux => os.CLOCK.BOOTTIME, |
| 214 | // On other posix systems, MONOTONIC is generally the fastest and | ||
| 215 | // ticks while suspended. | ||
| 217 | else => os.CLOCK.MONOTONIC, | 216 | else => os.CLOCK.MONOTONIC, |
| 218 | }; | 217 | }; |
| 219 | 218 | ||
| ... | @@ -262,7 +261,7 @@ pub const Instant = struct { | ... | @@ -262,7 +261,7 @@ pub const Instant = struct { |
| 262 | } | 261 | } |
| 263 | 262 | ||
| 264 | // WASI timestamps are directly in nanoseconds | 263 | // WASI timestamps are directly in nanoseconds |
| 265 | if (builtin.os.tag == .wasi and !builtin.link_libc) { | 264 | if (builtin.os.tag == .wasi) { |
| 266 | return self.timestamp - earlier.timestamp; | 265 | return self.timestamp - earlier.timestamp; |
| 267 | } | 266 | } |
| 268 | 267 |
src/TypedValue.zig+16-8| ... | @@ -367,18 +367,26 @@ pub fn print( | ... | @@ -367,18 +367,26 @@ pub fn print( |
| 367 | try writer.writeAll(".?"); | 367 | try writer.writeAll(".?"); |
| 368 | }, | 368 | }, |
| 369 | .elem => |elem| { | 369 | .elem => |elem| { |
| 370 | try print(.{ | 370 | if (level == 0) { |
| 371 | .ty = Type.fromInterned(ip.typeOf(elem.base)), | 371 | try writer.writeAll("(...)"); |
| 372 | .val = Value.fromInterned(elem.base), | 372 | } else { |
| 373 | }, writer, level - 1, mod); | 373 | try print(.{ |
| 374 | .ty = Type.fromInterned(ip.typeOf(elem.base)), | ||
| 375 | .val = Value.fromInterned(elem.base), | ||
| 376 | }, writer, level - 1, mod); | ||
| 377 | } | ||
| 374 | try writer.print("[{}]", .{elem.index}); | 378 | try writer.print("[{}]", .{elem.index}); |
| 375 | }, | 379 | }, |
| 376 | .field => |field| { | 380 | .field => |field| { |
| 377 | const ptr_container_ty = Type.fromInterned(ip.typeOf(field.base)); | 381 | const ptr_container_ty = Type.fromInterned(ip.typeOf(field.base)); |
| 378 | try print(.{ | 382 | if (level == 0) { |
| 379 | .ty = ptr_container_ty, | 383 | try writer.writeAll("(...)"); |
| 380 | .val = Value.fromInterned(field.base), | 384 | } else { |
| 381 | }, writer, level - 1, mod); | 385 | try print(.{ |
| 386 | .ty = ptr_container_ty, | ||
| 387 | .val = Value.fromInterned(field.base), | ||
| 388 | }, writer, level - 1, mod); | ||
| 389 | } | ||
| 382 | 390 | ||
| 383 | const container_ty = ptr_container_ty.childType(mod); | 391 | const container_ty = ptr_container_ty.childType(mod); |
| 384 | switch (container_ty.zigTypeTag(mod)) { | 392 | switch (container_ty.zigTypeTag(mod)) { |
test/behavior/packed-struct.zig+29| ... | @@ -1248,3 +1248,32 @@ test "bitcasting a packed struct at comptime and using the result" { | ... | @@ -1248,3 +1248,32 @@ test "bitcasting a packed struct at comptime and using the result" { |
| 1248 | _ = Struct.bitcast(@as(u64, 0)).cannotReach(); | 1248 | _ = Struct.bitcast(@as(u64, 0)).cannotReach(); |
| 1249 | } | 1249 | } |
| 1250 | } | 1250 | } |
| 1251 | |||
| 1252 | test "2-byte packed struct argument in C calling convention" { | ||
| 1253 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 1254 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; | ||
| 1255 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | ||
| 1256 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | ||
| 1257 | |||
| 1258 | const S = packed struct(u16) { | ||
| 1259 | x: u15 = 0, | ||
| 1260 | y: u1 = 0, | ||
| 1261 | |||
| 1262 | fn foo(s: @This()) callconv(.C) i32 { | ||
| 1263 | return s.x; | ||
| 1264 | } | ||
| 1265 | fn bar(s: @This()) !void { | ||
| 1266 | try expect(foo(s) == 1); | ||
| 1267 | } | ||
| 1268 | }; | ||
| 1269 | { | ||
| 1270 | var s: S = .{}; | ||
| 1271 | s.x += 1; | ||
| 1272 | try S.bar(s); | ||
| 1273 | } | ||
| 1274 | comptime { | ||
| 1275 | var s: S = .{}; | ||
| 1276 | s.x += 1; | ||
| 1277 | try S.bar(s); | ||
| 1278 | } | ||
| 1279 | } |