| ... | @@ -3,7 +3,8 @@ const builtin = @import("builtin"); | ... | @@ -3,7 +3,8 @@ const builtin = @import("builtin"); |
| 3 | const Os = builtin.Os; | 3 | const Os = builtin.Os; |
| 4 | const is_windows = builtin.os == Os.windows; | 4 | const is_windows = builtin.os == Os.windows; |
| 5 | const is_posix = switch (builtin.os) { | 5 | const is_posix = switch (builtin.os) { |
| 6 | builtin.Os.linux, builtin.Os.macosx => true, | 6 | builtin.Os.linux, |
| | 7 | builtin.Os.macosx => true, |
| 7 | else => false, | 8 | else => false, |
| 8 | }; | 9 | }; |
| 9 | const os = this; | 10 | const os = this; |
| ... | @@ -24,9 +25,10 @@ pub const windows = @import("windows/index.zig"); | ... | @@ -24,9 +25,10 @@ pub const windows = @import("windows/index.zig"); |
| 24 | pub const darwin = @import("darwin.zig"); | 25 | pub const darwin = @import("darwin.zig"); |
| 25 | pub const linux = @import("linux/index.zig"); | 26 | pub const linux = @import("linux/index.zig"); |
| 26 | pub const zen = @import("zen.zig"); | 27 | pub const zen = @import("zen.zig"); |
| 27 | pub const posix = switch(builtin.os) { | 28 | pub const posix = switch (builtin.os) { |
| 28 | Os.linux => linux, | 29 | Os.linux => linux, |
| 29 | Os.macosx, Os.ios => darwin, | 30 | Os.macosx, |
| | 31 | Os.ios => darwin, |
| 30 | Os.zen => zen, | 32 | Os.zen => zen, |
| 31 | else => @compileError("Unsupported OS"), | 33 | else => @compileError("Unsupported OS"), |
| 32 | }; | 34 | }; |
| ... | @@ -58,7 +60,7 @@ pub const windowsWrite = windows_util.windowsWrite; | ... | @@ -58,7 +60,7 @@ pub const windowsWrite = windows_util.windowsWrite; |
| 58 | pub const windowsIsCygwinPty = windows_util.windowsIsCygwinPty; | 60 | pub const windowsIsCygwinPty = windows_util.windowsIsCygwinPty; |
| 59 | pub const windowsOpen = windows_util.windowsOpen; | 61 | pub const windowsOpen = windows_util.windowsOpen; |
| 60 | pub const windowsLoadDll = windows_util.windowsLoadDll; | 62 | pub const windowsLoadDll = windows_util.windowsLoadDll; |
| 61 | pub const windowsUnloadDll = windows_util.windowsUnloadDll; | 63 | pub const windowsUnloadDll = windows_util.windowsUnloadDll; |
| 62 | pub const createWindowsEnvBlock = windows_util.createWindowsEnvBlock; | 64 | pub const createWindowsEnvBlock = windows_util.createWindowsEnvBlock; |
| 63 | | 65 | |
| 64 | pub const WindowsWaitError = windows_util.WaitError; | 66 | pub const WindowsWaitError = windows_util.WaitError; |
| ... | @@ -97,9 +99,9 @@ pub fn getRandomBytes(buf: []u8) !void { | ... | @@ -97,9 +99,9 @@ pub fn getRandomBytes(buf: []u8) !void { |
| 97 | switch (err) { | 99 | switch (err) { |
| 98 | posix.EINVAL => unreachable, | 100 | posix.EINVAL => unreachable, |
| 99 | posix.EFAULT => unreachable, | 101 | posix.EFAULT => unreachable, |
| 100 | posix.EINTR => continue, | 102 | posix.EINTR => continue, |
| 101 | posix.ENOSYS => { | 103 | posix.ENOSYS => { |
| 102 | const fd = try posixOpenC(c"/dev/urandom", posix.O_RDONLY|posix.O_CLOEXEC, 0); | 104 | const fd = try posixOpenC(c"/dev/urandom", posix.O_RDONLY | posix.O_CLOEXEC, 0); |
| 103 | defer close(fd); | 105 | defer close(fd); |
| 104 | | 106 | |
| 105 | try posixRead(fd, buf); | 107 | try posixRead(fd, buf); |
| ... | @@ -110,8 +112,9 @@ pub fn getRandomBytes(buf: []u8) !void { | ... | @@ -110,8 +112,9 @@ pub fn getRandomBytes(buf: []u8) !void { |
| 110 | } | 112 | } |
| 111 | return; | 113 | return; |
| 112 | }, | 114 | }, |
| 113 | Os.macosx, Os.ios => { | 115 | Os.macosx, |
| 114 | const fd = try posixOpenC(c"/dev/urandom", posix.O_RDONLY|posix.O_CLOEXEC, 0); | 116 | Os.ios => { |
| | 117 | const fd = try posixOpenC(c"/dev/urandom", posix.O_RDONLY | posix.O_CLOEXEC, 0); |
| 115 | defer close(fd); | 118 | defer close(fd); |
| 116 | | 119 | |
| 117 | try posixRead(fd, buf); | 120 | try posixRead(fd, buf); |
| ... | @@ -134,7 +137,20 @@ pub fn getRandomBytes(buf: []u8) !void { | ... | @@ -134,7 +137,20 @@ pub fn getRandomBytes(buf: []u8) !void { |
| 134 | } | 137 | } |
| 135 | }, | 138 | }, |
| 136 | Os.zen => { | 139 | Os.zen => { |
| 137 | const randomness = []u8 {42, 1, 7, 12, 22, 17, 99, 16, 26, 87, 41, 45}; | 140 | const randomness = []u8 { |
| | 141 | 42, |
| | 142 | 1, |
| | 143 | 7, |
| | 144 | 12, |
| | 145 | 22, |
| | 146 | 17, |
| | 147 | 99, |
| | 148 | 16, |
| | 149 | 26, |
| | 150 | 87, |
| | 151 | 41, |
| | 152 | 45, |
| | 153 | }; |
| 138 | var i: usize = 0; | 154 | var i: usize = 0; |
| 139 | while (i < buf.len) : (i += 1) { | 155 | while (i < buf.len) : (i += 1) { |
| 140 | if (i > randomness.len) return error.Unknown; | 156 | if (i > randomness.len) return error.Unknown; |
| ... | @@ -159,7 +175,9 @@ pub fn abort() noreturn { | ... | @@ -159,7 +175,9 @@ pub fn abort() noreturn { |
| 159 | c.abort(); | 175 | c.abort(); |
| 160 | } | 176 | } |
| 161 | switch (builtin.os) { | 177 | switch (builtin.os) { |
| 162 | Os.linux, Os.macosx, Os.ios => { | 178 | Os.linux, |
| | 179 | Os.macosx, |
| | 180 | Os.ios => { |
| 163 | _ = posix.raise(posix.SIGABRT); | 181 | _ = posix.raise(posix.SIGABRT); |
| 164 | _ = posix.raise(posix.SIGKILL); | 182 | _ = posix.raise(posix.SIGKILL); |
| 165 | while (true) {} | 183 | while (true) {} |
| ... | @@ -181,7 +199,9 @@ pub fn exit(status: u8) noreturn { | ... | @@ -181,7 +199,9 @@ pub fn exit(status: u8) noreturn { |
| 181 | c.exit(status); | 199 | c.exit(status); |
| 182 | } | 200 | } |
| 183 | switch (builtin.os) { | 201 | switch (builtin.os) { |
| 184 | Os.linux, Os.macosx, Os.ios => { | 202 | Os.linux, |
| | 203 | Os.macosx, |
| | 204 | Os.ios => { |
| 185 | posix.exit(status); | 205 | posix.exit(status); |
| 186 | }, | 206 | }, |
| 187 | Os.windows => { | 207 | Os.windows => { |
| ... | @@ -230,12 +250,14 @@ pub fn posixRead(fd: i32, buf: []u8) !void { | ... | @@ -230,12 +250,14 @@ pub fn posixRead(fd: i32, buf: []u8) !void { |
| 230 | if (err > 0) { | 250 | if (err > 0) { |
| 231 | return switch (err) { | 251 | return switch (err) { |
| 232 | posix.EINTR => continue, | 252 | posix.EINTR => continue, |
| 233 | posix.EINVAL, posix.EFAULT => unreachable, | 253 | posix.EINVAL, |
| | 254 | posix.EFAULT => unreachable, |
| 234 | posix.EAGAIN => error.WouldBlock, | 255 | posix.EAGAIN => error.WouldBlock, |
| 235 | posix.EBADF => error.FileClosed, | 256 | posix.EBADF => error.FileClosed, |
| 236 | posix.EIO => error.InputOutput, | 257 | posix.EIO => error.InputOutput, |
| 237 | posix.EISDIR => error.IsDir, | 258 | posix.EISDIR => error.IsDir, |
| 238 | posix.ENOBUFS, posix.ENOMEM => error.SystemResources, | 259 | posix.ENOBUFS, |
| | 260 | posix.ENOMEM => error.SystemResources, |
| 239 | else => unexpectedErrorPosix(err), | 261 | else => unexpectedErrorPosix(err), |
| 240 | }; | 262 | }; |
| 241 | } | 263 | } |
| ... | @@ -269,18 +291,19 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void { | ... | @@ -269,18 +291,19 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void { |
| 269 | const write_err = posix.getErrno(rc); | 291 | const write_err = posix.getErrno(rc); |
| 270 | if (write_err > 0) { | 292 | if (write_err > 0) { |
| 271 | return switch (write_err) { | 293 | return switch (write_err) { |
| 272 | posix.EINTR => continue, | 294 | posix.EINTR => continue, |
| 273 | posix.EINVAL, posix.EFAULT => unreachable, | 295 | posix.EINVAL, |
| | 296 | posix.EFAULT => unreachable, |
| 274 | posix.EAGAIN => PosixWriteError.WouldBlock, | 297 | posix.EAGAIN => PosixWriteError.WouldBlock, |
| 275 | posix.EBADF => PosixWriteError.FileClosed, | 298 | posix.EBADF => PosixWriteError.FileClosed, |
| 276 | posix.EDESTADDRREQ => PosixWriteError.DestinationAddressRequired, | 299 | posix.EDESTADDRREQ => PosixWriteError.DestinationAddressRequired, |
| 277 | posix.EDQUOT => PosixWriteError.DiskQuota, | 300 | posix.EDQUOT => PosixWriteError.DiskQuota, |
| 278 | posix.EFBIG => PosixWriteError.FileTooBig, | 301 | posix.EFBIG => PosixWriteError.FileTooBig, |
| 279 | posix.EIO => PosixWriteError.InputOutput, | 302 | posix.EIO => PosixWriteError.InputOutput, |
| 280 | posix.ENOSPC => PosixWriteError.NoSpaceLeft, | 303 | posix.ENOSPC => PosixWriteError.NoSpaceLeft, |
| 281 | posix.EPERM => PosixWriteError.AccessDenied, | 304 | posix.EPERM => PosixWriteError.AccessDenied, |
| 282 | posix.EPIPE => PosixWriteError.BrokenPipe, | 305 | posix.EPIPE => PosixWriteError.BrokenPipe, |
| 283 | else => unexpectedErrorPosix(write_err), | 306 | else => unexpectedErrorPosix(write_err), |
| 284 | }; | 307 | }; |
| 285 | } | 308 | } |
| 286 | index += rc; | 309 | index += rc; |
| ... | @@ -326,7 +349,8 @@ pub fn posixOpenC(file_path: &const u8, flags: u32, perm: usize) !i32 { | ... | @@ -326,7 +349,8 @@ pub fn posixOpenC(file_path: &const u8, flags: u32, perm: usize) !i32 { |
| 326 | posix.EFAULT => unreachable, | 349 | posix.EFAULT => unreachable, |
| 327 | posix.EINVAL => unreachable, | 350 | posix.EINVAL => unreachable, |
| 328 | posix.EACCES => return PosixOpenError.AccessDenied, | 351 | posix.EACCES => return PosixOpenError.AccessDenied, |
| 329 | posix.EFBIG, posix.EOVERFLOW => return PosixOpenError.FileTooBig, | 352 | posix.EFBIG, |
| | 353 | posix.EOVERFLOW => return PosixOpenError.FileTooBig, |
| 330 | posix.EISDIR => return PosixOpenError.IsDir, | 354 | posix.EISDIR => return PosixOpenError.IsDir, |
| 331 | posix.ELOOP => return PosixOpenError.SymLinkLoop, | 355 | posix.ELOOP => return PosixOpenError.SymLinkLoop, |
| 332 | posix.EMFILE => return PosixOpenError.ProcessFdQuotaExceeded, | 356 | posix.EMFILE => return PosixOpenError.ProcessFdQuotaExceeded, |
| ... | @@ -351,7 +375,8 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) !void { | ... | @@ -351,7 +375,8 @@ pub fn posixDup2(old_fd: i32, new_fd: i32) !void { |
| 351 | const err = posix.getErrno(posix.dup2(old_fd, new_fd)); | 375 | const err = posix.getErrno(posix.dup2(old_fd, new_fd)); |
| 352 | if (err > 0) { | 376 | if (err > 0) { |
| 353 | return switch (err) { | 377 | return switch (err) { |
| 354 | posix.EBUSY, posix.EINTR => continue, | 378 | posix.EBUSY, |
| | 379 | posix.EINTR => continue, |
| 355 | posix.EMFILE => error.ProcessFdQuotaExceeded, | 380 | posix.EMFILE => error.ProcessFdQuotaExceeded, |
| 356 | posix.EINVAL => unreachable, | 381 | posix.EINVAL => unreachable, |
| 357 | else => unexpectedErrorPosix(err), | 382 | else => unexpectedErrorPosix(err), |
| ... | @@ -386,7 +411,7 @@ pub fn createNullDelimitedEnvMap(allocator: &Allocator, env_map: &const BufMap) | ... | @@ -386,7 +411,7 @@ pub fn createNullDelimitedEnvMap(allocator: &Allocator, env_map: &const BufMap) |
| 386 | | 411 | |
| 387 | pub fn freeNullDelimitedEnvMap(allocator: &Allocator, envp_buf: []?&u8) void { | 412 | pub fn freeNullDelimitedEnvMap(allocator: &Allocator, envp_buf: []?&u8) void { |
| 388 | for (envp_buf) |env| { | 413 | for (envp_buf) |env| { |
| 389 | const env_buf = if (env) |ptr| ptr[0 .. cstr.len(ptr) + 1] else break; | 414 | const env_buf = if (env) |ptr| ptr[0..cstr.len(ptr) + 1] else break; |
| 390 | allocator.free(env_buf); | 415 | allocator.free(env_buf); |
| 391 | } | 416 | } |
| 392 | allocator.free(envp_buf); | 417 | allocator.free(envp_buf); |
| ... | @@ -397,9 +422,7 @@ pub fn freeNullDelimitedEnvMap(allocator: &Allocator, envp_buf: []?&u8) void { | ... | @@ -397,9 +422,7 @@ pub fn freeNullDelimitedEnvMap(allocator: &Allocator, envp_buf: []?&u8) void { |
| 397 | /// pointers after the args and after the environment variables. | 422 | /// pointers after the args and after the environment variables. |
| 398 | /// `argv[0]` is the executable path. | 423 | /// `argv[0]` is the executable path. |
| 399 | /// This function also uses the PATH environment variable to get the full path to the executable. | 424 | /// This function also uses the PATH environment variable to get the full path to the executable. |
| 400 | pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap, | 425 | pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap, allocator: &Allocator) !void { |
| 401 | allocator: &Allocator) !void | | |
| 402 | { | | |
| 403 | const argv_buf = try allocator.alloc(?&u8, argv.len + 1); | 426 | const argv_buf = try allocator.alloc(?&u8, argv.len + 1); |
| 404 | mem.set(?&u8, argv_buf, null); | 427 | mem.set(?&u8, argv_buf, null); |
| 405 | defer { | 428 | defer { |
| ... | @@ -438,7 +461,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap, | ... | @@ -438,7 +461,7 @@ pub fn posixExecve(argv: []const []const u8, env_map: &const BufMap, |
| 438 | while (it.next()) |search_path| { | 461 | while (it.next()) |search_path| { |
| 439 | mem.copy(u8, path_buf, search_path); | 462 | mem.copy(u8, path_buf, search_path); |
| 440 | path_buf[search_path.len] = '/'; | 463 | path_buf[search_path.len] = '/'; |
| 441 | mem.copy(u8, path_buf[search_path.len + 1 ..], exe_path); | 464 | mem.copy(u8, path_buf[search_path.len + 1..], exe_path); |
| 442 | path_buf[search_path.len + exe_path.len + 1] = 0; | 465 | path_buf[search_path.len + exe_path.len + 1] = 0; |
| 443 | err = posix.getErrno(posix.execve(path_buf.ptr, argv_buf.ptr, envp_buf.ptr)); | 466 | err = posix.getErrno(posix.execve(path_buf.ptr, argv_buf.ptr, envp_buf.ptr)); |
| 444 | assert(err > 0); | 467 | assert(err > 0); |
| ... | @@ -470,10 +493,17 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError { | ... | @@ -470,10 +493,17 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError { |
| 470 | assert(err > 0); | 493 | assert(err > 0); |
| 471 | return switch (err) { | 494 | return switch (err) { |
| 472 | posix.EFAULT => unreachable, | 495 | posix.EFAULT => unreachable, |
| 473 | posix.E2BIG, posix.EMFILE, posix.ENAMETOOLONG, posix.ENFILE, posix.ENOMEM => error.SystemResources, | 496 | posix.E2BIG, |
| 474 | posix.EACCES, posix.EPERM => error.AccessDenied, | 497 | posix.EMFILE, |
| 475 | posix.EINVAL, posix.ENOEXEC => error.InvalidExe, | 498 | posix.ENAMETOOLONG, |
| 476 | posix.EIO, posix.ELOOP => error.FileSystem, | 499 | posix.ENFILE, |
| | 500 | posix.ENOMEM => error.SystemResources, |
| | 501 | posix.EACCES, |
| | 502 | posix.EPERM => error.AccessDenied, |
| | 503 | posix.EINVAL, |
| | 504 | posix.ENOEXEC => error.InvalidExe, |
| | 505 | posix.EIO, |
| | 506 | posix.ELOOP => error.FileSystem, |
| 477 | posix.EISDIR => error.IsDir, | 507 | posix.EISDIR => error.IsDir, |
| 478 | posix.ENOENT => error.FileNotFound, | 508 | posix.ENOENT => error.FileNotFound, |
| 479 | posix.ENOTDIR => error.NotDir, | 509 | posix.ENOTDIR => error.NotDir, |
| ... | @@ -482,7 +512,7 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError { | ... | @@ -482,7 +512,7 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError { |
| 482 | }; | 512 | }; |
| 483 | } | 513 | } |
| 484 | | 514 | |
| 485 | pub var linux_aux_raw = []usize{0} ** 38; | 515 | pub var linux_aux_raw = []usize {0} ** 38; |
| 486 | pub var posix_environ_raw: []&u8 = undefined; | 516 | pub var posix_environ_raw: []&u8 = undefined; |
| 487 | | 517 | |
| 488 | /// Caller must free result when done. | 518 | /// Caller must free result when done. |
| ... | @@ -496,8 +526,7 @@ pub fn getEnvMap(allocator: &Allocator) !BufMap { | ... | @@ -496,8 +526,7 @@ pub fn getEnvMap(allocator: &Allocator) !BufMap { |
| 496 | | 526 | |
| 497 | var i: usize = 0; | 527 | var i: usize = 0; |
| 498 | while (true) { | 528 | while (true) { |
| 499 | if (ptr[i] == 0) | 529 | if (ptr[i] == 0) return result; |
| 500 | return result; | | |
| 501 | | 530 | |
| 502 | const key_start = i; | 531 | const key_start = i; |
| 503 | | 532 | |
| ... | @@ -535,8 +564,7 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 { | ... | @@ -535,8 +564,7 @@ pub fn getEnvPosix(key: []const u8) ?[]const u8 { |
| 535 | var line_i: usize = 0; | 564 | var line_i: usize = 0; |
| 536 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} | 565 | while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {} |
| 537 | const this_key = ptr[0..line_i]; | 566 | const this_key = ptr[0..line_i]; |
| 538 | if (!mem.eql(u8, key, this_key)) | 567 | if (!mem.eql(u8, key, this_key)) continue; |
| 539 | continue; | | |
| 540 | | 568 | |
| 541 | var end_i: usize = line_i; | 569 | var end_i: usize = line_i; |
| 542 | while (ptr[end_i] != 0) : (end_i += 1) {} | 570 | while (ptr[end_i] != 0) : (end_i += 1) {} |
| ... | @@ -689,8 +717,10 @@ pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path: | ... | @@ -689,8 +717,10 @@ pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path: |
| 689 | const err = posix.getErrno(posix.symlink(existing_buf.ptr, new_buf.ptr)); | 717 | const err = posix.getErrno(posix.symlink(existing_buf.ptr, new_buf.ptr)); |
| 690 | if (err > 0) { | 718 | if (err > 0) { |
| 691 | return switch (err) { | 719 | return switch (err) { |
| 692 | posix.EFAULT, posix.EINVAL => unreachable, | 720 | posix.EFAULT, |
| 693 | posix.EACCES, posix.EPERM => error.AccessDenied, | 721 | posix.EINVAL => unreachable, |
| | 722 | posix.EACCES, |
| | 723 | posix.EPERM => error.AccessDenied, |
| 694 | posix.EDQUOT => error.DiskQuota, | 724 | posix.EDQUOT => error.DiskQuota, |
| 695 | posix.EEXIST => error.PathAlreadyExists, | 725 | posix.EEXIST => error.PathAlreadyExists, |
| 696 | posix.EIO => error.FileSystem, | 726 | posix.EIO => error.FileSystem, |
| ... | @@ -707,9 +737,7 @@ pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path: | ... | @@ -707,9 +737,7 @@ pub fn symLinkPosix(allocator: &Allocator, existing_path: []const u8, new_path: |
| 707 | } | 737 | } |
| 708 | | 738 | |
| 709 | // here we replace the standard +/ with -_ so that it can be used in a file name | 739 | // here we replace the standard +/ with -_ so that it can be used in a file name |
| 710 | const b64_fs_encoder = base64.Base64Encoder.init( | 740 | const b64_fs_encoder = base64.Base64Encoder.init("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", base64.standard_pad_char); |
| 711 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", | | |
| 712 | base64.standard_pad_char); | | |
| 713 | | 741 | |
| 714 | pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) !void { | 742 | pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: []const u8) !void { |
| 715 | if (symLink(allocator, existing_path, new_path)) { | 743 | if (symLink(allocator, existing_path, new_path)) { |
| ... | @@ -728,7 +756,7 @@ pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: | ... | @@ -728,7 +756,7 @@ pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: |
| 728 | tmp_path[dirname.len] = os.path.sep; | 756 | tmp_path[dirname.len] = os.path.sep; |
| 729 | while (true) { | 757 | while (true) { |
| 730 | try getRandomBytes(rand_buf[0..]); | 758 | try getRandomBytes(rand_buf[0..]); |
| 731 | b64_fs_encoder.encode(tmp_path[dirname.len + 1 ..], rand_buf); | 759 | b64_fs_encoder.encode(tmp_path[dirname.len + 1..], rand_buf); |
| 732 | | 760 | |
| 733 | if (symLink(allocator, existing_path, tmp_path)) { | 761 | if (symLink(allocator, existing_path, tmp_path)) { |
| 734 | return rename(allocator, tmp_path, new_path); | 762 | return rename(allocator, tmp_path, new_path); |
| ... | @@ -737,7 +765,6 @@ pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: | ... | @@ -737,7 +765,6 @@ pub fn atomicSymLink(allocator: &Allocator, existing_path: []const u8, new_path: |
| 737 | else => return err, // TODO zig should know this set does not include PathAlreadyExists | 765 | else => return err, // TODO zig should know this set does not include PathAlreadyExists |
| 738 | } | 766 | } |
| 739 | } | 767 | } |
| 740 | | | |
| 741 | } | 768 | } |
| 742 | | 769 | |
| 743 | pub fn deleteFile(allocator: &Allocator, file_path: []const u8) !void { | 770 | pub fn deleteFile(allocator: &Allocator, file_path: []const u8) !void { |
| ... | @@ -760,7 +787,8 @@ pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) !void { | ... | @@ -760,7 +787,8 @@ pub fn deleteFileWindows(allocator: &Allocator, file_path: []const u8) !void { |
| 760 | return switch (err) { | 787 | return switch (err) { |
| 761 | windows.ERROR.FILE_NOT_FOUND => error.FileNotFound, | 788 | windows.ERROR.FILE_NOT_FOUND => error.FileNotFound, |
| 762 | windows.ERROR.ACCESS_DENIED => error.AccessDenied, | 789 | windows.ERROR.ACCESS_DENIED => error.AccessDenied, |
| 763 | windows.ERROR.FILENAME_EXCED_RANGE, windows.ERROR.INVALID_PARAMETER => error.NameTooLong, | 790 | windows.ERROR.FILENAME_EXCED_RANGE, |
| | 791 | windows.ERROR.INVALID_PARAMETER => error.NameTooLong, |
| 764 | else => unexpectedErrorWindows(err), | 792 | else => unexpectedErrorWindows(err), |
| 765 | }; | 793 | }; |
| 766 | } | 794 | } |
| ... | @@ -776,9 +804,11 @@ pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) !void { | ... | @@ -776,9 +804,11 @@ pub fn deleteFilePosix(allocator: &Allocator, file_path: []const u8) !void { |
| 776 | const err = posix.getErrno(posix.unlink(buf.ptr)); | 804 | const err = posix.getErrno(posix.unlink(buf.ptr)); |
| 777 | if (err > 0) { | 805 | if (err > 0) { |
| 778 | return switch (err) { | 806 | return switch (err) { |
| 779 | posix.EACCES, posix.EPERM => error.AccessDenied, | 807 | posix.EACCES, |
| | 808 | posix.EPERM => error.AccessDenied, |
| 780 | posix.EBUSY => error.FileBusy, | 809 | posix.EBUSY => error.FileBusy, |
| 781 | posix.EFAULT, posix.EINVAL => unreachable, | 810 | posix.EFAULT, |
| | 811 | posix.EINVAL => unreachable, |
| 782 | posix.EIO => error.FileSystem, | 812 | posix.EIO => error.FileSystem, |
| 783 | posix.EISDIR => error.IsDir, | 813 | posix.EISDIR => error.IsDir, |
| 784 | posix.ELOOP => error.SymLinkLoop, | 814 | posix.ELOOP => error.SymLinkLoop, |
| ... | @@ -856,7 +886,7 @@ pub const AtomicFile = struct { | ... | @@ -856,7 +886,7 @@ pub const AtomicFile = struct { |
| 856 | | 886 | |
| 857 | while (true) { | 887 | while (true) { |
| 858 | try getRandomBytes(rand_buf[0..]); | 888 | try getRandomBytes(rand_buf[0..]); |
| 859 | b64_fs_encoder.encode(tmp_path[dirname.len + 1 ..], rand_buf); | 889 | b64_fs_encoder.encode(tmp_path[dirname.len + 1..], rand_buf); |
| 860 | | 890 | |
| 861 | const file = os.File.openWriteNoClobber(allocator, tmp_path, mode) catch |err| switch (err) { | 891 | const file = os.File.openWriteNoClobber(allocator, tmp_path, mode) catch |err| switch (err) { |
| 862 | error.PathAlreadyExists => continue, | 892 | error.PathAlreadyExists => continue, |
| ... | @@ -907,7 +937,7 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) | ... | @@ -907,7 +937,7 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) |
| 907 | new_buf[new_path.len] = 0; | 937 | new_buf[new_path.len] = 0; |
| 908 | | 938 | |
| 909 | if (is_windows) { | 939 | if (is_windows) { |
| 910 | const flags = windows.MOVEFILE_REPLACE_EXISTING|windows.MOVEFILE_WRITE_THROUGH; | 940 | const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH; |
| 911 | if (windows.MoveFileExA(old_buf.ptr, new_buf.ptr, flags) == 0) { | 941 | if (windows.MoveFileExA(old_buf.ptr, new_buf.ptr, flags) == 0) { |
| 912 | const err = windows.GetLastError(); | 942 | const err = windows.GetLastError(); |
| 913 | return switch (err) { | 943 | return switch (err) { |
| ... | @@ -918,10 +948,12 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) | ... | @@ -918,10 +948,12 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) |
| 918 | const err = posix.getErrno(posix.rename(old_buf.ptr, new_buf.ptr)); | 948 | const err = posix.getErrno(posix.rename(old_buf.ptr, new_buf.ptr)); |
| 919 | if (err > 0) { | 949 | if (err > 0) { |
| 920 | return switch (err) { | 950 | return switch (err) { |
| 921 | posix.EACCES, posix.EPERM => error.AccessDenied, | 951 | posix.EACCES, |
| | 952 | posix.EPERM => error.AccessDenied, |
| 922 | posix.EBUSY => error.FileBusy, | 953 | posix.EBUSY => error.FileBusy, |
| 923 | posix.EDQUOT => error.DiskQuota, | 954 | posix.EDQUOT => error.DiskQuota, |
| 924 | posix.EFAULT, posix.EINVAL => unreachable, | 955 | posix.EFAULT, |
| | 956 | posix.EINVAL => unreachable, |
| 925 | posix.EISDIR => error.IsDir, | 957 | posix.EISDIR => error.IsDir, |
| 926 | posix.ELOOP => error.SymLinkLoop, | 958 | posix.ELOOP => error.SymLinkLoop, |
| 927 | posix.EMLINK => error.LinkQuotaExceeded, | 959 | posix.EMLINK => error.LinkQuotaExceeded, |
| ... | @@ -930,7 +962,8 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) | ... | @@ -930,7 +962,8 @@ pub fn rename(allocator: &Allocator, old_path: []const u8, new_path: []const u8) |
| 930 | posix.ENOTDIR => error.NotDir, | 962 | posix.ENOTDIR => error.NotDir, |
| 931 | posix.ENOMEM => error.SystemResources, | 963 | posix.ENOMEM => error.SystemResources, |
| 932 | posix.ENOSPC => error.NoSpaceLeft, | 964 | posix.ENOSPC => error.NoSpaceLeft, |
| 933 | posix.EEXIST, posix.ENOTEMPTY => error.PathAlreadyExists, | 965 | posix.EEXIST, |
| | 966 | posix.ENOTEMPTY => error.PathAlreadyExists, |
| 934 | posix.EROFS => error.ReadOnlyFileSystem, | 967 | posix.EROFS => error.ReadOnlyFileSystem, |
| 935 | posix.EXDEV => error.RenameAcrossMountPoints, | 968 | posix.EXDEV => error.RenameAcrossMountPoints, |
| 936 | else => unexpectedErrorPosix(err), | 969 | else => unexpectedErrorPosix(err), |
| ... | @@ -968,7 +1001,8 @@ pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) !void { | ... | @@ -968,7 +1001,8 @@ pub fn makeDirPosix(allocator: &Allocator, dir_path: []const u8) !void { |
| 968 | const err = posix.getErrno(posix.mkdir(path_buf.ptr, 0o755)); | 1001 | const err = posix.getErrno(posix.mkdir(path_buf.ptr, 0o755)); |
| 969 | if (err > 0) { | 1002 | if (err > 0) { |
| 970 | return switch (err) { | 1003 | return switch (err) { |
| 971 | posix.EACCES, posix.EPERM => error.AccessDenied, | 1004 | posix.EACCES, |
| | 1005 | posix.EPERM => error.AccessDenied, |
| 972 | posix.EDQUOT => error.DiskQuota, | 1006 | posix.EDQUOT => error.DiskQuota, |
| 973 | posix.EEXIST => error.PathAlreadyExists, | 1007 | posix.EEXIST => error.PathAlreadyExists, |
| 974 | posix.EFAULT => unreachable, | 1008 | posix.EFAULT => unreachable, |
| ... | @@ -998,27 +1032,23 @@ pub fn makePath(allocator: &Allocator, full_path: []const u8) !void { | ... | @@ -998,27 +1032,23 @@ pub fn makePath(allocator: &Allocator, full_path: []const u8) !void { |
| 998 | // TODO stat the file and return an error if it's not a directory | 1032 | // TODO stat the file and return an error if it's not a directory |
| 999 | // this is important because otherwise a dangling symlink | 1033 | // this is important because otherwise a dangling symlink |
| 1000 | // could cause an infinite loop | 1034 | // could cause an infinite loop |
| 1001 | if (end_index == resolved_path.len) | 1035 | if (end_index == resolved_path.len) return; |
| 1002 | return; | | |
| 1003 | } else if (err == error.FileNotFound) { | 1036 | } else if (err == error.FileNotFound) { |
| 1004 | // march end_index backward until next path component | 1037 | // march end_index backward until next path component |
| 1005 | while (true) { | 1038 | while (true) { |
| 1006 | end_index -= 1; | 1039 | end_index -= 1; |
| 1007 | if (os.path.isSep(resolved_path[end_index])) | 1040 | if (os.path.isSep(resolved_path[end_index])) break; |
| 1008 | break; | | |
| 1009 | } | 1041 | } |
| 1010 | continue; | 1042 | continue; |
| 1011 | } else { | 1043 | } else { |
| 1012 | return err; | 1044 | return err; |
| 1013 | } | 1045 | } |
| 1014 | }; | 1046 | }; |
| 1015 | if (end_index == resolved_path.len) | 1047 | if (end_index == resolved_path.len) return; |
| 1016 | return; | | |
| 1017 | // march end_index forward until next path component | 1048 | // march end_index forward until next path component |
| 1018 | while (true) { | 1049 | while (true) { |
| 1019 | end_index += 1; | 1050 | end_index += 1; |
| 1020 | if (end_index == resolved_path.len or os.path.isSep(resolved_path[end_index])) | 1051 | if (end_index == resolved_path.len or os.path.isSep(resolved_path[end_index])) break; |
| 1021 | break; | | |
| 1022 | } | 1052 | } |
| 1023 | } | 1053 | } |
| 1024 | } | 1054 | } |
| ... | @@ -1035,15 +1065,18 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) !void { | ... | @@ -1035,15 +1065,18 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) !void { |
| 1035 | const err = posix.getErrno(posix.rmdir(path_buf.ptr)); | 1065 | const err = posix.getErrno(posix.rmdir(path_buf.ptr)); |
| 1036 | if (err > 0) { | 1066 | if (err > 0) { |
| 1037 | return switch (err) { | 1067 | return switch (err) { |
| 1038 | posix.EACCES, posix.EPERM => error.AccessDenied, | 1068 | posix.EACCES, |
| | 1069 | posix.EPERM => error.AccessDenied, |
| 1039 | posix.EBUSY => error.FileBusy, | 1070 | posix.EBUSY => error.FileBusy, |
| 1040 | posix.EFAULT, posix.EINVAL => unreachable, | 1071 | posix.EFAULT, |
| | 1072 | posix.EINVAL => unreachable, |
| 1041 | posix.ELOOP => error.SymLinkLoop, | 1073 | posix.ELOOP => error.SymLinkLoop, |
| 1042 | posix.ENAMETOOLONG => error.NameTooLong, | 1074 | posix.ENAMETOOLONG => error.NameTooLong, |
| 1043 | posix.ENOENT => error.FileNotFound, | 1075 | posix.ENOENT => error.FileNotFound, |
| 1044 | posix.ENOMEM => error.SystemResources, | 1076 | posix.ENOMEM => error.SystemResources, |
| 1045 | posix.ENOTDIR => error.NotDir, | 1077 | posix.ENOTDIR => error.NotDir, |
| 1046 | posix.EEXIST, posix.ENOTEMPTY => error.DirNotEmpty, | 1078 | posix.EEXIST, |
| | 1079 | posix.ENOTEMPTY => error.DirNotEmpty, |
| 1047 | posix.EROFS => error.ReadOnlyFileSystem, | 1080 | posix.EROFS => error.ReadOnlyFileSystem, |
| 1048 | else => unexpectedErrorPosix(err), | 1081 | else => unexpectedErrorPosix(err), |
| 1049 | }; | 1082 | }; |
| ... | @@ -1053,7 +1086,7 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) !void { | ... | @@ -1053,7 +1086,7 @@ pub fn deleteDir(allocator: &Allocator, dir_path: []const u8) !void { |
| 1053 | /// Whether ::full_path describes a symlink, file, or directory, this function | 1086 | /// Whether ::full_path describes a symlink, file, or directory, this function |
| 1054 | /// removes it. If it cannot be removed because it is a non-empty directory, | 1087 | /// removes it. If it cannot be removed because it is a non-empty directory, |
| 1055 | /// this function recursively removes its entries and then tries again. | 1088 | /// this function recursively removes its entries and then tries again. |
| 1056 | // TODO non-recursive implementation | 1089 | /// TODO non-recursive implementation |
| 1057 | const DeleteTreeError = error { | 1090 | const DeleteTreeError = error { |
| 1058 | OutOfMemory, | 1091 | OutOfMemory, |
| 1059 | AccessDenied, | 1092 | AccessDenied, |
| ... | @@ -1095,8 +1128,7 @@ pub fn deleteTree(allocator: &Allocator, full_path: []const u8) DeleteTreeError! | ... | @@ -1095,8 +1128,7 @@ pub fn deleteTree(allocator: &Allocator, full_path: []const u8) DeleteTreeError! |
| 1095 | error.NotDir, | 1128 | error.NotDir, |
| 1096 | error.FileSystem, | 1129 | error.FileSystem, |
| 1097 | error.FileBusy, | 1130 | error.FileBusy, |
| 1098 | error.Unexpected | 1131 | error.Unexpected => return err, |
| 1099 | => return err, | | |
| 1100 | } | 1132 | } |
| 1101 | { | 1133 | { |
| 1102 | var dir = Dir.open(allocator, full_path) catch |err| switch (err) { | 1134 | var dir = Dir.open(allocator, full_path) catch |err| switch (err) { |
| ... | @@ -1120,8 +1152,7 @@ pub fn deleteTree(allocator: &Allocator, full_path: []const u8) DeleteTreeError! | ... | @@ -1120,8 +1152,7 @@ pub fn deleteTree(allocator: &Allocator, full_path: []const u8) DeleteTreeError! |
| 1120 | error.SystemResources, | 1152 | error.SystemResources, |
| 1121 | error.NoSpaceLeft, | 1153 | error.NoSpaceLeft, |
| 1122 | error.PathAlreadyExists, | 1154 | error.PathAlreadyExists, |
| 1123 | error.Unexpected | 1155 | error.Unexpected => return err, |
| 1124 | => return err, | | |
| 1125 | }; | 1156 | }; |
| 1126 | defer dir.close(); | 1157 | defer dir.close(); |
| 1127 | | 1158 | |
| ... | @@ -1151,7 +1182,8 @@ pub const Dir = struct { | ... | @@ -1151,7 +1182,8 @@ pub const Dir = struct { |
| 1151 | end_index: usize, | 1182 | end_index: usize, |
| 1152 | | 1183 | |
| 1153 | const darwin_seek_t = switch (builtin.os) { | 1184 | const darwin_seek_t = switch (builtin.os) { |
| 1154 | Os.macosx, Os.ios => i64, | 1185 | Os.macosx, |
| | 1186 | Os.ios => i64, |
| 1155 | else => void, | 1187 | else => void, |
| 1156 | }; | 1188 | }; |
| 1157 | | 1189 | |
| ... | @@ -1175,12 +1207,14 @@ pub const Dir = struct { | ... | @@ -1175,12 +1207,14 @@ pub const Dir = struct { |
| 1175 | pub fn open(allocator: &Allocator, dir_path: []const u8) !Dir { | 1207 | pub fn open(allocator: &Allocator, dir_path: []const u8) !Dir { |
| 1176 | const fd = switch (builtin.os) { | 1208 | const fd = switch (builtin.os) { |
| 1177 | Os.windows => @compileError("TODO support Dir.open for windows"), | 1209 | Os.windows => @compileError("TODO support Dir.open for windows"), |
| 1178 | Os.linux => try posixOpen(allocator, dir_path, posix.O_RDONLY|posix.O_DIRECTORY|posix.O_CLOEXEC, 0), | 1210 | Os.linux => try posixOpen(allocator, dir_path, posix.O_RDONLY | posix.O_DIRECTORY | posix.O_CLOEXEC, 0), |
| 1179 | Os.macosx, Os.ios => try posixOpen(allocator, dir_path, posix.O_RDONLY|posix.O_NONBLOCK|posix.O_DIRECTORY|posix.O_CLOEXEC, 0), | 1211 | Os.macosx, |
| | 1212 | Os.ios => try posixOpen(allocator, dir_path, posix.O_RDONLY | posix.O_NONBLOCK | posix.O_DIRECTORY | posix.O_CLOEXEC, 0), |
| 1180 | else => @compileError("Dir.open is not supported for this platform"), | 1213 | else => @compileError("Dir.open is not supported for this platform"), |
| 1181 | }; | 1214 | }; |
| 1182 | const darwin_seek_init = switch (builtin.os) { | 1215 | const darwin_seek_init = switch (builtin.os) { |
| 1183 | Os.macosx, Os.ios => 0, | 1216 | Os.macosx, |
| | 1217 | Os.ios => 0, |
| 1184 | else => {}, | 1218 | else => {}, |
| 1185 | }; | 1219 | }; |
| 1186 | return Dir { | 1220 | return Dir { |
| ... | @@ -1203,7 +1237,8 @@ pub const Dir = struct { | ... | @@ -1203,7 +1237,8 @@ pub const Dir = struct { |
| 1203 | pub fn next(self: &Dir) !?Entry { | 1237 | pub fn next(self: &Dir) !?Entry { |
| 1204 | switch (builtin.os) { | 1238 | switch (builtin.os) { |
| 1205 | Os.linux => return self.nextLinux(), | 1239 | Os.linux => return self.nextLinux(), |
| 1206 | Os.macosx, Os.ios => return self.nextDarwin(), | 1240 | Os.macosx, |
| | 1241 | Os.ios => return self.nextDarwin(), |
| 1207 | Os.windows => return self.nextWindows(), | 1242 | Os.windows => return self.nextWindows(), |
| 1208 | else => @compileError("Dir.next not supported on " ++ @tagName(builtin.os)), | 1243 | else => @compileError("Dir.next not supported on " ++ @tagName(builtin.os)), |
| 1209 | } | 1244 | } |
| ... | @@ -1217,12 +1252,13 @@ pub const Dir = struct { | ... | @@ -1217,12 +1252,13 @@ pub const Dir = struct { |
| 1217 | } | 1252 | } |
| 1218 | | 1253 | |
| 1219 | while (true) { | 1254 | while (true) { |
| 1220 | const result = posix.getdirentries64(self.fd, self.buf.ptr, self.buf.len, | 1255 | const result = posix.getdirentries64(self.fd, self.buf.ptr, self.buf.len, &self.darwin_seek); |
| 1221 | &self.darwin_seek); | | |
| 1222 | const err = posix.getErrno(result); | 1256 | const err = posix.getErrno(result); |
| 1223 | if (err > 0) { | 1257 | if (err > 0) { |
| 1224 | switch (err) { | 1258 | switch (err) { |
| 1225 | posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable, | 1259 | posix.EBADF, |
| | 1260 | posix.EFAULT, |
| | 1261 | posix.ENOTDIR => unreachable, |
| 1226 | posix.EINVAL => { | 1262 | posix.EINVAL => { |
| 1227 | self.buf = try self.allocator.realloc(u8, self.buf, self.buf.len * 2); | 1263 | self.buf = try self.allocator.realloc(u8, self.buf, self.buf.len * 2); |
| 1228 | continue; | 1264 | continue; |
| ... | @@ -1230,14 +1266,13 @@ pub const Dir = struct { | ... | @@ -1230,14 +1266,13 @@ pub const Dir = struct { |
| 1230 | else => return unexpectedErrorPosix(err), | 1266 | else => return unexpectedErrorPosix(err), |
| 1231 | } | 1267 | } |
| 1232 | } | 1268 | } |
| 1233 | if (result == 0) | 1269 | if (result == 0) return null; |
| 1234 | return null; | | |
| 1235 | self.index = 0; | 1270 | self.index = 0; |
| 1236 | self.end_index = result; | 1271 | self.end_index = result; |
| 1237 | break; | 1272 | break; |
| 1238 | } | 1273 | } |
| 1239 | } | 1274 | } |
| 1240 | const darwin_entry = @ptrCast(& align(1) posix.dirent, &self.buf[self.index]); | 1275 | const darwin_entry = @ptrCast(&align(1) posix.dirent, &self.buf[self.index]); |
| 1241 | const next_index = self.index + darwin_entry.d_reclen; | 1276 | const next_index = self.index + darwin_entry.d_reclen; |
| 1242 | self.index = next_index; | 1277 | self.index = next_index; |
| 1243 | | 1278 | |
| ... | @@ -1282,7 +1317,9 @@ pub const Dir = struct { | ... | @@ -1282,7 +1317,9 @@ pub const Dir = struct { |
| 1282 | const err = posix.getErrno(result); | 1317 | const err = posix.getErrno(result); |
| 1283 | if (err > 0) { | 1318 | if (err > 0) { |
| 1284 | switch (err) { | 1319 | switch (err) { |
| 1285 | posix.EBADF, posix.EFAULT, posix.ENOTDIR => unreachable, | 1320 | posix.EBADF, |
| | 1321 | posix.EFAULT, |
| | 1322 | posix.ENOTDIR => unreachable, |
| 1286 | posix.EINVAL => { | 1323 | posix.EINVAL => { |
| 1287 | self.buf = try self.allocator.realloc(u8, self.buf, self.buf.len * 2); | 1324 | self.buf = try self.allocator.realloc(u8, self.buf, self.buf.len * 2); |
| 1288 | continue; | 1325 | continue; |
| ... | @@ -1290,14 +1327,13 @@ pub const Dir = struct { | ... | @@ -1290,14 +1327,13 @@ pub const Dir = struct { |
| 1290 | else => return unexpectedErrorPosix(err), | 1327 | else => return unexpectedErrorPosix(err), |
| 1291 | } | 1328 | } |
| 1292 | } | 1329 | } |
| 1293 | if (result == 0) | 1330 | if (result == 0) return null; |
| 1294 | return null; | | |
| 1295 | self.index = 0; | 1331 | self.index = 0; |
| 1296 | self.end_index = result; | 1332 | self.end_index = result; |
| 1297 | break; | 1333 | break; |
| 1298 | } | 1334 | } |
| 1299 | } | 1335 | } |
| 1300 | const linux_entry = @ptrCast(& align(1) posix.dirent, &self.buf[self.index]); | 1336 | const linux_entry = @ptrCast(&align(1) posix.dirent, &self.buf[self.index]); |
| 1301 | const next_index = self.index + linux_entry.d_reclen; | 1337 | const next_index = self.index + linux_entry.d_reclen; |
| 1302 | self.index = next_index; | 1338 | self.index = next_index; |
| 1303 | | 1339 | |
| ... | @@ -1366,7 +1402,8 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) ![]u8 { | ... | @@ -1366,7 +1402,8 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) ![]u8 { |
| 1366 | if (err > 0) { | 1402 | if (err > 0) { |
| 1367 | return switch (err) { | 1403 | return switch (err) { |
| 1368 | posix.EACCES => error.AccessDenied, | 1404 | posix.EACCES => error.AccessDenied, |
| 1369 | posix.EFAULT, posix.EINVAL => unreachable, | 1405 | posix.EFAULT, |
| | 1406 | posix.EINVAL => unreachable, |
| 1370 | posix.EIO => error.FileSystem, | 1407 | posix.EIO => error.FileSystem, |
| 1371 | posix.ELOOP => error.SymLinkLoop, | 1408 | posix.ELOOP => error.SymLinkLoop, |
| 1372 | posix.ENAMETOOLONG => error.NameTooLong, | 1409 | posix.ENAMETOOLONG => error.NameTooLong, |
| ... | @@ -1459,8 +1496,7 @@ pub const ArgIteratorPosix = struct { | ... | @@ -1459,8 +1496,7 @@ pub const ArgIteratorPosix = struct { |
| 1459 | } | 1496 | } |
| 1460 | | 1497 | |
| 1461 | pub fn next(self: &ArgIteratorPosix) ?[]const u8 { | 1498 | pub fn next(self: &ArgIteratorPosix) ?[]const u8 { |
| 1462 | if (self.index == self.count) | 1499 | if (self.index == self.count) return null; |
| 1463 | return null; | | |
| 1464 | | 1500 | |
| 1465 | const s = raw[self.index]; | 1501 | const s = raw[self.index]; |
| 1466 | self.index += 1; | 1502 | self.index += 1; |
| ... | @@ -1468,8 +1504,7 @@ pub const ArgIteratorPosix = struct { | ... | @@ -1468,8 +1504,7 @@ pub const ArgIteratorPosix = struct { |
| 1468 | } | 1504 | } |
| 1469 | | 1505 | |
| 1470 | pub fn skip(self: &ArgIteratorPosix) bool { | 1506 | pub fn skip(self: &ArgIteratorPosix) bool { |
| 1471 | if (self.index == self.count) | 1507 | if (self.index == self.count) return false; |
| 1472 | return false; | | |
| 1473 | | 1508 | |
| 1474 | self.index += 1; | 1509 | self.index += 1; |
| 1475 | return true; | 1510 | return true; |
| ... | @@ -1487,7 +1522,9 @@ pub const ArgIteratorWindows = struct { | ... | @@ -1487,7 +1522,9 @@ pub const ArgIteratorWindows = struct { |
| 1487 | quote_count: usize, | 1522 | quote_count: usize, |
| 1488 | seen_quote_count: usize, | 1523 | seen_quote_count: usize, |
| 1489 | | 1524 | |
| 1490 | pub const NextError = error{OutOfMemory}; | 1525 | pub const NextError = error { |
| | 1526 | OutOfMemory, |
| | 1527 | }; |
| 1491 | | 1528 | |
| 1492 | pub fn init() ArgIteratorWindows { | 1529 | pub fn init() ArgIteratorWindows { |
| 1493 | return initWithCmdLine(windows.GetCommandLineA()); | 1530 | return initWithCmdLine(windows.GetCommandLineA()); |
| ... | @@ -1510,7 +1547,8 @@ pub const ArgIteratorWindows = struct { | ... | @@ -1510,7 +1547,8 @@ pub const ArgIteratorWindows = struct { |
| 1510 | const byte = self.cmd_line[self.index]; | 1547 | const byte = self.cmd_line[self.index]; |
| 1511 | switch (byte) { | 1548 | switch (byte) { |
| 1512 | 0 => return null, | 1549 | 0 => return null, |
| 1513 | ' ', '\t' => continue, | 1550 | ' ', |
| | 1551 | '\t' => continue, |
| 1514 | else => break, | 1552 | else => break, |
| 1515 | } | 1553 | } |
| 1516 | } | 1554 | } |
| ... | @@ -1524,7 +1562,8 @@ pub const ArgIteratorWindows = struct { | ... | @@ -1524,7 +1562,8 @@ pub const ArgIteratorWindows = struct { |
| 1524 | const byte = self.cmd_line[self.index]; | 1562 | const byte = self.cmd_line[self.index]; |
| 1525 | switch (byte) { | 1563 | switch (byte) { |
| 1526 | 0 => return false, | 1564 | 0 => return false, |
| 1527 | ' ', '\t' => continue, | 1565 | ' ', |
| | 1566 | '\t' => continue, |
| 1528 | else => break, | 1567 | else => break, |
| 1529 | } | 1568 | } |
| 1530 | } | 1569 | } |
| ... | @@ -1543,7 +1582,8 @@ pub const ArgIteratorWindows = struct { | ... | @@ -1543,7 +1582,8 @@ pub const ArgIteratorWindows = struct { |
| 1543 | '\\' => { | 1582 | '\\' => { |
| 1544 | backslash_count += 1; | 1583 | backslash_count += 1; |
| 1545 | }, | 1584 | }, |
| 1546 | ' ', '\t' => { | 1585 | ' ', |
| | 1586 | '\t' => { |
| 1547 | if (self.seen_quote_count % 2 == 0 or self.seen_quote_count == self.quote_count) { | 1587 | if (self.seen_quote_count % 2 == 0 or self.seen_quote_count == self.quote_count) { |
| 1548 | return true; | 1588 | return true; |
| 1549 | } | 1589 | } |
| ... | @@ -1583,7 +1623,8 @@ pub const ArgIteratorWindows = struct { | ... | @@ -1583,7 +1623,8 @@ pub const ArgIteratorWindows = struct { |
| 1583 | '\\' => { | 1623 | '\\' => { |
| 1584 | backslash_count += 1; | 1624 | backslash_count += 1; |
| 1585 | }, | 1625 | }, |
| 1586 | ' ', '\t' => { | 1626 | ' ', |
| | 1627 | '\t' => { |
| 1587 | try self.emitBackslashes(&buf, backslash_count); | 1628 | try self.emitBackslashes(&buf, backslash_count); |
| 1588 | backslash_count = 0; | 1629 | backslash_count = 0; |
| 1589 | if (self.seen_quote_count % 2 == 1 and self.seen_quote_count != self.quote_count) { | 1630 | if (self.seen_quote_count % 2 == 1 and self.seen_quote_count != self.quote_count) { |
| ... | @@ -1627,7 +1668,6 @@ pub const ArgIteratorWindows = struct { | ... | @@ -1627,7 +1668,6 @@ pub const ArgIteratorWindows = struct { |
| 1627 | } | 1668 | } |
| 1628 | } | 1669 | } |
| 1629 | } | 1670 | } |
| 1630 | | | |
| 1631 | }; | 1671 | }; |
| 1632 | | 1672 | |
| 1633 | pub const ArgIterator = struct { | 1673 | pub const ArgIterator = struct { |
| ... | @@ -1642,7 +1682,7 @@ pub const ArgIterator = struct { | ... | @@ -1642,7 +1682,7 @@ pub const ArgIterator = struct { |
| 1642 | } | 1682 | } |
| 1643 | | 1683 | |
| 1644 | pub const NextError = ArgIteratorWindows.NextError; | 1684 | pub const NextError = ArgIteratorWindows.NextError; |
| 1645 | | 1685 | |
| 1646 | /// You must free the returned memory when done. | 1686 | /// You must free the returned memory when done. |
| 1647 | pub fn next(self: &ArgIterator, allocator: &Allocator) ?(NextError![]u8) { | 1687 | pub fn next(self: &ArgIterator, allocator: &Allocator) ?(NextError![]u8) { |
| 1648 | if (builtin.os == Os.windows) { | 1688 | if (builtin.os == Os.windows) { |
| ... | @@ -1717,15 +1757,47 @@ pub fn argsFree(allocator: &mem.Allocator, args_alloc: []const []u8) void { | ... | @@ -1717,15 +1757,47 @@ pub fn argsFree(allocator: &mem.Allocator, args_alloc: []const []u8) void { |
| 1717 | } | 1757 | } |
| 1718 | | 1758 | |
| 1719 | test "windows arg parsing" { | 1759 | test "windows arg parsing" { |
| 1720 | testWindowsCmdLine(c"a b\tc d", [][]const u8{"a", "b", "c", "d"}); | 1760 | testWindowsCmdLine(c"a b\tc d", [][]const u8 { |
| 1721 | testWindowsCmdLine(c"\"abc\" d e", [][]const u8{"abc", "d", "e"}); | 1761 | "a", |
| 1722 | testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [][]const u8{"a\\\\\\b", "de fg", "h"}); | 1762 | "b", |
| 1723 | testWindowsCmdLine(c"a\\\\\\\"b c d", [][]const u8{"a\\\"b", "c", "d"}); | 1763 | "c", |
| 1724 | testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [][]const u8{"a\\\\b c", "d", "e"}); | 1764 | "d", |
| 1725 | testWindowsCmdLine(c"a b\tc \"d f", [][]const u8{"a", "b", "c", "\"d", "f"}); | 1765 | }); |
| 1726 | | 1766 | testWindowsCmdLine(c"\"abc\" d e", [][]const u8 { |
| 1727 | testWindowsCmdLine(c"\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", | 1767 | "abc", |
| 1728 | [][]const u8{".\\..\\zig-cache\\build", "bin\\zig.exe", ".\\..", ".\\..\\zig-cache", "--help"}); | 1768 | "d", |
| | 1769 | "e", |
| | 1770 | }); |
| | 1771 | testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [][]const u8 { |
| | 1772 | "a\\\\\\b", |
| | 1773 | "de fg", |
| | 1774 | "h", |
| | 1775 | }); |
| | 1776 | testWindowsCmdLine(c"a\\\\\\\"b c d", [][]const u8 { |
| | 1777 | "a\\\"b", |
| | 1778 | "c", |
| | 1779 | "d", |
| | 1780 | }); |
| | 1781 | testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [][]const u8 { |
| | 1782 | "a\\\\b c", |
| | 1783 | "d", |
| | 1784 | "e", |
| | 1785 | }); |
| | 1786 | testWindowsCmdLine(c"a b\tc \"d f", [][]const u8 { |
| | 1787 | "a", |
| | 1788 | "b", |
| | 1789 | "c", |
| | 1790 | "\"d", |
| | 1791 | "f", |
| | 1792 | }); |
| | 1793 | |
| | 1794 | testWindowsCmdLine(c"\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", [][]const u8 { |
| | 1795 | ".\\..\\zig-cache\\build", |
| | 1796 | "bin\\zig.exe", |
| | 1797 | ".\\..", |
| | 1798 | ".\\..\\zig-cache", |
| | 1799 | "--help", |
| | 1800 | }); |
| 1729 | } | 1801 | } |
| 1730 | | 1802 | |
| 1731 | fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const u8) void { | 1803 | fn testWindowsCmdLine(input_cmd_line: &const u8, expected_args: []const []const u8) void { |
| ... | @@ -1772,7 +1844,8 @@ pub fn openSelfExe() !os.File { | ... | @@ -1772,7 +1844,8 @@ pub fn openSelfExe() !os.File { |
| 1772 | var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]); | 1844 | var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]); |
| 1773 | return os.File.openRead(&fixed_allocator.allocator, proc_file_path); | 1845 | return os.File.openRead(&fixed_allocator.allocator, proc_file_path); |
| 1774 | }, | 1846 | }, |
| 1775 | Os.macosx, Os.ios => { | 1847 | Os.macosx, |
| | 1848 | Os.ios => { |
| 1776 | var fixed_buffer_mem: [darwin.PATH_MAX * 2]u8 = undefined; | 1849 | var fixed_buffer_mem: [darwin.PATH_MAX * 2]u8 = undefined; |
| 1777 | var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]); | 1850 | var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]); |
| 1778 | const self_exe_path = try selfExePath(&fixed_allocator.allocator); | 1851 | const self_exe_path = try selfExePath(&fixed_allocator.allocator); |
| ... | @@ -1784,8 +1857,10 @@ pub fn openSelfExe() !os.File { | ... | @@ -1784,8 +1857,10 @@ pub fn openSelfExe() !os.File { |
| 1784 | | 1857 | |
| 1785 | test "openSelfExe" { | 1858 | test "openSelfExe" { |
| 1786 | switch (builtin.os) { | 1859 | switch (builtin.os) { |
| 1787 | Os.linux, Os.macosx, Os.ios => (try openSelfExe()).close(), | 1860 | Os.linux, |
| 1788 | else => return, // Unsupported OS. | 1861 | Os.macosx, |
| | 1862 | Os.ios => (try openSelfExe()).close(), |
| | 1863 | else => return, // Unsupported OS. |
| 1789 | } | 1864 | } |
| 1790 | } | 1865 | } |
| 1791 | | 1866 | |
| ... | @@ -1822,7 +1897,8 @@ pub fn selfExePath(allocator: &mem.Allocator) ![]u8 { | ... | @@ -1822,7 +1897,8 @@ pub fn selfExePath(allocator: &mem.Allocator) ![]u8 { |
| 1822 | try out_path.resize(new_len); | 1897 | try out_path.resize(new_len); |
| 1823 | } | 1898 | } |
| 1824 | }, | 1899 | }, |
| 1825 | Os.macosx, Os.ios => { | 1900 | Os.macosx, |
| | 1901 | Os.ios => { |
| 1826 | var u32_len: u32 = 0; | 1902 | var u32_len: u32 = 0; |
| 1827 | const ret1 = c._NSGetExecutablePath(undefined, &u32_len); | 1903 | const ret1 = c._NSGetExecutablePath(undefined, &u32_len); |
| 1828 | assert(ret1 != 0); | 1904 | assert(ret1 != 0); |
| ... | @@ -1850,7 +1926,9 @@ pub fn selfExeDirPath(allocator: &mem.Allocator) ![]u8 { | ... | @@ -1850,7 +1926,9 @@ pub fn selfExeDirPath(allocator: &mem.Allocator) ![]u8 { |
| 1850 | const dir = path.dirname(full_exe_path); | 1926 | const dir = path.dirname(full_exe_path); |
| 1851 | return allocator.shrink(u8, full_exe_path, dir.len); | 1927 | return allocator.shrink(u8, full_exe_path, dir.len); |
| 1852 | }, | 1928 | }, |
| 1853 | Os.windows, Os.macosx, Os.ios => { | 1929 | Os.windows, |
| | 1930 | Os.macosx, |
| | 1931 | Os.ios => { |
| 1854 | const self_exe_path = try selfExePath(allocator); | 1932 | const self_exe_path = try selfExePath(allocator); |
| 1855 | errdefer allocator.free(self_exe_path); | 1933 | errdefer allocator.free(self_exe_path); |
| 1856 | const dirname = os.path.dirname(self_exe_path); | 1934 | const dirname = os.path.dirname(self_exe_path); |
| ... | @@ -1907,7 +1985,8 @@ pub fn posixSocket(domain: u32, socket_type: u32, protocol: u32) !i32 { | ... | @@ -1907,7 +1985,8 @@ pub fn posixSocket(domain: u32, socket_type: u32, protocol: u32) !i32 { |
| 1907 | posix.EINVAL => return PosixSocketError.ProtocolFamilyNotAvailable, | 1985 | posix.EINVAL => return PosixSocketError.ProtocolFamilyNotAvailable, |
| 1908 | posix.EMFILE => return PosixSocketError.ProcessFdQuotaExceeded, | 1986 | posix.EMFILE => return PosixSocketError.ProcessFdQuotaExceeded, |
| 1909 | posix.ENFILE => return PosixSocketError.SystemFdQuotaExceeded, | 1987 | posix.ENFILE => return PosixSocketError.SystemFdQuotaExceeded, |
| 1910 | posix.ENOBUFS, posix.ENOMEM => return PosixSocketError.SystemResources, | 1988 | posix.ENOBUFS, |
| | 1989 | posix.ENOMEM => return PosixSocketError.SystemResources, |
| 1911 | posix.EPROTONOSUPPORT => return PosixSocketError.ProtocolNotSupported, | 1990 | posix.EPROTONOSUPPORT => return PosixSocketError.ProtocolNotSupported, |
| 1912 | else => return unexpectedErrorPosix(err), | 1991 | else => return unexpectedErrorPosix(err), |
| 1913 | } | 1992 | } |
| ... | @@ -1938,7 +2017,7 @@ pub const PosixBindError = error { | ... | @@ -1938,7 +2017,7 @@ pub const PosixBindError = error { |
| 1938 | | 2017 | |
| 1939 | /// A nonexistent interface was requested or the requested address was not local. | 2018 | /// A nonexistent interface was requested or the requested address was not local. |
| 1940 | AddressNotAvailable, | 2019 | AddressNotAvailable, |
| 1941 | | 2020 | |
| 1942 | /// addr points outside the user's accessible address space. | 2021 | /// addr points outside the user's accessible address space. |
| 1943 | PageFault, | 2022 | PageFault, |
| 1944 | | 2023 | |
| ... | @@ -2027,7 +2106,7 @@ pub const PosixAcceptError = error { | ... | @@ -2027,7 +2106,7 @@ pub const PosixAcceptError = error { |
| 2027 | FileDescriptorClosed, | 2106 | FileDescriptorClosed, |
| 2028 | | 2107 | |
| 2029 | ConnectionAborted, | 2108 | ConnectionAborted, |
| 2030 | | 2109 | |
| 2031 | /// The addr argument is not in a writable part of the user address space. | 2110 | /// The addr argument is not in a writable part of the user address space. |
| 2032 | PageFault, | 2111 | PageFault, |
| 2033 | | 2112 | |
| ... | @@ -2040,7 +2119,7 @@ pub const PosixAcceptError = error { | ... | @@ -2040,7 +2119,7 @@ pub const PosixAcceptError = error { |
| 2040 | | 2119 | |
| 2041 | /// The system-wide limit on the total number of open files has been reached. | 2120 | /// The system-wide limit on the total number of open files has been reached. |
| 2042 | SystemFdQuotaExceeded, | 2121 | SystemFdQuotaExceeded, |
| 2043 | | 2122 | |
| 2044 | /// Not enough free memory. This often means that the memory allocation is limited | 2123 | /// Not enough free memory. This often means that the memory allocation is limited |
| 2045 | /// by the socket buffer limits, not by the system memory. | 2124 | /// by the socket buffer limits, not by the system memory. |
| 2046 | SystemResources, | 2125 | SystemResources, |
| ... | @@ -2076,7 +2155,8 @@ pub fn posixAccept(fd: i32, addr: &posix.sockaddr, flags: u32) PosixAcceptError! | ... | @@ -2076,7 +2155,8 @@ pub fn posixAccept(fd: i32, addr: &posix.sockaddr, flags: u32) PosixAcceptError! |
| 2076 | posix.EINVAL => return PosixAcceptError.InvalidSyscall, | 2155 | posix.EINVAL => return PosixAcceptError.InvalidSyscall, |
| 2077 | posix.EMFILE => return PosixAcceptError.ProcessFdQuotaExceeded, | 2156 | posix.EMFILE => return PosixAcceptError.ProcessFdQuotaExceeded, |
| 2078 | posix.ENFILE => return PosixAcceptError.SystemFdQuotaExceeded, | 2157 | posix.ENFILE => return PosixAcceptError.SystemFdQuotaExceeded, |
| 2079 | posix.ENOBUFS, posix.ENOMEM => return PosixAcceptError.SystemResources, | 2158 | posix.ENOBUFS, |
| | 2159 | posix.ENOMEM => return PosixAcceptError.SystemResources, |
| 2080 | posix.ENOTSOCK => return PosixAcceptError.FileDescriptorNotASocket, | 2160 | posix.ENOTSOCK => return PosixAcceptError.FileDescriptorNotASocket, |
| 2081 | posix.EOPNOTSUPP => return PosixAcceptError.OperationNotSupported, | 2161 | posix.EOPNOTSUPP => return PosixAcceptError.OperationNotSupported, |
| 2082 | posix.EPROTO => return PosixAcceptError.ProtocolFailure, | 2162 | posix.EPROTO => return PosixAcceptError.ProtocolFailure, |
| ... | @@ -2287,7 +2367,8 @@ pub fn posixConnectAsync(sockfd: i32, sockaddr: &const posix.sockaddr) PosixConn | ... | @@ -2287,7 +2367,8 @@ pub fn posixConnectAsync(sockfd: i32, sockaddr: &const posix.sockaddr) PosixConn |
| 2287 | const rc = posix.connect(sockfd, sockaddr, @sizeOf(posix.sockaddr)); | 2367 | const rc = posix.connect(sockfd, sockaddr, @sizeOf(posix.sockaddr)); |
| 2288 | const err = posix.getErrno(rc); | 2368 | const err = posix.getErrno(rc); |
| 2289 | switch (err) { | 2369 | switch (err) { |
| 2290 | 0, posix.EINPROGRESS => return, | 2370 | 0, |
| | 2371 | posix.EINPROGRESS => return, |
| 2291 | else => return unexpectedErrorPosix(err), | 2372 | else => return unexpectedErrorPosix(err), |
| 2292 | | 2373 | |
| 2293 | posix.EACCES => return PosixConnectError.PermissionDenied, | 2374 | posix.EACCES => return PosixConnectError.PermissionDenied, |
| ... | @@ -2351,9 +2432,9 @@ pub const Thread = struct { | ... | @@ -2351,9 +2432,9 @@ pub const Thread = struct { |
| 2351 | | 2432 | |
| 2352 | pub const use_pthreads = is_posix and builtin.link_libc; | 2433 | pub const use_pthreads = is_posix and builtin.link_libc; |
| 2353 | const Data = if (use_pthreads) struct { | 2434 | const Data = if (use_pthreads) struct { |
| 2354 | handle: c.pthread_t, | 2435 | handle: c.pthread_t, |
| 2355 | stack_addr: usize, | 2436 | stack_addr: usize, |
| 2356 | stack_len: usize, | 2437 | stack_len: usize, |
| 2357 | } else switch (builtin.os) { | 2438 | } else switch (builtin.os) { |
| 2358 | builtin.Os.linux => struct { | 2439 | builtin.Os.linux => struct { |
| 2359 | pid: i32, | 2440 | pid: i32, |
| ... | @@ -2467,9 +2548,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread | ... | @@ -2467,9 +2548,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread |
| 2467 | outer_context.thread.data.alloc_start = bytes_ptr; | 2548 | outer_context.thread.data.alloc_start = bytes_ptr; |
| 2468 | | 2549 | |
| 2469 | const parameter = if (@sizeOf(Context) == 0) null else @ptrCast(&c_void, &outer_context.inner); | 2550 | const parameter = if (@sizeOf(Context) == 0) null else @ptrCast(&c_void, &outer_context.inner); |
| 2470 | outer_context.thread.data.handle = windows.CreateThread(null, default_stack_size, WinThread.threadMain, | 2551 | outer_context.thread.data.handle = windows.CreateThread(null, default_stack_size, WinThread.threadMain, parameter, 0, null) ?? { |
| 2471 | parameter, 0, null) ?? | | |
| 2472 | { | | |
| 2473 | const err = windows.GetLastError(); | 2552 | const err = windows.GetLastError(); |
| 2474 | return switch (err) { | 2553 | return switch (err) { |
| 2475 | else => os.unexpectedErrorWindows(err), | 2554 | else => os.unexpectedErrorWindows(err), |
| ... | @@ -2500,8 +2579,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread | ... | @@ -2500,8 +2579,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread |
| 2500 | const MAP_GROWSDOWN = if (builtin.os == builtin.Os.linux) linux.MAP_GROWSDOWN else 0; | 2579 | const MAP_GROWSDOWN = if (builtin.os == builtin.Os.linux) linux.MAP_GROWSDOWN else 0; |
| 2501 | | 2580 | |
| 2502 | const mmap_len = default_stack_size; | 2581 | const mmap_len = default_stack_size; |
| 2503 | const stack_addr = posix.mmap(null, mmap_len, posix.PROT_READ|posix.PROT_WRITE, | 2582 | const stack_addr = posix.mmap(null, mmap_len, posix.PROT_READ | posix.PROT_WRITE, posix.MAP_PRIVATE | posix.MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0); |
| 2504 | posix.MAP_PRIVATE|posix.MAP_ANONYMOUS|MAP_GROWSDOWN, -1, 0); | | |
| 2505 | if (stack_addr == posix.MAP_FAILED) return error.OutOfMemory; | 2583 | if (stack_addr == posix.MAP_FAILED) return error.OutOfMemory; |
| 2506 | errdefer assert(posix.munmap(stack_addr, mmap_len) == 0); | 2584 | errdefer assert(posix.munmap(stack_addr, mmap_len) == 0); |
| 2507 | | 2585 | |
| ... | @@ -2547,9 +2625,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread | ... | @@ -2547,9 +2625,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!&Thread |
| 2547 | } | 2625 | } |
| 2548 | } else if (builtin.os == builtin.Os.linux) { | 2626 | } else if (builtin.os == builtin.Os.linux) { |
| 2549 | // use linux API directly. TODO use posix.CLONE_SETTLS and initialize thread local storage correctly | 2627 | // use linux API directly. TODO use posix.CLONE_SETTLS and initialize thread local storage correctly |
| 2550 | const flags = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND | 2628 | const flags = posix.CLONE_VM | posix.CLONE_FS | posix.CLONE_FILES | posix.CLONE_SIGHAND | posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID | posix.CLONE_DETACHED; |
| 2551 | | posix.CLONE_THREAD | posix.CLONE_SYSVSEM | | |
| 2552 | | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID | posix.CLONE_DETACHED; | | |
| 2553 | const newtls: usize = 0; | 2629 | const newtls: usize = 0; |
| 2554 | const rc = posix.clone(MainFuncs.linuxThreadMain, stack_end, flags, arg, &thread_ptr.data.pid, newtls, &thread_ptr.data.pid); | 2630 | const rc = posix.clone(MainFuncs.linuxThreadMain, stack_end, flags, arg, &thread_ptr.data.pid, newtls, &thread_ptr.data.pid); |
| 2555 | const err = posix.getErrno(rc); | 2631 | const err = posix.getErrno(rc); |