| ... | ... | @@ -474,7 +474,7 @@ pub fn dup2(old: i32, new: i32) usize { |
| 474 | 474 | } else { |
| 475 | 475 | if (old == new) { |
| 476 | 476 | if (std.debug.runtime_safety) { |
| 477 | | const rc = syscall2(.fcntl, @as(usize, @bitCast(@as(isize, old))), F.GETFD); |
| 477 | const rc = fcntl(F.GETFD, @as(fd_t, old), 0); |
| 478 | 478 | if (@as(isize, @bitCast(rc)) < 0) return rc; |
| 479 | 479 | } |
| 480 | 480 | return @as(usize, @intCast(old)); |
| ... | ... | @@ -1211,7 +1211,7 @@ pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize { |
| 1211 | 1211 | // NOTE: The offset parameter splitting is independent from the target |
| 1212 | 1212 | // endianness. |
| 1213 | 1213 | return syscall5( |
| 1214 | | ._llseek, |
| 1214 | .llseek, |
| 1215 | 1215 | @as(usize, @bitCast(@as(isize, fd))), |
| 1216 | 1216 | @as(usize, @truncate(offset >> 32)), |
| 1217 | 1217 | @as(usize, @truncate(offset)), |
| ... | ... | @@ -1370,7 +1370,11 @@ pub fn waitid(id_type: P, id: i32, infop: *siginfo_t, flags: u32) usize { |
| 1370 | 1370 | } |
| 1371 | 1371 | |
| 1372 | 1372 | pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) usize { |
| 1373 | | return syscall3(.fcntl, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg); |
| 1373 | if (@hasField(SYS, "fcntl64")) { |
| 1374 | return syscall3(.fcntl64, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg); |
| 1375 | } else { |
| 1376 | return syscall3(.fcntl, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg); |
| 1377 | } |
| 1374 | 1378 | } |
| 1375 | 1379 | |
| 1376 | 1380 | pub fn flock(fd: fd_t, operation: i32) usize { |
| ... | ... | @@ -2198,40 +2202,40 @@ pub fn process_vm_writev(pid: pid_t, local: []const iovec_const, remote: []const |
| 2198 | 2202 | } |
| 2199 | 2203 | |
| 2200 | 2204 | pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize { |
| 2201 | | if (comptime builtin.cpu.arch.isMIPS()) { |
| 2202 | | // MIPS requires a 7 argument syscall |
| 2205 | if (comptime native_arch.isARM() or native_arch.isPPC()) { |
| 2206 | // These architectures reorder the arguments so that a register is not skipped to align the |
| 2207 | // register number that `offset` is passed in. |
| 2203 | 2208 | |
| 2204 | 2209 | const offset_halves = splitValue64(offset); |
| 2205 | 2210 | const length_halves = splitValue64(len); |
| 2206 | 2211 | |
| 2207 | | return syscall7( |
| 2208 | | .fadvise64, |
| 2212 | return syscall6( |
| 2213 | .fadvise64_64, |
| 2209 | 2214 | @as(usize, @bitCast(@as(isize, fd))), |
| 2210 | | 0, |
| 2215 | advice, |
| 2211 | 2216 | offset_halves[0], |
| 2212 | 2217 | offset_halves[1], |
| 2213 | 2218 | length_halves[0], |
| 2214 | 2219 | length_halves[1], |
| 2215 | | advice, |
| 2216 | 2220 | ); |
| 2217 | | } else if (comptime builtin.cpu.arch.isARM()) { |
| 2218 | | // ARM reorders the arguments |
| 2221 | } else if (comptime native_arch == .mips or native_arch == .mipsel) { |
| 2222 | // MIPS O32 does not deal with the register alignment issue, so pass a dummy value. |
| 2219 | 2223 | |
| 2220 | 2224 | const offset_halves = splitValue64(offset); |
| 2221 | 2225 | const length_halves = splitValue64(len); |
| 2222 | 2226 | |
| 2223 | | return syscall6( |
| 2224 | | .fadvise64_64, |
| 2227 | return syscall7( |
| 2228 | .fadvise64, |
| 2225 | 2229 | @as(usize, @bitCast(@as(isize, fd))), |
| 2226 | | advice, |
| 2230 | 0, |
| 2227 | 2231 | offset_halves[0], |
| 2228 | 2232 | offset_halves[1], |
| 2229 | 2233 | length_halves[0], |
| 2230 | 2234 | length_halves[1], |
| 2235 | advice, |
| 2231 | 2236 | ); |
| 2232 | | } else if (@hasField(SYS, "fadvise64_64") and usize_bits != 64) { |
| 2233 | | // The extra usize check is needed to avoid SPARC64 because it provides both |
| 2234 | | // fadvise64 and fadvise64_64 but the latter behaves differently than other platforms. |
| 2237 | } else if (comptime usize_bits < 64) { |
| 2238 | // Other 32-bit architectures do not require register alignment. |
| 2235 | 2239 | |
| 2236 | 2240 | const offset_halves = splitValue64(offset); |
| 2237 | 2241 | const length_halves = splitValue64(len); |
| ... | ... | @@ -2246,8 +2250,18 @@ pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize { |
| 2246 | 2250 | advice, |
| 2247 | 2251 | ); |
| 2248 | 2252 | } else { |
| 2253 | // On 64-bit architectures, fadvise64_64 and fadvise64 are the same. Generally, older ports |
| 2254 | // call it fadvise64 (x86, PowerPC, etc), while newer ports call it fadvise64_64 (RISC-V, |
| 2255 | // LoongArch, etc). SPARC is the odd one out because it has both. |
| 2249 | 2256 | return syscall4( |
| 2250 | | .fadvise64, |
| 2257 | // 64-bit SPARC (apparently?) has a broken fadvise64_64, so use its fadvise64 instead. |
| 2258 | // TODO: I can't make sense of this. They go to the same code in the kernel, and there |
| 2259 | // is no special-casing for SPARC in glibc and musl. I suspect a QEMU bug, which is |
| 2260 | // really not our responsibility. |
| 2261 | if (@hasField(SYS, "fadvise64_64") and native_arch != .sparc64) |
| 2262 | .fadvise64_64 |
| 2263 | else |
| 2264 | .fadvise64, |
| 2251 | 2265 | @as(usize, @bitCast(@as(isize, fd))), |
| 2252 | 2266 | @as(usize, @bitCast(offset)), |
| 2253 | 2267 | @as(usize, @bitCast(len)), |