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