| ... | ... | @@ -7963,7 +7963,7 @@ fn fileReadStreamingPosix(userdata: ?*anyopaque, file: File, data: []const []u8) |
| 7963 | 7963 | switch (e) { |
| 7964 | 7964 | .INVAL => |err| return errnoBug(err), |
| 7965 | 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 | 7967 | .IO => return error.InputOutput, |
| 7968 | 7968 | .ISDIR => return error.IsDir, |
| 7969 | 7969 | .NOBUFS => return error.SystemResources, |
| ... | ... | @@ -8793,7 +8793,7 @@ fn fileWritePositional( |
| 8793 | 8793 | .INVAL => |err| return errnoBug(err), |
| 8794 | 8794 | .FAULT => |err| return errnoBug(err), |
| 8795 | 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 | 8797 | .DESTADDRREQ => |err| return errnoBug(err), // `connect` was never called. |
| 8798 | 8798 | .DQUOT => return error.DiskQuota, |
| 8799 | 8799 | .FBIG => return error.FileTooBig, |
| ... | ... | @@ -16176,6 +16176,7 @@ fn fileMemoryMapCreate( |
| 16176 | 16176 | return result; |
| 16177 | 16177 | } else |err| switch (err) { |
| 16178 | 16178 | error.Unseekable, error.Canceled, error.AccessDenied => |e| return e, |
| 16179 | error.OperationUnsupported => {}, |
| 16179 | 16180 | else => { |
| 16180 | 16181 | if (builtin.mode == .Debug) |
| 16181 | 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 | 16479 | } |
| 16479 | 16480 | |
| 16480 | 16481 | fn mmSyncRead(file: File, memory: []u8, offset: u64) File.ReadPositionalError!void { |
| 16481 | | switch (native_os) { |
| 16482 | | .windows => @panic("TODO"), |
| 16483 | | .wasi => @panic("TODO"), |
| 16484 | | else => { |
| 16485 | | var i: usize = 0; |
| 16486 | | const syscall: Syscall = try .start(); |
| 16487 | | while (true) { |
| 16488 | | const buf = memory[i..]; |
| 16489 | | if (buf.len == 0) { |
| 16490 | | syscall.finish(); |
| 16491 | | break; |
| 16492 | | } |
| 16493 | | const rc = pread_sym(file.handle, buf.ptr, buf.len, @intCast(offset + i)); |
| 16494 | | switch (posix.errno(rc)) { |
| 16495 | | .SUCCESS => { |
| 16496 | | const n: usize = @intCast(rc); |
| 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| { |
| 16482 | if (is_windows) { |
| 16483 | @panic("TODO"); |
| 16484 | } else if (native_os == .wasi and !builtin.link_libc) { |
| 16485 | var i: usize = 0; |
| 16486 | const syscall: Syscall = try .start(); |
| 16487 | while (true) { |
| 16488 | const buf = memory[i..]; |
| 16489 | if (buf.len == 0) { |
| 16490 | syscall.finish(); |
| 16491 | break; |
| 16492 | } |
| 16493 | var n: usize = undefined; |
| 16494 | const vec: std.os.wasi.iovec_t = .{ .base = buf.ptr, .len = buf.len }; |
| 16495 | switch (std.os.wasi.fd_pread(file.handle, (&vec)[0..1], 1, offset + i, &n)) { |
| 16496 | .SUCCESS => { |
| 16497 | if (n == 0) { |
| 16523 | 16498 | syscall.finish(); |
| 16524 | | if (native_os == .wasi) return error.IsDir; // File operation on directory. |
| 16525 | | return errnoBug(err); // File descriptor used after closed. |
| 16526 | | }, |
| 16527 | | else => |err| return syscall.unexpectedErrno(err), |
| 16528 | | } |
| 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 | .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 | 16572 | fn mmSyncWrite(file: File, memory: []u8, offset: u64) File.WritePositionalError!void { |
| 16535 | | switch (native_os) { |
| 16536 | | .windows => @panic("TODO"), |
| 16537 | | .wasi => @panic("TODO"), |
| 16538 | | else => { |
| 16539 | | var i: usize = 0; |
| 16540 | | const syscall: Syscall = try .start(); |
| 16541 | | while (true) { |
| 16542 | | const buf = memory[i..]; |
| 16543 | | if (buf.len == 0) { |
| 16544 | | syscall.finish(); |
| 16545 | | 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 | | } |
| 16573 | if (is_windows) { |
| 16574 | @panic("TODO"); |
| 16575 | } else if (native_os == .wasi and !builtin.link_libc) { |
| 16576 | var i: usize = 0; |
| 16577 | var n: usize = undefined; |
| 16578 | const syscall: Syscall = try .start(); |
| 16579 | while (true) { |
| 16580 | const buf = memory[i..]; |
| 16581 | if (buf.len == 0) { |
| 16582 | syscall.finish(); |
| 16583 | break; |
| 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 | } |