Skip to content

Commit

Permalink
Merge branch 'master' into mkfifo
Browse files Browse the repository at this point in the history
  • Loading branch information
jpastuszek committed Oct 9, 2017
2 parents f0a9c9b + 5851bd0 commit 39cb5e6
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#663](https://github.com/nix-rust/nix/pull/663))
- Added `nix::unistd::mkfifo`.
([#602](https://github.com/nix-rust/nix/pull/774))
- 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))
Expand Down
2 changes: 1 addition & 1 deletion nix-test/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
40 changes: 40 additions & 0 deletions src/fcntl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
42 changes: 42 additions & 0 deletions src/sys/aio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down Expand Up @@ -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");
Expand All @@ -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`.
Expand Down
24 changes: 23 additions & 1 deletion test/sys/test_aio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,36 @@ 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; };
thread::sleep(time::Duration::from_millis(10));
}
}

#[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.
Expand Down
15 changes: 13 additions & 2 deletions test/test_fcntl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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());
}
}

0 comments on commit 39cb5e6

Please sign in to comment.