std: Add setEndPos to fs.file
Allow the user to shrink/grow the file size as needed.master
parent
89d7fc773d
commit
11df0d0cf8
|
@ -79,6 +79,7 @@ pub extern "c" fn fstatat(dirfd: fd_t, path: [*:0]const u8, stat_buf: *Stat, fla
|
||||||
pub extern "c" fn lseek(fd: fd_t, offset: off_t, whence: c_int) off_t;
|
pub extern "c" fn lseek(fd: fd_t, offset: off_t, whence: c_int) off_t;
|
||||||
pub extern "c" fn open(path: [*:0]const u8, oflag: c_uint, ...) c_int;
|
pub extern "c" fn open(path: [*:0]const u8, oflag: c_uint, ...) c_int;
|
||||||
pub extern "c" fn openat(fd: c_int, path: [*:0]const u8, oflag: c_uint, ...) c_int;
|
pub extern "c" fn openat(fd: c_int, path: [*:0]const u8, oflag: c_uint, ...) c_int;
|
||||||
|
pub extern "c" fn ftruncate(fd: c_int, length: off_t) c_int;
|
||||||
pub extern "c" fn raise(sig: c_int) c_int;
|
pub extern "c" fn raise(sig: c_int) c_int;
|
||||||
pub extern "c" fn read(fd: fd_t, buf: [*]u8, nbyte: usize) isize;
|
pub extern "c" fn read(fd: fd_t, buf: [*]u8, nbyte: usize) isize;
|
||||||
pub extern "c" fn readv(fd: c_int, iov: [*]const iovec, iovcnt: c_uint) isize;
|
pub extern "c" fn readv(fd: c_int, iov: [*]const iovec, iovcnt: c_uint) isize;
|
||||||
|
|
|
@ -82,6 +82,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 memfd_create(name: [*:0]const u8, flags: c_uint) c_int;
|
||||||
|
|
||||||
|
pub extern "c" fn ftruncate64(fd: c_int, length: off_t) c_int;
|
||||||
|
|
||||||
pub extern "c" fn sendfile(
|
pub extern "c" fn sendfile(
|
||||||
out_fd: fd_t,
|
out_fd: fd_t,
|
||||||
in_fd: fd_t,
|
in_fd: fd_t,
|
||||||
|
|
|
@ -99,6 +99,14 @@ pub const File = struct {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const SetEndPosError = os.TruncateError;
|
||||||
|
|
||||||
|
/// Shrinks or expands the file.
|
||||||
|
/// The file offset after this call is undefined.
|
||||||
|
pub fn setEndPos(self: File, length: u64) SetEndPosError!void {
|
||||||
|
try os.truncate(self.handle, length);
|
||||||
|
}
|
||||||
|
|
||||||
pub const SeekError = os.SeekError;
|
pub const SeekError = os.SeekError;
|
||||||
|
|
||||||
/// Repositions read/write file offset relative to the current offset.
|
/// Repositions read/write file offset relative to the current offset.
|
||||||
|
|
|
@ -125,6 +125,23 @@ test "File seek ops" {
|
||||||
expect((try file.getPos()) == 1234);
|
expect((try file.getPos()) == 1234);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "setEndPos" {
|
||||||
|
const tmp_file_name = "temp_test_file.txt";
|
||||||
|
var file = try fs.cwd().createFile(tmp_file_name, .{});
|
||||||
|
defer {
|
||||||
|
file.close();
|
||||||
|
fs.cwd().deleteFile(tmp_file_name) catch {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std.testing.expect((try file.getEndPos()) == 0);
|
||||||
|
try file.setEndPos(8192);
|
||||||
|
std.testing.expect((try file.getEndPos()) == 8192);
|
||||||
|
try file.setEndPos(4096);
|
||||||
|
std.testing.expect((try file.getEndPos()) == 4096);
|
||||||
|
try file.setEndPos(0);
|
||||||
|
std.testing.expect((try file.getEndPos()) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
test "updateTimes" {
|
test "updateTimes" {
|
||||||
const tmp_file_name = "just_a_temporary_file.txt";
|
const tmp_file_name = "just_a_temporary_file.txt";
|
||||||
var file = try fs.cwd().createFile(tmp_file_name, .{ .read = true });
|
var file = try fs.cwd().createFile(tmp_file_name, .{ .read = true });
|
||||||
|
|
|
@ -438,6 +438,39 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const TruncateError = error{
|
||||||
|
/// The file descriptor is not open for writing.
|
||||||
|
NotFile,
|
||||||
|
} || UnexpectedError;
|
||||||
|
|
||||||
|
pub fn truncate(fd: fd_t, length: u64) TruncateError!void {
|
||||||
|
if (std.Target.current.os.tag == .windows) {
|
||||||
|
try windows.SetFilePointerEx_BEGIN(fd, length);
|
||||||
|
|
||||||
|
if (windows.kernel32.SetEndOfFile(fd) == 0)
|
||||||
|
return TruncateError.Unexpected;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const rc = if (builtin.link_libc) blk: {
|
||||||
|
if (std.Target.current.os.tag == .linux)
|
||||||
|
break :blk system.ftruncate64(fd, @bitCast(off_t, length))
|
||||||
|
else
|
||||||
|
break :blk system.ftruncate(fd, @bitCast(off_t, length));
|
||||||
|
} else
|
||||||
|
system.ftruncate(fd, length);
|
||||||
|
|
||||||
|
switch (errno(rc)) {
|
||||||
|
0 => return,
|
||||||
|
EINTR => continue,
|
||||||
|
EBADF, EINVAL => return error.NotFile,
|
||||||
|
else => |err| return unexpectedErrno(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Number of bytes read is returned. Upon reading end-of-file, zero is returned.
|
/// Number of bytes read is returned. Upon reading end-of-file, zero is returned.
|
||||||
///
|
///
|
||||||
/// Retries when interrupted by a signal.
|
/// Retries when interrupted by a signal.
|
||||||
|
|
|
@ -390,6 +390,33 @@ pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
|
||||||
return syscall3(SYS_write, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), count);
|
return syscall3(SYS_write, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ftruncate(fd: i32, length: u64) usize {
|
||||||
|
if (@hasDecl(@This(), "SYS_ftruncate64")) {
|
||||||
|
if (require_aligned_register_pair) {
|
||||||
|
return syscall4(
|
||||||
|
SYS_ftruncate64,
|
||||||
|
@bitCast(usize, @as(isize, fd)),
|
||||||
|
0,
|
||||||
|
@truncate(usize, length),
|
||||||
|
@truncate(usize, length >> 32),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return syscall3(
|
||||||
|
SYS_ftruncate64,
|
||||||
|
@bitCast(usize, @as(isize, fd)),
|
||||||
|
@truncate(usize, length),
|
||||||
|
@truncate(usize, length >> 32),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return syscall2(
|
||||||
|
SYS_ftruncate,
|
||||||
|
@bitCast(usize, @as(isize, fd)),
|
||||||
|
@truncate(usize, length),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
|
pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize {
|
||||||
if (@hasDecl(@This(), "SYS_pwrite64")) {
|
if (@hasDecl(@This(), "SYS_pwrite64")) {
|
||||||
if (require_aligned_register_pair) {
|
if (require_aligned_register_pair) {
|
||||||
|
|
|
@ -8,6 +8,7 @@ pub extern "kernel32" fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) c
|
||||||
pub extern "kernel32" fn CloseHandle(hObject: HANDLE) callconv(.Stdcall) BOOL;
|
pub extern "kernel32" fn CloseHandle(hObject: HANDLE) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" fn CreateDirectoryW(lpPathName: [*:0]const u16, lpSecurityAttributes: ?*SECURITY_ATTRIBUTES) callconv(.Stdcall) BOOL;
|
pub extern "kernel32" fn CreateDirectoryW(lpPathName: [*:0]const u16, lpSecurityAttributes: ?*SECURITY_ATTRIBUTES) callconv(.Stdcall) BOOL;
|
||||||
|
pub extern "kernel32" fn SetEndOfFile(hFile: HANDLE) callconv(.Stdcall) BOOL;
|
||||||
|
|
||||||
pub extern "kernel32" fn CreateEventExW(
|
pub extern "kernel32" fn CreateEventExW(
|
||||||
lpEventAttributes: ?*SECURITY_ATTRIBUTES,
|
lpEventAttributes: ?*SECURITY_ATTRIBUTES,
|
||||||
|
|
Loading…
Reference in New Issue