| ... | @@ -7963,7 +7963,7 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: File, data: []const []u8) | ... | @@ -7963,7 +7963,7 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: File, data: []const []u8) |
| 7963 | switch (e) { | 7963 | switch (e) { |
| 7964 | .INVAL => |err| return errnoBug(err), | 7964 | .INVAL => |err| return errnoBug(err), |
| 7965 | .FAULT => |err| return errnoBug(err), | 7965 | .FAULT => |err| return errnoBug(err), |
| 7966 | .BADF => return error.NotOpenForReading, // File operation on directory. | 7966 | .BADF => return error.IsDir, // File operation on directory. |
| 7967 | .IO => return error.InputOutput, | 7967 | .IO => return error.InputOutput, |
| 7968 | .ISDIR => return error.IsDir, | 7968 | .ISDIR => return error.IsDir, |
| 7969 | .NOBUFS => return error.SystemResources, | 7969 | .NOBUFS => return error.SystemResources, |
| ... | @@ -8793,7 +8793,7 @@ fn fileWritePositional( | ... | @@ -8793,7 +8793,7 @@ fn fileWritePositional( |
| 8793 | .INVAL => |err| return errnoBug(err), | 8793 | .INVAL => |err| return errnoBug(err), |
| 8794 | .FAULT => |err| return errnoBug(err), | 8794 | .FAULT => |err| return errnoBug(err), |
| 8795 | .AGAIN => |err| return errnoBug(err), | 8795 | .AGAIN => |err| return errnoBug(err), |
| 8796 | .BADF => return error.NotOpenForWriting, // can be a race condition. | 8796 | .BADF => |err| return errnoBug(err), // use after free |
| 8797 | .DESTADDRREQ => |err| return errnoBug(err), // `connect` was never called. | 8797 | .DESTADDRREQ => |err| return errnoBug(err), // `connect` was never called. |
| 8798 | .DQUOT => return error.DiskQuota, | 8798 | .DQUOT => return error.DiskQuota, |
| 8799 | .FBIG => return error.FileTooBig, | 8799 | .FBIG => return error.FileTooBig, |
| ... | @@ -16176,6 +16176,7 @@ fn fileMemoryMapCreate( | ... | @@ -16176,6 +16176,7 @@ fn fileMemoryMapCreate( |
| 16176 | return result; | 16176 | return result; |
| 16177 | } else |err| switch (err) { | 16177 | } else |err| switch (err) { |
| 16178 | error.Unseekable, error.Canceled, error.AccessDenied => |e| return e, | 16178 | error.Unseekable, error.Canceled, error.AccessDenied => |e| return e, |
| | 16179 | error.OperationUnsupported => {}, |
| 16179 | else => { | 16180 | else => { |
| 16180 | if (builtin.mode == .Debug) | 16181 | if (builtin.mode == .Debug) |
| 16181 | std.log.warn("memory mapping failed with {t}, falling back to file operations", .{err}); | 16182 | std.log.warn("memory mapping failed with {t}, falling back to file operations", .{err}); |
| ... | @@ -16478,104 +16479,178 @@ fn fileMemoryMapWrite(userdata: ?*anyopaque, mm: *File.MemoryMap) File.WritePosi | ... | @@ -16478,104 +16479,178 @@ fn fileMemoryMapWrite(userdata: ?*anyopaque, mm: *File.MemoryMap) File.WritePosi |
| 16478 | } | 16479 | } |
| 16479 | | 16480 | |
| 16480 | fn mmSyncRead(file: File, memory: []u8, offset: u64) File.ReadPositionalError!void { | 16481 | fn mmSyncRead(file: File, memory: []u8, offset: u64) File.ReadPositionalError!void { |
| 16481 | switch (native_os) { | 16482 | if (is_windows) { |
| 16482 | .windows => @panic("TODO"), | 16483 | @panic("TODO"); |
| 16483 | .wasi => @panic("TODO"), | 16484 | } else if (native_os == .wasi and !builtin.link_libc) { |
| 16484 | else => { | 16485 | var i: usize = 0; |
| 16485 | var i: usize = 0; | 16486 | const syscall: Syscall = try .start(); |
| 16486 | const syscall: Syscall = try .start(); | 16487 | while (true) { |
| 16487 | while (true) { | 16488 | const buf = memory[i..]; |
| 16488 | const buf = memory[i..]; | 16489 | if (buf.len == 0) { |
| 16489 | if (buf.len == 0) { | 16490 | syscall.finish(); |
| 16490 | syscall.finish(); | 16491 | break; |
| 16491 | break; | 16492 | } |
| 16492 | } | 16493 | var n: usize = undefined; |
| 16493 | const rc = pread_sym(file.handle, buf.ptr, buf.len, @intCast(offset + i)); | 16494 | const vec: std.os.wasi.iovec_t = .{ .base = buf.ptr, .len = buf.len }; |
| 16494 | switch (posix.errno(rc)) { | 16495 | switch (std.os.wasi.fd_pread(file.handle, (&vec)[0..1], 1, offset + i, &n)) { |
| 16495 | .SUCCESS => { | 16496 | .SUCCESS => { |
| 16496 | const n: usize = @intCast(rc); | 16497 | if (n == 0) { |
| 16497 | if (n == 0) { | | |
| 16498 | syscall.finish(); | | |
| 16499 | @memset(memory[i..], 0); | | |
| 16500 | break; | | |
| 16501 | } | | |
| 16502 | i += n; | | |
| 16503 | try syscall.checkCancel(); | | |
| 16504 | continue; | | |
| 16505 | }, | | |
| 16506 | .INTR, .TIMEDOUT => { | | |
| 16507 | try syscall.checkCancel(); | | |
| 16508 | continue; | | |
| 16509 | }, | | |
| 16510 | .NXIO => return syscall.fail(error.Unseekable), | | |
| 16511 | .SPIPE => return syscall.fail(error.Unseekable), | | |
| 16512 | .OVERFLOW => return syscall.fail(error.Unseekable), | | |
| 16513 | .NOBUFS => return syscall.fail(error.SystemResources), | | |
| 16514 | .NOMEM => return syscall.fail(error.SystemResources), | | |
| 16515 | .AGAIN => return syscall.fail(error.WouldBlock), | | |
| 16516 | .IO => return syscall.fail(error.InputOutput), | | |
| 16517 | .ISDIR => return syscall.fail(error.IsDir), | | |
| 16518 | .NOTCONN => |err| return syscall.errnoBug(err), // not a socket | | |
| 16519 | .CONNRESET => |err| return syscall.errnoBug(err), // not a socket | | |
| 16520 | .INVAL => |err| return syscall.errnoBug(err), | | |
| 16521 | .FAULT => |err| return syscall.errnoBug(err), | | |
| 16522 | .BADF => |err| { | | |
| 16523 | syscall.finish(); | 16498 | syscall.finish(); |
| 16524 | if (native_os == .wasi) return error.IsDir; // File operation on directory. | 16499 | @memset(memory[i..], 0); |
| 16525 | return errnoBug(err); // File descriptor used after closed. | 16500 | break; |
| 16526 | }, | 16501 | } |
| 16527 | else => |err| return syscall.unexpectedErrno(err), | 16502 | i += n; |
| 16528 | } | 16503 | try syscall.checkCancel(); |
| | 16504 | continue; |
| | 16505 | }, |
| | 16506 | .INTR, .TIMEDOUT => { |
| | 16507 | try syscall.checkCancel(); |
| | 16508 | continue; |
| | 16509 | }, |
| | 16510 | .NOTCONN => |err| return syscall.errnoBug(err), // not a socket |
| | 16511 | .CONNRESET => |err| return syscall.errnoBug(err), // not a socket |
| | 16512 | .BADF => |err| return syscall.errnoBug(err), // use after free |
| | 16513 | .INVAL => |err| return syscall.errnoBug(err), |
| | 16514 | .FAULT => |err| return syscall.errnoBug(err), // segmentation fault |
| | 16515 | .AGAIN => |err| return syscall.errnoBug(err), |
| | 16516 | .IO => return syscall.fail(error.InputOutput), |
| | 16517 | .ISDIR => return syscall.fail(error.IsDir), |
| | 16518 | .NOBUFS => return syscall.fail(error.SystemResources), |
| | 16519 | .NOMEM => return syscall.fail(error.SystemResources), |
| | 16520 | .NXIO => return syscall.fail(error.Unseekable), |
| | 16521 | .SPIPE => return syscall.fail(error.Unseekable), |
| | 16522 | .OVERFLOW => return syscall.fail(error.Unseekable), |
| | 16523 | .NOTCAPABLE => return syscall.fail(error.AccessDenied), |
| | 16524 | else => |err| return syscall.unexpectedErrno(err), |
| 16529 | } | 16525 | } |
| 16530 | }, | 16526 | } |
| | 16527 | } else { |
| | 16528 | var i: usize = 0; |
| | 16529 | const syscall: Syscall = try .start(); |
| | 16530 | while (true) { |
| | 16531 | const buf = memory[i..]; |
| | 16532 | if (buf.len == 0) { |
| | 16533 | syscall.finish(); |
| | 16534 | break; |
| | 16535 | } |
| | 16536 | const rc = pread_sym(file.handle, buf.ptr, buf.len, @intCast(offset + i)); |
| | 16537 | switch (posix.errno(rc)) { |
| | 16538 | .SUCCESS => { |
| | 16539 | const n: usize = @intCast(rc); |
| | 16540 | if (n == 0) { |
| | 16541 | syscall.finish(); |
| | 16542 | @memset(memory[i..], 0); |
| | 16543 | break; |
| | 16544 | } |
| | 16545 | i += n; |
| | 16546 | try syscall.checkCancel(); |
| | 16547 | continue; |
| | 16548 | }, |
| | 16549 | .INTR, .TIMEDOUT => { |
| | 16550 | try syscall.checkCancel(); |
| | 16551 | continue; |
| | 16552 | }, |
| | 16553 | .NXIO => return syscall.fail(error.Unseekable), |
| | 16554 | .SPIPE => return syscall.fail(error.Unseekable), |
| | 16555 | .OVERFLOW => return syscall.fail(error.Unseekable), |
| | 16556 | .NOBUFS => return syscall.fail(error.SystemResources), |
| | 16557 | .NOMEM => return syscall.fail(error.SystemResources), |
| | 16558 | .AGAIN => return syscall.fail(error.WouldBlock), |
| | 16559 | .IO => return syscall.fail(error.InputOutput), |
| | 16560 | .ISDIR => return syscall.fail(error.IsDir), |
| | 16561 | .NOTCONN => |err| return syscall.errnoBug(err), // not a socket |
| | 16562 | .CONNRESET => |err| return syscall.errnoBug(err), // not a socket |
| | 16563 | .INVAL => |err| return syscall.errnoBug(err), |
| | 16564 | .FAULT => |err| return syscall.errnoBug(err), |
| | 16565 | .BADF => |err| return syscall.errnoBug(err), // use after free |
| | 16566 | else => |err| return syscall.unexpectedErrno(err), |
| | 16567 | } |
| | 16568 | } |
| 16531 | } | 16569 | } |
| 16532 | } | 16570 | } |
| 16533 | | 16571 | |
| 16534 | fn mmSyncWrite(file: File, memory: []u8, offset: u64) File.WritePositionalError!void { | 16572 | fn mmSyncWrite(file: File, memory: []u8, offset: u64) File.WritePositionalError!void { |
| 16535 | switch (native_os) { | 16573 | if (is_windows) { |
| 16536 | .windows => @panic("TODO"), | 16574 | @panic("TODO"); |
| 16537 | .wasi => @panic("TODO"), | 16575 | } else if (native_os == .wasi and !builtin.link_libc) { |
| 16538 | else => { | 16576 | var i: usize = 0; |
| 16539 | var i: usize = 0; | 16577 | var n: usize = undefined; |
| 16540 | const syscall: Syscall = try .start(); | 16578 | const syscall: Syscall = try .start(); |
| 16541 | while (true) { | 16579 | while (true) { |
| 16542 | const buf = memory[i..]; | 16580 | const buf = memory[i..]; |
| 16543 | if (buf.len == 0) { | 16581 | if (buf.len == 0) { |
| 16544 | syscall.finish(); | 16582 | syscall.finish(); |
| 16545 | break; | 16583 | break; |
| 16546 | } | | |
| 16547 | const rc = pwrite_sym(file.handle, buf.ptr, buf.len, @intCast(offset)); | | |
| 16548 | switch (posix.errno(rc)) { | | |
| 16549 | .SUCCESS => { | | |
| 16550 | const n: usize = @bitCast(rc); | | |
| 16551 | i += n; | | |
| 16552 | try syscall.checkCancel(); | | |
| 16553 | continue; | | |
| 16554 | }, | | |
| 16555 | .INTR => { | | |
| 16556 | try syscall.checkCancel(); | | |
| 16557 | continue; | | |
| 16558 | }, | | |
| 16559 | .INVAL => |err| return syscall.errnoBug(err), | | |
| 16560 | .FAULT => |err| return syscall.errnoBug(err), | | |
| 16561 | .DESTADDRREQ => |err| return syscall.errnoBug(err), // not a socket | | |
| 16562 | .CONNRESET => |err| return syscall.errnoBug(err), // not a socket | | |
| 16563 | .BADF => |err| return syscall.errnoBug(err), // use after free | | |
| 16564 | .AGAIN => return syscall.fail(error.WouldBlock), | | |
| 16565 | .DQUOT => return syscall.fail(error.DiskQuota), | | |
| 16566 | .FBIG => return syscall.fail(error.FileTooBig), | | |
| 16567 | .IO => return syscall.fail(error.InputOutput), | | |
| 16568 | .NOSPC => return syscall.fail(error.NoSpaceLeft), | | |
| 16569 | .PERM => return syscall.fail(error.PermissionDenied), | | |
| 16570 | .PIPE => return syscall.fail(error.BrokenPipe), | | |
| 16571 | .BUSY => return syscall.fail(error.DeviceBusy), | | |
| 16572 | .TXTBSY => return syscall.fail(error.FileBusy), | | |
| 16573 | .NXIO => return syscall.fail(error.Unseekable), | | |
| 16574 | .SPIPE => return syscall.fail(error.Unseekable), | | |
| 16575 | .OVERFLOW => return syscall.fail(error.Unseekable), | | |
| 16576 | else => |err| return syscall.unexpectedErrno(err), | | |
| 16577 | } | | |
| 16578 | } | 16584 | } |
| 16579 | }, | 16585 | const iovec: std.os.wasi.ciovec_t = .{ .base = buf.ptr, .len = buf.len }; |
| | 16586 | switch (std.os.wasi.fd_pwrite(file.handle, (&iovec)[0..1], 1, offset + i, &n)) { |
| | 16587 | .SUCCESS => { |
| | 16588 | i += n; |
| | 16589 | try syscall.checkCancel(); |
| | 16590 | continue; |
| | 16591 | }, |
| | 16592 | .INTR => { |
| | 16593 | try syscall.checkCancel(); |
| | 16594 | continue; |
| | 16595 | }, |
| | 16596 | .DQUOT => return syscall.fail(error.DiskQuota), |
| | 16597 | .FBIG => return syscall.fail(error.FileTooBig), |
| | 16598 | .IO => return syscall.fail(error.InputOutput), |
| | 16599 | .NOSPC => return syscall.fail(error.NoSpaceLeft), |
| | 16600 | .PERM => return syscall.fail(error.PermissionDenied), |
| | 16601 | .PIPE => return syscall.fail(error.BrokenPipe), |
| | 16602 | .NOTCAPABLE => return syscall.fail(error.AccessDenied), |
| | 16603 | .NXIO => return syscall.fail(error.Unseekable), |
| | 16604 | .SPIPE => return syscall.fail(error.Unseekable), |
| | 16605 | .OVERFLOW => return syscall.fail(error.Unseekable), |
| | 16606 | .INVAL => |err| return syscall.errnoBug(err), |
| | 16607 | .FAULT => |err| return syscall.errnoBug(err), |
| | 16608 | .AGAIN => |err| return syscall.errnoBug(err), |
| | 16609 | .BADF => |err| return syscall.errnoBug(err), // use after free |
| | 16610 | .DESTADDRREQ => |err| return syscall.errnoBug(err), // not a socket |
| | 16611 | else => |err| return syscall.unexpectedErrno(err), |
| | 16612 | } |
| | 16613 | } |
| | 16614 | } else { |
| | 16615 | var i: usize = 0; |
| | 16616 | const syscall: Syscall = try .start(); |
| | 16617 | while (true) { |
| | 16618 | const buf = memory[i..]; |
| | 16619 | if (buf.len == 0) { |
| | 16620 | syscall.finish(); |
| | 16621 | break; |
| | 16622 | } |
| | 16623 | const rc = pwrite_sym(file.handle, buf.ptr, buf.len, @intCast(offset + i)); |
| | 16624 | switch (posix.errno(rc)) { |
| | 16625 | .SUCCESS => { |
| | 16626 | const n: usize = @bitCast(rc); |
| | 16627 | i += n; |
| | 16628 | try syscall.checkCancel(); |
| | 16629 | continue; |
| | 16630 | }, |
| | 16631 | .INTR => { |
| | 16632 | try syscall.checkCancel(); |
| | 16633 | continue; |
| | 16634 | }, |
| | 16635 | .INVAL => |err| return syscall.errnoBug(err), |
| | 16636 | .FAULT => |err| return syscall.errnoBug(err), |
| | 16637 | .DESTADDRREQ => |err| return syscall.errnoBug(err), // not a socket |
| | 16638 | .CONNRESET => |err| return syscall.errnoBug(err), // not a socket |
| | 16639 | .BADF => |err| return syscall.errnoBug(err), // use after free |
| | 16640 | .AGAIN => return syscall.fail(error.WouldBlock), |
| | 16641 | .DQUOT => return syscall.fail(error.DiskQuota), |
| | 16642 | .FBIG => return syscall.fail(error.FileTooBig), |
| | 16643 | .IO => return syscall.fail(error.InputOutput), |
| | 16644 | .NOSPC => return syscall.fail(error.NoSpaceLeft), |
| | 16645 | .PERM => return syscall.fail(error.PermissionDenied), |
| | 16646 | .PIPE => return syscall.fail(error.BrokenPipe), |
| | 16647 | .BUSY => return syscall.fail(error.DeviceBusy), |
| | 16648 | .TXTBSY => return syscall.fail(error.FileBusy), |
| | 16649 | .NXIO => return syscall.fail(error.Unseekable), |
| | 16650 | .SPIPE => return syscall.fail(error.Unseekable), |
| | 16651 | .OVERFLOW => return syscall.fail(error.Unseekable), |
| | 16652 | else => |err| return syscall.unexpectedErrno(err), |
| | 16653 | } |
| | 16654 | } |
| 16580 | } | 16655 | } |
| 16581 | } | 16656 | } |