Skip to content

Commit

Permalink
Add AsyncFd::truncate
Browse files Browse the repository at this point in the history
Calls ftruncate(2), truncating a file to a specified length.
  • Loading branch information
Thomasdezeeuw committed Jul 20, 2024
1 parent 7eed39f commit 9792bbf
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 1 deletion.
31 changes: 31 additions & 0 deletions src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,21 @@ impl<D: Descriptor> AsyncFd<D> {
) -> Allocate<'fd, D> {
Allocate::new(self, (offset, length, mode))
}


/// Truncate the file to `length`.
///
/// If the file previously was larger than this size, the extra data is
/// lost. If the file previously was shorter, it is extended, and the
/// extended part reads as null bytes.
#[doc = man_link!(ftruncate(2))]
#[doc(alias = "ftruncate")]
pub const fn truncate<'fd>(
&'fd self,
length: u64,
) -> Truncate<'fd, D> {
Truncate::new(self, length)
}
}

// SyncData.
Expand Down Expand Up @@ -430,6 +445,22 @@ op_future! {
},
}

// Truncate.
op_future! {
fn AsyncFd::truncate -> (),
struct Truncate<'fd> {
// Doesn't need any fields.
},
setup_state: flags: u64,
setup: |submission, fd, (), length| unsafe {
submission.ftruncate(fd.fd(), length);
},
map_result: |this, (), res| {
debug_assert!(res == 0);
Ok(())
},
}

/// Metadata information about a file.
///
/// See [`AsyncFd::metadata`] and [`Stat`].
Expand Down
6 changes: 6 additions & 0 deletions src/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,12 @@ impl Submission {
};
}

pub(crate) unsafe fn ftruncate(&mut self, fd: RawFd, offset: u64) {
self.inner.opcode = libc::IORING_OP_FTRUNCATE as u8;
self.inner.fd = fd;
self.inner.__bindgen_anon_1 = libc::io_uring_sqe__bindgen_ty_1 { off: offset };
}

pub(crate) unsafe fn wake(&mut self, ring_fd: RawFd) {
self.msg(ring_fd, u64::MAX, 0, 0);
self.no_completion_event();
Expand Down
37 changes: 36 additions & 1 deletion tests/async_fd/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
use std::{panic, str};

use a10::fd::File;
use a10::fs::{self, Advise, Allocate, CreateDir, Delete, Open, OpenOptions, Rename};
use a10::fs::{self, Advise, Allocate, CreateDir, Delete, Open, OpenOptions, Rename, Truncate};
use a10::io::{Read, ReadVectored, Write, WriteVectored};
use a10::{Extract, SubmissionQueue};

Expand Down Expand Up @@ -521,6 +521,41 @@ fn fadvise() {
assert!(buf == test_file.content, "read content is different");
}

#[test]
fn ftruncate() {
let sq = test_queue();
let waker = Waker::new();

is_send::<Truncate>();
is_sync::<Truncate>();

let mut path = temp_dir();
path.push("ftruncate");
let _d = defer(|| remove_test_file(&path));

let open_file: Open<File> = OpenOptions::new()
.write()
.create()
.truncate()
.open(sq, path.clone());
let file = waker.block_on(open_file).unwrap();

waker.block_on(file.write_all(LOREM_IPSUM_50.content)).unwrap();

let metadata = waker.block_on(file.metadata()).unwrap();
assert_eq!(metadata.len(), LOREM_IPSUM_50.content.len() as u64);

const SIZE: u64 = 4096;

waker
.block_on(file.truncate(SIZE))
.expect("failed fallocate");

let metadata = waker.block_on(file.metadata()).unwrap();
assert_eq!(metadata.len(), SIZE);
}


#[test]
fn fallocate() {
let sq = test_queue();
Expand Down

0 comments on commit 9792bbf

Please sign in to comment.