summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md4
-rw-r--r--nix-test/build.rs2
-rw-r--r--src/fcntl.rs40
-rw-r--r--src/sys/aio.rs42
-rw-r--r--test/sys/test_aio.rs24
-rw-r--r--test/test_fcntl.rs15
6 files changed, 123 insertions, 4 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d8be1905..664fdaff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Added socket option variant that enables the timestamp socket
control message: `nix::sys::socket::sockopt::ReceiveTimestamp`
([#663](https://github.com/nix-rust/nix/pull/663))
+- Added more accessor methods for `AioCb`
+ ([#773](https://github.com/nix-rust/nix/pull/773))
+- Add nix::sys::fallocate
+ ([#768](https:://github.com/nix-rust/nix/pull/768))
### Changed
- Renamed existing `ptrace` wrappers to encourage namespacing ([#692](https://github.com/nix-rust/nix/pull/692))
diff --git a/nix-test/build.rs b/nix-test/build.rs
index 0c18e1c8..5d1b1bba 100644
--- a/nix-test/build.rs
+++ b/nix-test/build.rs
@@ -13,7 +13,7 @@ pub fn main() {
"UNKNOWN"
};
- gcc::Config::new()
+ gcc::Build::new()
.file("src/const.c")
.file("src/sizes.c")
.define(os, None)
diff --git a/src/fcntl.rs b/src/fcntl.rs
index 003c316c..f99036d6 100644
--- a/src/fcntl.rs
+++ b/src/fcntl.rs
@@ -341,3 +341,43 @@ pub fn vmsplice(fd: RawFd, iov: &[IoVec<&[u8]>], flags: SpliceFFlags) -> Result<
Errno::result(ret).map(|r| r as usize)
}
+#[cfg(any(target_os = "linux"))]
+libc_bitflags!(
+ /// Mode argument flags for fallocate determining operation performed on a given range.
+ pub struct FallocateFlags: libc::c_int {
+ /// File size is not changed.
+ ///
+ /// offset + len can be greater than file size.
+ FALLOC_FL_KEEP_SIZE;
+ /// Deallocates space by creating a hole.
+ ///
+ /// Must be ORed with FALLOC_FL_KEEP_SIZE. Byte range starts at offset and continues for len bytes.
+ FALLOC_FL_PUNCH_HOLE;
+ /// Removes byte range from a file without leaving a hole.
+ ///
+ /// Byte range to collapse starts at offset and continues for len bytes.
+ FALLOC_FL_COLLAPSE_RANGE;
+ /// Zeroes space in specified byte range.
+ ///
+ /// Byte range starts at offset and continues for len bytes.
+ FALLOC_FL_ZERO_RANGE;
+ /// Increases file space by inserting a hole within the file size.
+ ///
+ /// Does not overwrite existing data. Hole starts at offset and continues for len bytes.
+ FALLOC_FL_INSERT_RANGE;
+ /// Shared file data extants are made private to the file.
+ ///
+ /// Gaurantees that a subsequent write will not fail due to lack of space.
+ FALLOC_FL_UNSHARE_RANGE;
+ }
+);
+
+/// Manipulates file space.
+///
+/// Allows the caller to directly manipulate the allocated disk space for the
+/// file referred to by fd.
+#[cfg(any(target_os = "linux"))]
+pub fn fallocate(fd: RawFd, mode: FallocateFlags, offset: libc::off_t, len: libc::off_t) -> Result<c_int> {
+ let res = unsafe { libc::fallocate(fd, mode.bits(), offset, len) };
+ Errno::result(res)
+}
diff --git a/src/sys/aio.rs b/src/sys/aio.rs
index 22bd3959..4be0da7b 100644
--- a/src/sys/aio.rs
+++ b/src/sys/aio.rs
@@ -84,6 +84,11 @@ pub struct AioCb<'a> {
}
impl<'a> AioCb<'a> {
+ /// Returns the underlying file descriptor associated with the `AioCb`
+ pub fn fd(&self) -> RawFd {
+ self.aiocb.aio_fildes
+ }
+
/// Constructs a new `AioCb` with no associated buffer.
///
/// The resulting `AioCb` structure is suitable for use with `AioCb::fsync`.
@@ -239,6 +244,38 @@ impl<'a> AioCb<'a> {
})
}
+ /// Returns the `aiocb`'s `LioOpcode` field
+ ///
+ /// If the value cannot be represented as an `LioOpcode`, returns `None`
+ /// instead.
+ pub fn lio_opcode(&self) -> Option<LioOpcode> {
+ match self.aiocb.aio_lio_opcode {
+ libc::LIO_READ => Some(LioOpcode::LIO_READ),
+ libc::LIO_WRITE => Some(LioOpcode::LIO_WRITE),
+ libc::LIO_NOP => Some(LioOpcode::LIO_NOP),
+ _ => None
+ }
+ }
+
+ /// Returns the requested length of the aio operation in bytes
+ ///
+ /// This method returns the *requested* length of the operation. To get the
+ /// number of bytes actually read or written by a completed operation, use
+ /// `aio_return` instead.
+ pub fn nbytes(&self) -> usize {
+ self.aiocb.aio_nbytes
+ }
+
+ /// Returns the file offset stored in the `AioCb`
+ pub fn offset(&self) -> off_t {
+ self.aiocb.aio_offset
+ }
+
+ /// Returns the priority of the `AioCb`
+ pub fn priority(&self) -> libc::c_int {
+ self.aiocb.aio_reqprio
+ }
+
/// Asynchronously reads from a file descriptor into a buffer
pub fn read(&mut self) -> Result<()> {
assert!(self.mutable, "Can't read into an immutable buffer");
@@ -250,6 +287,11 @@ impl<'a> AioCb<'a> {
})
}
+ /// Returns the `SigEvent` stored in the `AioCb`
+ pub fn sigevent(&self) -> SigEvent {
+ SigEvent::from(&self.aiocb.aio_sigevent)
+ }
+
/// Retrieve return status of an asynchronous operation. Should only be
/// called once for each `AioCb`, after `AioCb::error` indicates that it has
/// completed. The result is the same as for `read`, `write`, of `fsync`.
diff --git a/test/sys/test_aio.rs b/test/sys/test_aio.rs
index 67fd0850..630dff9a 100644
--- a/test/sys/test_aio.rs
+++ b/test/sys/test_aio.rs
@@ -13,7 +13,7 @@ use std::{thread, time};
use tempfile::tempfile;
// Helper that polls an AioCb for completion or error
-fn poll_aio(mut aiocb: &mut AioCb) -> Result<()> {
+fn poll_aio(aiocb: &mut AioCb) -> Result<()> {
loop {
let err = aiocb.error();
if err != Err(Error::from(Errno::EINPROGRESS)) { return err; };
@@ -21,6 +21,28 @@ fn poll_aio(mut aiocb: &mut AioCb) -> Result<()> {
}
}
+#[test]
+fn test_accessors() {
+ let mut rbuf = vec![0; 4];
+ let aiocb = AioCb::from_mut_slice( 1001,
+ 2, //offset
+ &mut rbuf,
+ 42, //priority
+ SigevNotify::SigevSignal {
+ signal: Signal::SIGUSR2,
+ si_value: 99
+ },
+ LioOpcode::LIO_NOP);
+ assert_eq!(1001, aiocb.fd());
+ assert_eq!(Some(LioOpcode::LIO_NOP), aiocb.lio_opcode());
+ assert_eq!(4, aiocb.nbytes());
+ assert_eq!(2, aiocb.offset());
+ assert_eq!(42, aiocb.priority());
+ let sev = aiocb.sigevent().sigevent();
+ assert_eq!(Signal::SIGUSR2 as i32, sev.sigev_signo);
+ assert_eq!(99, sev.sigev_value.sival_ptr as i64);
+}
+
// Tests AioCb.cancel. We aren't trying to test the OS's implementation, only our
// bindings. So it's sufficient to check that AioCb.cancel returned any
// AioCancelStat value.
diff --git a/test/test_fcntl.rs b/test/test_fcntl.rs
index 43bfc091..d171b91d 100644
--- a/test/test_fcntl.rs
+++ b/test/test_fcntl.rs
@@ -54,11 +54,11 @@ mod linux_android {
use libc::loff_t;
- use nix::fcntl::{SpliceFFlags, splice, tee, vmsplice};
+ use nix::fcntl::{SpliceFFlags, FallocateFlags, fallocate, splice, tee, vmsplice};
use nix::sys::uio::IoVec;
use nix::unistd::{close, pipe, read, write};
- use tempfile::tempfile;
+ use tempfile::{tempfile, NamedTempFile};
#[test]
fn test_splice() {
@@ -131,4 +131,15 @@ mod linux_android {
close(wr).unwrap();
}
+ #[test]
+ fn test_fallocate() {
+ let tmp = NamedTempFile::new().unwrap();
+
+ let fd = tmp.as_raw_fd();
+ fallocate(fd, FallocateFlags::empty(), 0, 100).unwrap();
+
+ // Check if we read exactly 100 bytes
+ let mut buf = [0u8; 200];
+ assert_eq!(100, read(fd, &mut buf).unwrap());
+ }
}