| ... | @@ -4945,7 +4945,9 @@ pub fn sendfile( | ... | @@ -4945,7 +4945,9 @@ pub fn sendfile( |
| 4945 | pub const CopyFileRangeError = error{ | 4945 | pub const CopyFileRangeError = error{ |
| 4946 | FileTooBig, | 4946 | FileTooBig, |
| 4947 | InputOutput, | 4947 | InputOutput, |
| 4948 | InvalidFileDescriptor, | 4948 | /// `fd_in` is not open for reading; or `fd_out` is not open for writing; |
| | 4949 | /// or the `O_APPEND` flag is set for `fd_out`. |
| | 4950 | FilesOpenedWithWrongFlags, |
| 4949 | IsDir, | 4951 | IsDir, |
| 4950 | OutOfMemory, | 4952 | OutOfMemory, |
| 4951 | NoSpaceLeft, | 4953 | NoSpaceLeft, |
| ... | @@ -4955,7 +4957,7 @@ pub const CopyFileRangeError = error{ | ... | @@ -4955,7 +4957,7 @@ pub const CopyFileRangeError = error{ |
| 4955 | } || PReadError || PWriteError || UnexpectedError; | 4957 | } || PReadError || PWriteError || UnexpectedError; |
| 4956 | | 4958 | |
| 4957 | var has_copy_file_range_syscall = init: { | 4959 | var has_copy_file_range_syscall = init: { |
| 4958 | const kernel_has_syscall = comptime std.Target.current.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse true; | 4960 | const kernel_has_syscall = std.Target.current.os.isAtLeast(.linux, .{ .major = 4, .minor = 5 }) orelse true; |
| 4959 | break :init std.atomic.Int(bool).init(kernel_has_syscall); | 4961 | break :init std.atomic.Int(bool).init(kernel_has_syscall); |
| 4960 | }; | 4962 | }; |
| 4961 | | 4963 | |
| ... | @@ -4998,7 +5000,7 @@ pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len | ... | @@ -4998,7 +5000,7 @@ pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len |
| 4998 | const rc = sys.copy_file_range(fd_in, &off_in_copy, fd_out, &off_out_copy, len, flags); | 5000 | const rc = sys.copy_file_range(fd_in, &off_in_copy, fd_out, &off_out_copy, len, flags); |
| 4999 | switch (sys.getErrno(rc)) { | 5001 | switch (sys.getErrno(rc)) { |
| 5000 | 0 => return @intCast(usize, rc), | 5002 | 0 => return @intCast(usize, rc), |
| 5001 | EBADF => return error.InvalidFileDescriptor, | 5003 | EBADF => return error.FilesOpenedWithWrongFlags, |
| 5002 | EFBIG => return error.FileTooBig, | 5004 | EFBIG => return error.FileTooBig, |
| 5003 | EIO => return error.InputOutput, | 5005 | EIO => return error.InputOutput, |
| 5004 | EISDIR => return error.IsDir, | 5006 | EISDIR => return error.IsDir, |
| ... | @@ -5019,24 +5021,13 @@ pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len | ... | @@ -5019,24 +5021,13 @@ pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len |
| 5019 | } | 5021 | } |
| 5020 | } | 5022 | } |
| 5021 | | 5023 | |
| 5022 | var buf: [2 * 4096]u8 = undefined; | 5024 | var buf: [8 * 4096]u8 = undefined; |
| 5023 | | 5025 | const adjusted_count = math.min(buf.len, len); |
| 5024 | var total_copied: usize = 0; | 5026 | const amt_read = try pread(fd_in, buf[0..adjusted_count], off_in); |
| 5025 | var read_off = off_in; | 5027 | // TODO without @as the line below fails to compile for wasm32-wasi: |
| 5026 | var write_off = off_out; | 5028 | // error: integer value 0 cannot be coerced to type 'os.PWriteError!usize' |
| 5027 | while (total_copied < len) { | 5029 | if (amt_read == 0) return @as(usize, 0); |
| 5028 | const adjusted_count = math.min(buf.len, len - total_copied); | 5030 | return pwrite(fd_out, buf[0..amt_read], off_out); |
| 5029 | const amt_read = try pread(fd_in, buf[0..adjusted_count], read_off); | | |
| 5030 | if (amt_read == 0) break; | | |
| 5031 | const amt_written = try pwrite(fd_out, buf[0..amt_read], write_off); | | |
| 5032 | // pwrite may write less than the specified amount, handle the remaining | | |
| 5033 | // chunk of data in the next iteration | | |
| 5034 | read_off += amt_written; | | |
| 5035 | write_off += amt_written; | | |
| 5036 | total_copied += amt_written; | | |
| 5037 | } | | |
| 5038 | | | |
| 5039 | return total_copied; | | |
| 5040 | } | 5031 | } |
| 5041 | | 5032 | |
| 5042 | pub const PollError = error{ | 5033 | pub const PollError = error{ |