authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2021-05-07 09:41:26+02:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2021-05-11 12:33:47+02:00
loga909db6aea38f65ffe996d61a62a4f1bd2cbc44c
treea6893a890c42ffbdfc5da44c2632b67e65130eed
parent28a9e4c4aaff3a186c344d98d2a2bf918d20a13c

std: Prefer 64bit libc functions where possible

While musl decided to hard-wire off_t to a 64bit quantity, glibc is much older and defaults to 32bit offsets and offers some -64 suffixed versions of I/O functions. There's a weird mix-up of types: sometimes off_t is used, sometimes not, sometimes it's defined as a signed quantity and sometimes as an unsigned one, but we'll sort this problem later.

2 files changed, 107 insertions(+), 26 deletions(-)

lib/std/c/linux.zig+17-2
...@@ -61,6 +61,23 @@ pub const EAI = extern enum(c_int) {...@@ -61,6 +61,23 @@ pub const EAI = extern enum(c_int) {
61 _,61 _,
62};62};
6363
64pub extern "c" fn fallocate64(fd: fd_t, mode: c_int, offset: i64, len: i64) c_int;
65pub extern "c" fn fopen64(noalias filename: [*:0]const u8, noalias modes: [*:0]const u8) ?*FILE;
66pub extern "c" fn fstat64(fd: fd_t, buf: *libc_stat) c_int;
67pub extern "c" fn fstatat64(dirfd: fd_t, path: [*:0]const u8, stat_buf: *libc_stat, flags: u32) c_int;
68pub extern "c" fn ftruncate64(fd: c_int, length: i64) c_int;
69pub extern "c" fn getrlimit64(resource: rlimit_resource, rlim: *rlimit) c_int;
70pub extern "c" fn lseek64(fd: fd_t, offset: u64, whence: c_int) u64;
71pub extern "c" fn mmap64(addr: ?*align(std.mem.page_size) c_void, len: usize, prot: c_uint, flags: c_uint, fd: fd_t, offset: u64) *c_void;
72pub extern "c" fn open64(path: [*:0]const u8, oflag: c_uint, ...) c_int;
73pub extern "c" fn openat64(fd: c_int, path: [*:0]const u8, oflag: c_uint, ...) c_int;
74pub extern "c" fn pread64(fd: fd_t, buf: [*]u8, nbyte: usize, offset: u64) isize;
75pub extern "c" fn preadv64(fd: c_int, iov: [*]const iovec, iovcnt: c_uint, offset: u64) isize;
76pub extern "c" fn pwrite64(fd: fd_t, buf: [*]const u8, nbyte: usize, offset: u64) isize;
77pub extern "c" fn pwritev64(fd: c_int, iov: [*]const iovec_const, iovcnt: c_uint, offset: u64) isize;
78pub extern "c" fn sendfile64(out_fd: fd_t, in_fd: fd_t, offset: ?*i64, count: usize) isize;
79pub extern "c" fn setrlimit64(resource: rlimit_resource, rlim: *const rlimit) c_int;
80
64pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize;81pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize;
65pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int;82pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int;
66pub extern "c" fn eventfd(initval: c_uint, flags: c_uint) c_int;83pub extern "c" fn eventfd(initval: c_uint, flags: c_uint) c_int;
...@@ -90,8 +107,6 @@ pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int;...@@ -90,8 +107,6 @@ pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int;
90107
91pub extern "c" fn fallocate(fd: fd_t, mode: c_int, offset: off_t, len: off_t) c_int;108pub extern "c" fn fallocate(fd: fd_t, mode: c_int, offset: off_t, len: off_t) c_int;
92109
93pub extern "c" fn ftruncate64(fd: c_int, length: off_t) c_int;
94
95pub extern "c" fn sendfile(110pub extern "c" fn sendfile(
96 out_fd: fd_t,111 out_fd: fd_t,
97 in_fd: fd_t,112 in_fd: fd_t,
lib/std/os.zig+90-24
...@@ -497,8 +497,13 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {...@@ -497,8 +497,13 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {
497 };497 };
498 const adjusted_len = math.min(max_count, buf.len);498 const adjusted_len = math.min(max_count, buf.len);
499499
500 const pread_sym = if (builtin.os.tag == .linux and builtin.link_libc)
501 system.pread64
502 else
503 system.pread;
504
500 while (true) {505 while (true) {
501 const rc = system.pread(fd, buf.ptr, adjusted_len, offset);506 const rc = pread_sym(fd, buf.ptr, adjusted_len, offset);
502 switch (errno(rc)) {507 switch (errno(rc)) {
503 0 => return @intCast(usize, rc),508 0 => return @intCast(usize, rc),
504 EINTR => continue,509 EINTR => continue,
...@@ -567,15 +572,12 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {...@@ -567,15 +572,12 @@ pub fn ftruncate(fd: fd_t, length: u64) TruncateError!void {
567 }572 }
568573
569 while (true) {574 while (true) {
570 const rc = if (builtin.link_libc)575 const ftruncate_sym = if (builtin.os.tag == .linux and builtin.link_libc)
571 if (std.Target.current.os.tag == .linux)576 system.ftruncate64
572 system.ftruncate64(fd, @bitCast(off_t, length))
573 else
574 system.ftruncate(fd, @bitCast(off_t, length))
575 else577 else
576 system.ftruncate(fd, length);578 system.ftruncate;
577579
578 switch (errno(rc)) {580 switch (errno(ftruncate_sym(fd, @bitCast(off_t, length)))) {
579 0 => return,581 0 => return,
580 EINTR => continue,582 EINTR => continue,
581 EFBIG => return error.FileTooBig,583 EFBIG => return error.FileTooBig,
...@@ -637,8 +639,13 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize {...@@ -637,8 +639,13 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize {
637639
638 const iov_count = math.cast(u31, iov.len) catch math.maxInt(u31);640 const iov_count = math.cast(u31, iov.len) catch math.maxInt(u31);
639641
642 const preadv_sym = if (builtin.os.tag == .linux and builtin.link_libc)
643 system.preadv64
644 else
645 system.preadv;
646
640 while (true) {647 while (true) {
641 const rc = system.preadv(fd, iov.ptr, iov_count, offset);648 const rc = preadv_sym(fd, iov.ptr, iov_count, offset);
642 switch (errno(rc)) {649 switch (errno(rc)) {
643 0 => return @bitCast(usize, rc),650 0 => return @bitCast(usize, rc),
644 EINTR => continue,651 EINTR => continue,
...@@ -895,8 +902,13 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {...@@ -895,8 +902,13 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {
895 };902 };
896 const adjusted_len = math.min(max_count, bytes.len);903 const adjusted_len = math.min(max_count, bytes.len);
897904
905 const pwrite_sym = if (builtin.os.tag == .linux and builtin.link_libc)
906 system.pwrite64
907 else
908 system.pwrite;
909
898 while (true) {910 while (true) {
899 const rc = system.pwrite(fd, bytes.ptr, adjusted_len, offset);911 const rc = pwrite_sym(fd, bytes.ptr, adjusted_len, offset);
900 switch (errno(rc)) {912 switch (errno(rc)) {
901 0 => return @intCast(usize, rc),913 0 => return @intCast(usize, rc),
902 EINTR => continue,914 EINTR => continue,
...@@ -977,9 +989,14 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz...@@ -977,9 +989,14 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz
977 }989 }
978 }990 }
979991
992 const pwritev_sym = if (builtin.os.tag == .linux and builtin.link_libc)
993 system.pwritev64
994 else
995 system.pwritev;
996
980 const iov_count = math.cast(u31, iov.len) catch math.maxInt(u31);997 const iov_count = math.cast(u31, iov.len) catch math.maxInt(u31);
981 while (true) {998 while (true) {
982 const rc = system.pwritev(fd, iov.ptr, iov_count, offset);999 const rc = pwritev_sym(fd, iov.ptr, iov_count, offset);
983 switch (errno(rc)) {1000 switch (errno(rc)) {
984 0 => return @intCast(usize, rc),1001 0 => return @intCast(usize, rc),
985 EINTR => continue,1002 EINTR => continue,
...@@ -1068,8 +1085,14 @@ pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: mode_t) OpenError!fd_t...@@ -1068,8 +1085,14 @@ pub fn openZ(file_path: [*:0]const u8, flags: u32, perm: mode_t) OpenError!fd_t
1068 const file_path_w = try windows.cStrToPrefixedFileW(file_path);1085 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
1069 return openW(file_path_w.span(), flags, perm);1086 return openW(file_path_w.span(), flags, perm);
1070 }1087 }
1088
1089 const open_sym = if (builtin.os.tag == .linux and builtin.link_libc)
1090 system.open64
1091 else
1092 system.open;
1093
1071 while (true) {1094 while (true) {
1072 const rc = system.open(file_path, flags, perm);1095 const rc = open_sym(file_path, flags, perm);
1073 switch (errno(rc)) {1096 switch (errno(rc)) {
1074 0 => return @intCast(fd_t, rc),1097 0 => return @intCast(fd_t, rc),
1075 EINTR => continue,1098 EINTR => continue,
...@@ -1202,8 +1225,14 @@ pub fn openatZ(dir_fd: fd_t, file_path: [*:0]const u8, flags: u32, mode: mode_t)...@@ -1202,8 +1225,14 @@ pub fn openatZ(dir_fd: fd_t, file_path: [*:0]const u8, flags: u32, mode: mode_t)
1202 const file_path_w = try windows.cStrToPrefixedFileW(file_path);1225 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
1203 return openatW(dir_fd, file_path_w.span(), flags, mode);1226 return openatW(dir_fd, file_path_w.span(), flags, mode);
1204 }1227 }
1228
1229 const openat_sym = if (builtin.os.tag == .linux and builtin.link_libc)
1230 system.openat64
1231 else
1232 system.openat;
1233
1205 while (true) {1234 while (true) {
1206 const rc = system.openat(dir_fd, file_path, flags, mode);1235 const rc = openat_sym(dir_fd, file_path, flags, mode);
1207 switch (errno(rc)) {1236 switch (errno(rc)) {
1208 0 => return @intCast(fd_t, rc),1237 0 => return @intCast(fd_t, rc),
1209 EINTR => continue,1238 EINTR => continue,
...@@ -3437,8 +3466,13 @@ pub fn fstat(fd: fd_t) FStatError!Stat {...@@ -3437,8 +3466,13 @@ pub fn fstat(fd: fd_t) FStatError!Stat {
3437 @compileError("fstat is not yet implemented on Windows");3466 @compileError("fstat is not yet implemented on Windows");
3438 }3467 }
34393468
3469 const fstat_sym = if (builtin.os.tag == .linux and builtin.link_libc)
3470 system.fstat64
3471 else
3472 system.fstat;
3473
3440 var stat = mem.zeroes(Stat);3474 var stat = mem.zeroes(Stat);
3441 switch (errno(system.fstat(fd, &stat))) {3475 switch (errno(fstat_sym(fd, &stat))) {
3442 0 => return stat,3476 0 => return stat,
3443 EINVAL => unreachable,3477 EINVAL => unreachable,
3444 EBADF => unreachable, // Always a race condition.3478 EBADF => unreachable, // Always a race condition.
...@@ -3488,8 +3522,13 @@ pub fn fstatatWasi(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!S...@@ -3488,8 +3522,13 @@ pub fn fstatatWasi(dirfd: fd_t, pathname: []const u8, flags: u32) FStatAtError!S
3488/// Same as `fstatat` but `pathname` is null-terminated.3522/// Same as `fstatat` but `pathname` is null-terminated.
3489/// See also `fstatat`.3523/// See also `fstatat`.
3490pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!Stat {3524pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!Stat {
3525 const fstatat_sym = if (builtin.os.tag == .linux and builtin.link_libc)
3526 system.fstatat64
3527 else
3528 system.fstatat;
3529
3491 var stat = mem.zeroes(Stat);3530 var stat = mem.zeroes(Stat);
3492 switch (errno(system.fstatat(dirfd, pathname, &stat, flags))) {3531 switch (errno(fstatat_sym(dirfd, pathname, &stat, flags))) {
3493 0 => return stat,3532 0 => return stat,
3494 EINVAL => unreachable,3533 EINVAL => unreachable,
3495 EBADF => unreachable, // Always a race condition.3534 EBADF => unreachable, // Always a race condition.
...@@ -3701,12 +3740,16 @@ pub fn mmap(...@@ -3701,12 +3740,16 @@ pub fn mmap(
3701 fd: fd_t,3740 fd: fd_t,
3702 offset: u64,3741 offset: u64,
3703) MMapError![]align(mem.page_size) u8 {3742) MMapError![]align(mem.page_size) u8 {
3743 const mmap_sym = if (builtin.os.tag == .linux and builtin.link_libc)
3744 system.mmap64
3745 else
3746 system.mmap;
3747
3748 const rc = mmap_sym(ptr, length, prot, flags, fd, offset);
3704 const err = if (builtin.link_libc) blk: {3749 const err = if (builtin.link_libc) blk: {
3705 const rc = std.c.mmap(ptr, length, prot, flags, fd, offset);
3706 if (rc != std.c.MAP_FAILED) return @ptrCast([*]align(mem.page_size) u8, @alignCast(mem.page_size, rc))[0..length];3750 if (rc != std.c.MAP_FAILED) return @ptrCast([*]align(mem.page_size) u8, @alignCast(mem.page_size, rc))[0..length];
3707 break :blk system._errno().*;3751 break :blk system._errno().*;
3708 } else blk: {3752 } else blk: {
3709 const rc = system.mmap(ptr, length, prot, flags, fd, offset);
3710 const err = errno(rc);3753 const err = errno(rc);
3711 if (err == 0) return @intToPtr([*]align(mem.page_size) u8, rc)[0..length];3754 if (err == 0) return @intToPtr([*]align(mem.page_size) u8, rc)[0..length];
3712 break :blk err;3755 break :blk err;
...@@ -4139,7 +4182,12 @@ pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {...@@ -4139,7 +4182,12 @@ pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {
4139 else => |err| return unexpectedErrno(err),4182 else => |err| return unexpectedErrno(err),
4140 }4183 }
4141 }4184 }
4142 switch (errno(system.lseek(fd, offset, SEEK_END))) {4185 const lseek_sym = if (builtin.os.tag == .linux and builtin.link_libc)
4186 system.lseek64
4187 else
4188 system.lseek;
4189
4190 switch (errno(lseek_sym(fd, offset, SEEK_END))) {
4143 0 => return,4191 0 => return,
4144 EBADF => unreachable, // always a race condition4192 EBADF => unreachable, // always a race condition
4145 EINVAL => return error.Unseekable,4193 EINVAL => return error.Unseekable,
...@@ -4180,7 +4228,12 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {...@@ -4180,7 +4228,12 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {
4180 else => |err| return unexpectedErrno(err),4228 else => |err| return unexpectedErrno(err),
4181 }4229 }
4182 }4230 }
4183 const rc = system.lseek(fd, 0, SEEK_CUR);4231 const lseek_sym = if (builtin.os.tag == .linux and builtin.link_libc)
4232 system.lseek64
4233 else
4234 system.lseek;
4235
4236 const rc = lseek_sym(fd, 0, SEEK_CUR);
4184 switch (errno(rc)) {4237 switch (errno(rc)) {
4185 0 => return @bitCast(u64, rc),4238 0 => return @bitCast(u64, rc),
4186 EBADF => unreachable, // always a race condition4239 EBADF => unreachable, // always a race condition
...@@ -5198,9 +5251,14 @@ pub fn sendfile(...@@ -5198,9 +5251,14 @@ pub fn sendfile(
5198 // Here we match BSD behavior, making a zero count value send as many bytes as possible.5251 // Here we match BSD behavior, making a zero count value send as many bytes as possible.
5199 const adjusted_count = if (in_len == 0) max_count else math.min(in_len, @as(size_t, max_count));5252 const adjusted_count = if (in_len == 0) max_count else math.min(in_len, @as(size_t, max_count));
52005253
5254 const sendfile_sym = if (builtin.link_libc)
5255 system.sendfile64
5256 else
5257 system.sendfile;
5258
5201 while (true) {5259 while (true) {
5202 var offset: off_t = @bitCast(off_t, in_offset);5260 var offset: off_t = @bitCast(off_t, in_offset);
5203 const rc = system.sendfile(out_fd, in_fd, &offset, adjusted_count);5261 const rc = sendfile_sym(out_fd, in_fd, &offset, adjusted_count);
5204 switch (errno(rc)) {5262 switch (errno(rc)) {
5205 0 => {5263 0 => {
5206 const amt = @bitCast(usize, rc);5264 const amt = @bitCast(usize, rc);
...@@ -6018,9 +6076,13 @@ pub fn prctl(option: PR, args: anytype) PrctlError!u31 {...@@ -6018,9 +6076,13 @@ pub fn prctl(option: PR, args: anytype) PrctlError!u31 {
6018pub const GetrlimitError = UnexpectedError;6076pub const GetrlimitError = UnexpectedError;
60196077
6020pub fn getrlimit(resource: rlimit_resource) GetrlimitError!rlimit {6078pub fn getrlimit(resource: rlimit_resource) GetrlimitError!rlimit {
6079 const getrlimit_sym = if (builtin.os.tag == .linux and builtin.link_libc)
6080 system.getrlimit64
6081 else
6082 system.getrlimit;
6083
6021 var limits: rlimit = undefined;6084 var limits: rlimit = undefined;
6022 const rc = system.getrlimit(resource, &limits);6085 switch (errno(getrlimit_sym(resource, &limits))) {
6023 switch (errno(rc)) {
6024 0 => return limits,6086 0 => return limits,
6025 EFAULT => unreachable, // bogus pointer6087 EFAULT => unreachable, // bogus pointer
6026 EINVAL => unreachable,6088 EINVAL => unreachable,
...@@ -6031,8 +6093,12 @@ pub fn getrlimit(resource: rlimit_resource) GetrlimitError!rlimit {...@@ -6031,8 +6093,12 @@ pub fn getrlimit(resource: rlimit_resource) GetrlimitError!rlimit {
6031pub const SetrlimitError = error{PermissionDenied} || UnexpectedError;6093pub const SetrlimitError = error{PermissionDenied} || UnexpectedError;
60326094
6033pub fn setrlimit(resource: rlimit_resource, limits: rlimit) SetrlimitError!void {6095pub fn setrlimit(resource: rlimit_resource, limits: rlimit) SetrlimitError!void {
6034 const rc = system.setrlimit(resource, &limits);6096 const setrlimit_sym = if (builtin.os.tag == .linux and builtin.link_libc)
6035 switch (errno(rc)) {6097 system.setrlimit64
6098 else
6099 system.setrlimit;
6100
6101 switch (errno(setrlimit_sym(resource, &limits))) {
6036 0 => return,6102 0 => return,
6037 EFAULT => unreachable, // bogus pointer6103 EFAULT => unreachable, // bogus pointer
6038 EINVAL => unreachable,6104 EINVAL => unreachable,