| author | |
| committer | |
| log | 11df0d0cf8c786d5b502c21a42d47631657a42f4 |
| tree | b860be3c40159ad2ea9c41f44c3873d1b29e33bb |
| parent | 89d7fc773d66609a8d93106f9a6d84d479771690 |
Allow the user to shrink/grow the file size as needed.7 files changed, 89 insertions(+), 0 deletions(-)
lib/std/c.zig+1| ... | @@ -79,6 +79,7 @@ pub extern "c" fn fstatat(dirfd: fd_t, path: [*:0]const u8, stat_buf: *Stat, fla | ... | @@ -79,6 +79,7 @@ pub extern "c" fn fstatat(dirfd: fd_t, path: [*:0]const u8, stat_buf: *Stat, fla |
| 79 | pub extern "c" fn lseek(fd: fd_t, offset: off_t, whence: c_int) off_t; | 79 | pub extern "c" fn lseek(fd: fd_t, offset: off_t, whence: c_int) off_t; |
| 80 | pub extern "c" fn open(path: [*:0]const u8, oflag: c_uint, ...) c_int; | 80 | pub extern "c" fn open(path: [*:0]const u8, oflag: c_uint, ...) c_int; |
| 81 | pub extern "c" fn openat(fd: c_int, path: [*:0]const u8, oflag: c_uint, ...) c_int; | 81 | pub extern "c" fn openat(fd: c_int, path: [*:0]const u8, oflag: c_uint, ...) c_int; |
| 82 | pub extern "c" fn ftruncate(fd: c_int, length: off_t) c_int; | ||
| 82 | pub extern "c" fn raise(sig: c_int) c_int; | 83 | pub extern "c" fn raise(sig: c_int) c_int; |
| 83 | pub extern "c" fn read(fd: fd_t, buf: [*]u8, nbyte: usize) isize; | 84 | pub extern "c" fn read(fd: fd_t, buf: [*]u8, nbyte: usize) isize; |
| 84 | pub extern "c" fn readv(fd: c_int, iov: [*]const iovec, iovcnt: c_uint) isize; | 85 | pub extern "c" fn readv(fd: c_int, iov: [*]const iovec, iovcnt: c_uint) isize; |
lib/std/c/linux.zig+2| ... | @@ -82,6 +82,8 @@ pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; | ... | @@ -82,6 +82,8 @@ pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; |
| 82 | 82 | ||
| 83 | pub extern "c" fn memfd_create(name: [*:0]const u8, flags: c_uint) c_int; | 83 | pub extern "c" fn memfd_create(name: [*:0]const u8, flags: c_uint) c_int; |
| 84 | 84 | ||
| 85 | pub extern "c" fn ftruncate64(fd: c_int, length: off_t) c_int; | ||
| 86 | |||
| 85 | pub extern "c" fn sendfile( | 87 | pub extern "c" fn sendfile( |
| 86 | out_fd: fd_t, | 88 | out_fd: fd_t, |
| 87 | in_fd: fd_t, | 89 | in_fd: fd_t, |
lib/std/fs/file.zig+8| ... | @@ -99,6 +99,14 @@ pub const File = struct { | ... | @@ -99,6 +99,14 @@ pub const File = struct { |
| 99 | return false; | 99 | return false; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | pub const SetEndPosError = os.TruncateError; | ||
| 103 | |||
| 104 | /// Shrinks or expands the file. | ||
| 105 | /// The file offset after this call is undefined. | ||
| 106 | pub fn setEndPos(self: File, length: u64) SetEndPosError!void { | ||
| 107 | try os.truncate(self.handle, length); | ||
| 108 | } | ||
| 109 | |||
| 102 | pub const SeekError = os.SeekError; | 110 | pub const SeekError = os.SeekError; |
| 103 | 111 | ||
| 104 | /// Repositions read/write file offset relative to the current offset. | 112 | /// Repositions read/write file offset relative to the current offset. |
lib/std/io/test.zig+17| ... | @@ -125,6 +125,23 @@ test "File seek ops" { | ... | @@ -125,6 +125,23 @@ test "File seek ops" { |
| 125 | expect((try file.getPos()) == 1234); | 125 | expect((try file.getPos()) == 1234); |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | test "setEndPos" { | ||
| 129 | const tmp_file_name = "temp_test_file.txt"; | ||
| 130 | var file = try fs.cwd().createFile(tmp_file_name, .{}); | ||
| 131 | defer { | ||
| 132 | file.close(); | ||
| 133 | fs.cwd().deleteFile(tmp_file_name) catch {}; | ||
| 134 | } | ||
| 135 | |||
| 136 | std.testing.expect((try file.getEndPos()) == 0); | ||
| 137 | try file.setEndPos(8192); | ||
| 138 | std.testing.expect((try file.getEndPos()) == 8192); | ||
| 139 | try file.setEndPos(4096); | ||
| 140 | std.testing.expect((try file.getEndPos()) == 4096); | ||
| 141 | try file.setEndPos(0); | ||
| 142 | std.testing.expect((try file.getEndPos()) == 0); | ||
| 143 | } | ||
| 144 | |||
| 128 | test "updateTimes" { | 145 | test "updateTimes" { |
| 129 | const tmp_file_name = "just_a_temporary_file.txt"; | 146 | const tmp_file_name = "just_a_temporary_file.txt"; |
| 130 | var file = try fs.cwd().createFile(tmp_file_name, .{ .read = true }); | 147 | var file = try fs.cwd().createFile(tmp_file_name, .{ .read = true }); |
lib/std/os.zig+33| ... | @@ -438,6 +438,39 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { | ... | @@ -438,6 +438,39 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { |
| 438 | return index; | 438 | return index; |
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | pub const TruncateError = error{ | ||
| 442 | /// The file descriptor is not open for writing. | ||
| 443 | NotFile, | ||
| 444 | } || UnexpectedError; | ||
| 445 | |||
| 446 | pub fn truncate(fd: fd_t, length: u64) TruncateError!void { | ||
| 447 | if (std.Target.current.os.tag == .windows) { | ||
| 448 | try windows.SetFilePointerEx_BEGIN(fd, length); | ||
| 449 | |||
| 450 | if (windows.kernel32.SetEndOfFile(fd) == 0) | ||
| 451 | return TruncateError.Unexpected; | ||
| 452 | |||
| 453 | return; | ||
| 454 | } | ||
| 455 | |||
| 456 | while (true) { | ||
| 457 | const rc = if (builtin.link_libc) blk: { | ||
| 458 | if (std.Target.current.os.tag == .linux) | ||
| 459 | break :blk system.ftruncate64(fd, @bitCast(off_t, length)) | ||
| 460 | else | ||
| 461 | break :blk system.ftruncate(fd, @bitCast(off_t, length)); | ||
| 462 | } else | ||
| 463 | system.ftruncate(fd, length); | ||
| 464 | |||
| 465 | switch (errno(rc)) { | ||
| 466 | 0 => return, | ||
| 467 | EINTR => continue, | ||
| 468 | EBADF, EINVAL => return error.NotFile, | ||
| 469 | else => |err| return unexpectedErrno(err), | ||
| 470 | } | ||
| 471 | } | ||
| 472 | } | ||
| 473 | |||
| 441 | /// Number of bytes read is returned. Upon reading end-of-file, zero is returned. | 474 | /// Number of bytes read is returned. Upon reading end-of-file, zero is returned. |
| 442 | /// | 475 | /// |
| 443 | /// Retries when interrupted by a signal. | 476 | /// Retries when interrupted by a signal. |
lib/std/os/linux.zig+27| ... | @@ -390,6 +390,33 @@ pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { | ... | @@ -390,6 +390,33 @@ pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { |
| 390 | return syscall3(SYS_write, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), count); | 390 | return syscall3(SYS_write, @bitCast(usize, @as(isize, fd)), @ptrToInt(buf), count); |
| 391 | } | 391 | } |
| 392 | 392 | ||
| 393 | pub fn ftruncate(fd: i32, length: u64) usize { | ||
| 394 | if (@hasDecl(@This(), "SYS_ftruncate64")) { | ||
| 395 | if (require_aligned_register_pair) { | ||
| 396 | return syscall4( | ||
| 397 | SYS_ftruncate64, | ||
| 398 | @bitCast(usize, @as(isize, fd)), | ||
| 399 | 0, | ||
| 400 | @truncate(usize, length), | ||
| 401 | @truncate(usize, length >> 32), | ||
| 402 | ); | ||
| 403 | } else { | ||
| 404 | return syscall3( | ||
| 405 | SYS_ftruncate64, | ||
| 406 | @bitCast(usize, @as(isize, fd)), | ||
| 407 | @truncate(usize, length), | ||
| 408 | @truncate(usize, length >> 32), | ||
| 409 | ); | ||
| 410 | } | ||
| 411 | } else { | ||
| 412 | return syscall2( | ||
| 413 | SYS_ftruncate, | ||
| 414 | @bitCast(usize, @as(isize, fd)), | ||
| 415 | @truncate(usize, length), | ||
| 416 | ); | ||
| 417 | } | ||
| 418 | } | ||
| 419 | |||
| 393 | pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize { | 420 | pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: usize) usize { |
| 394 | if (@hasDecl(@This(), "SYS_pwrite64")) { | 421 | if (@hasDecl(@This(), "SYS_pwrite64")) { |
| 395 | if (require_aligned_register_pair) { | 422 | if (require_aligned_register_pair) { |
lib/std/os/windows/kernel32.zig+1| ... | @@ -8,6 +8,7 @@ pub extern "kernel32" fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) c | ... | @@ -8,6 +8,7 @@ pub extern "kernel32" fn CancelIoEx(hFile: HANDLE, lpOverlapped: LPOVERLAPPED) c |
| 8 | pub extern "kernel32" fn CloseHandle(hObject: HANDLE) callconv(.Stdcall) BOOL; | 8 | pub extern "kernel32" fn CloseHandle(hObject: HANDLE) callconv(.Stdcall) BOOL; |
| 9 | 9 | ||
| 10 | pub extern "kernel32" fn CreateDirectoryW(lpPathName: [*:0]const u16, lpSecurityAttributes: ?*SECURITY_ATTRIBUTES) callconv(.Stdcall) BOOL; | 10 | pub extern "kernel32" fn CreateDirectoryW(lpPathName: [*:0]const u16, lpSecurityAttributes: ?*SECURITY_ATTRIBUTES) callconv(.Stdcall) BOOL; |
| 11 | pub extern "kernel32" fn SetEndOfFile(hFile: HANDLE) callconv(.Stdcall) BOOL; | ||
| 11 | 12 | ||
| 12 | pub extern "kernel32" fn CreateEventExW( | 13 | pub extern "kernel32" fn CreateEventExW( |
| 13 | lpEventAttributes: ?*SECURITY_ATTRIBUTES, | 14 | lpEventAttributes: ?*SECURITY_ATTRIBUTES, |