diff --git a/lib/std/c/linux.zig b/lib/std/c/linux.zig index d48c76c7a6..4ec2fdad33 100644 --- a/lib/std/c/linux.zig +++ b/lib/std/c/linux.zig @@ -87,6 +87,8 @@ pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; pub extern "c" fn memfd_create(name: [*:0]const u8, flags: c_uint) c_int; +pub extern "c" fn fallocate(fd: fd_t, mode: c_int, offset: off_t, len: off_t) c_int; + pub extern "c" fn ftruncate64(fd: c_int, length: off_t) c_int; pub extern "c" fn sendfile( diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index ce9b4a90d1..f53f102c2a 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -84,6 +84,27 @@ pub const AT_STATX_DONT_SYNC = 0x4000; /// Apply to the entire subtree pub const AT_RECURSIVE = 0x8000; +/// Default is extend size +pub const FALLOC_FL_KEEP_SIZE = 0x01; + +/// De-allocates range +pub const FALLOC_FL_PUNCH_HOLE = 0x02; + +/// Reserved codepoint +pub const FALLOC_FL_NO_HIDE_STALE = 0x04; + +/// Removes a range of a file without leaving a hole in the file +pub const FALLOC_FL_COLLAPSE_RANGE = 0x08; + +/// Converts a range of file to zeros preferably without issuing data IO +pub const FALLOC_FL_ZERO_RANGE = 0x10; + +/// Inserts space within the file size without overwriting any existing data +pub const FALLOC_FL_INSERT_RANGE = 0x20; + +/// Unshares shared blocks within the file size without overwriting any existing data +pub const FALLOC_FL_UNSHARE_RANGE = 0x40; + pub const FUTEX_WAIT = 0; pub const FUTEX_WAKE = 1; pub const FUTEX_FD = 2; diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index c5fbd0bcfe..c422826f13 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -136,6 +136,30 @@ pub fn utimensat(dirfd: i32, path: ?[*:0]const u8, times: *const [2]timespec, fl return syscall4(.utimensat, @bitCast(usize, @as(isize, dirfd)), @ptrToInt(path), @ptrToInt(times), flags); } +pub fn fallocate(fd: i32, mode: i32, offset: u64, length: u64) usize { + if (@sizeOf(usize) == 4) { + const offset_halves = splitValue64(offset); + const length_halves = splitValue64(length); + return syscall6( + .fallocate, + @bitCast(usize, @as(isize, fd)), + @bitCast(usize, @as(isize, mode)), + offset_halves[0], + offset_halves[1], + length_halves[0], + length_halves[1], + ); + } else { + return syscall4( + .fallocate, + @bitCast(usize, @as(isize, fd)), + @bitCast(usize, @as(isize, mode)), + offset, + length, + ); + } +} + pub fn futex_wait(uaddr: *const i32, futex_op: u32, val: i32, timeout: ?*timespec) usize { return syscall4(.futex, @ptrToInt(uaddr), futex_op, @bitCast(u32, val), @ptrToInt(timeout)); } diff --git a/lib/std/os/linux/test.zig b/lib/std/os/linux/test.zig index 7599cfc395..b182fa3f61 100644 --- a/lib/std/os/linux/test.zig +++ b/lib/std/os/linux/test.zig @@ -11,6 +11,25 @@ const elf = std.elf; const expect = std.testing.expect; const fs = std.fs; +test "fallocate" { + const path = "test_fallocate"; + const file = try fs.cwd().createFile(path, .{ .truncate = true, .mode = 0o666 }); + defer file.close(); + defer fs.cwd().deleteFile(path) catch {}; + + expect((try file.stat()).size == 0); + + const len: u64 = 65536; + switch (linux.getErrno(linux.fallocate(file.handle, 0, 0, len))) { + 0 => {}, + linux.ENOSYS => return error.SkipZigTest, + linux.EOPNOTSUPP => return error.SkipZigTest, + else => |errno| std.debug.panic("unhandled errno: {}", .{ errno }), + } + + expect((try file.stat()).size == len); +} + test "getpid" { expect(linux.getpid() != 0); }