Skip to content

Commit

Permalink
Removed ffi from nix and into libc; Switched from CStr to OsStr; Mino…
Browse files Browse the repository at this point in the history
…r corrections on comments;
  • Loading branch information
vdagonneau committed Jan 26, 2019
1 parent d586d10 commit 2ec9c3d
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 91 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ exclude = [
]

[dependencies]
libc = { git = "https://github.com/rust-lang/libc" }
libc = { path = "../libc" }
bitflags = "1.0"
cfg-if = "0.1.0"
void = "1.0.2"
Expand Down
120 changes: 45 additions & 75 deletions src/sys/inotify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,89 +28,59 @@
//! ```

use libc::{
c_char,
c_int,
uint32_t
};
use std::ffi::{CString,CStr};
use std::ffi::{OsString,OsStr,CStr};
use std::os::unix::ffi::OsStrExt;
use std::mem::size_of;
use std::os::raw::c_char;
use std::os::unix::io::{RawFd,AsRawFd,FromRawFd};
use unistd::read;
use Result;
use NixPath;
use errno::Errno;

pub mod ffi {
use libc::{
c_char,
c_int,
uint32_t
};

extern {
pub fn inotify_init1(flags: c_int) -> c_int;
pub fn inotify_add_watch(fd: c_int,
path: *const c_char,
mask: uint32_t) -> c_int;
pub fn inotify_rm_watch(fd: c_int, wd: c_int) -> c_int;
}

#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct inotify_event {
pub wd: c_int,
pub mask: uint32_t,
pub cookie: uint32_t,
pub len: uint32_t
}
}

bitflags! {
libc_bitflags! {
/// Configuration options for [`inotify_add_watch`](fn.inotify_add_watch.html).
pub struct EventFlags: uint32_t {
const IN_ACCESS = 0x00000001;
const IN_MODIFY = 0x00000002;
const IN_ATTRIB = 0x00000004;
const IN_CLOSE_WRITE = 0x00000008;
const IN_CLOSE_NOWRITE = 0x00000010;
const IN_OPEN = 0x00000020;
const IN_MOVED_FROM = 0x00000040;
const IN_MOVED_TO = 0x00000080;
const IN_CREATE = 0x00000100;
const IN_DELETE = 0x00000200;
const IN_DELETE_SELF = 0x00000400;
const IN_MOVE_SELF = 0x00000800;

const IN_UNMOUNT = 0x00002000;
const IN_Q_OVERFLOW = 0x00004000;
const IN_IGNORED = 0x00008000;

const IN_ONLYDIR = 0x01000000;
const IN_DONT_FOLLOW = 0x02000000;
const IN_EXCL_UNLINK = 0x04000000;
const IN_MASK_ADD = 0x20000000;
const IN_ISDIR = 0x40000000;
const IN_ONESHOT = 0x80000000;

const IN_CLOSE = Self::IN_CLOSE_WRITE.bits |
Self::IN_CLOSE_NOWRITE.bits;
const IN_MOVE = Self::IN_MOVED_FROM.bits |
Self::IN_MOVED_TO.bits;
const IN_ALL_EVENTS =
Self::IN_ACCESS.bits | Self::IN_MODIFY.bits | Self::IN_ATTRIB.bits |
Self::IN_CLOSE_WRITE.bits | Self::IN_CLOSE_NOWRITE.bits |
Self::IN_OPEN.bits | Self::IN_MOVED_FROM.bits |
Self::IN_MOVED_TO.bits | Self::IN_DELETE.bits |
Self::IN_CREATE.bits | Self::IN_DELETE_SELF.bits |
Self::IN_MOVE_SELF.bits;
IN_ACCESS;
IN_MODIFY;
IN_ATTRIB;
IN_CLOSE_WRITE;
IN_CLOSE_NOWRITE;
IN_OPEN;
IN_MOVED_FROM;
IN_MOVED_TO;
IN_CREATE;
IN_DELETE;
IN_DELETE_SELF;
IN_MOVE_SELF;

IN_UNMOUNT;
IN_Q_OVERFLOW;
IN_IGNORED;

IN_CLOSE;
IN_MOVE;

IN_ONLYDIR;
IN_DONT_FOLLOW;
IN_EXCL_UNLINK;

IN_MASK_CREATE;
IN_MASK_ADD;
IN_ISDIR;
IN_ONESHOT;
IN_ALL_EVENTS;
}
}

bitflags! {
libc_bitflags! {
/// Configuration options for [`inotify_init1`](fn.inotify_init1.html).
pub struct InotifyInitFlags: c_int {
const IN_CLOEXEC = 0o02000000;
const IN_NONBLOCK = 0o00004000;
IN_CLOEXEC;
IN_NONBLOCK;
}
}

Expand Down Expand Up @@ -145,7 +115,7 @@ pub struct InotifyEvent {
pub cookie: u32,
/// Filename. This field exists only if the event was triggered for a file
/// inside the watched directory.
pub name: Option<CString>
pub name: Option<OsString>
}

impl Inotify {
Expand All @@ -156,7 +126,7 @@ impl Inotify {
/// For more information see, [inotify_init(2)](http://man7.org/linux/man-pages/man2/inotify_init.2.html).
pub fn init(flags: InotifyInitFlags) -> Result<Inotify> {
let res = Errno::result(unsafe {
ffi::inotify_init1(flags.bits())
libc::inotify_init1(flags.bits())
});

res.map(|fd| Inotify { fd })
Expand All @@ -173,7 +143,7 @@ impl Inotify {
{
let res = path.with_nix_path(|cstr| {
unsafe {
ffi::inotify_add_watch(self.fd, cstr.as_ptr(), mask.bits())
libc::inotify_add_watch(self.fd, cstr.as_ptr(), mask.bits())
}
})?;

Expand All @@ -187,7 +157,7 @@ impl Inotify {
///
/// For more information see, [inotify_rm_watch(2)](http://man7.org/linux/man-pages/man2/inotify_rm_watch.2.html).
pub fn rm_watch(&self, wd: WatchDescriptor) -> Result<()> {
let res = unsafe { ffi::inotify_rm_watch(self.fd, wd.wd) };
let res = unsafe { libc::inotify_rm_watch(self.fd, wd.wd) };

Errno::result(res).map(drop)
}
Expand All @@ -196,10 +166,10 @@ impl Inotify {
/// can either be blocking or non blocking depending on whether IN_NONBLOCK
/// was set at initialization.
///
/// Returns as many event as available. If the call was non blocking and no
/// event could be read then the EAGAIN error is returned.
/// Returns as many events as available. If the call was non blocking and no
/// events could be read then the EAGAIN error is returned.
pub fn read_events(&self) -> Result<Vec<InotifyEvent>> {
let header_size = size_of::<ffi::inotify_event>();
let header_size = size_of::<libc::inotify_event>();
let mut buffer = [0u8; 4096];
let mut events = Vec::new();
let mut offset = 0;
Expand All @@ -211,7 +181,7 @@ impl Inotify {
&*(
buffer
.as_ptr()
.offset(offset as isize) as *const ffi::inotify_event
.offset(offset as isize) as *const libc::inotify_event
)
};

Expand All @@ -226,7 +196,7 @@ impl Inotify {
};
let cstr = unsafe { CStr::from_ptr(ptr) };

Some(cstr.to_owned())
Some(OsStr::from_bytes(cstr.to_bytes()).to_owned())
}
};

Expand Down
29 changes: 14 additions & 15 deletions test/sys/test_inotify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use nix::sys::inotify::{EventFlags,InotifyInitFlags,Inotify};
use nix::Error;
use nix::errno::Errno;
use tempfile;
use std::ffi::CString;
use std::ffi::OsString;
use std::fs::{rename, File};

#[test]
Expand All @@ -11,16 +11,15 @@ pub fn test_inotify() {
.unwrap();
let tempdir = tempfile::tempdir().unwrap();

let wd = instance.add_watch(tempdir.path(), EventFlags::IN_ALL_EVENTS);
assert!(wd.is_ok());
instance.add_watch(tempdir.path(), EventFlags::IN_ALL_EVENTS).unwrap();

let event = instance.read_events();
assert_eq!(event.unwrap_err(), Error::Sys(Errno::EAGAIN));
let events = instance.read_events();
assert_eq!(events.unwrap_err(), Error::Sys(Errno::EAGAIN));

File::create(tempdir.path().join("test")).unwrap();

let events = instance.read_events().unwrap();
assert_eq!(events[0].name, Some(CString::new("test").unwrap()));
assert_eq!(events[0].name, Some(OsString::from("test")));
}

#[test]
Expand All @@ -29,11 +28,10 @@ pub fn test_inotify_multi_events() {
.unwrap();
let tempdir = tempfile::tempdir().unwrap();

let wd = instance.add_watch(tempdir.path(), EventFlags::IN_ALL_EVENTS);
assert!(wd.is_ok());
instance.add_watch(tempdir.path(), EventFlags::IN_ALL_EVENTS).unwrap();

let event = instance.read_events();
assert_eq!(event.unwrap_err(), Error::Sys(Errno::EAGAIN));
let events = instance.read_events();
assert_eq!(events.unwrap_err(), Error::Sys(Errno::EAGAIN));

File::create(tempdir.path().join("test")).unwrap();
rename(tempdir.path().join("test"), tempdir.path().join("test2")).unwrap();
Expand All @@ -49,19 +47,20 @@ pub fn test_inotify_multi_events() {
assert_eq!(events.len(), 5);

assert_eq!(events[0].mask, EventFlags::IN_CREATE);
assert_eq!(events[0].name, Some(CString::new("test").unwrap()));
assert_eq!(events[0].name, Some(OsString::from("test")));

assert_eq!(events[1].mask, EventFlags::IN_OPEN);
assert_eq!(events[1].name, Some(CString::new("test").unwrap()));
assert_eq!(events[1].name, Some(OsString::from("test")));

assert_eq!(events[2].mask, EventFlags::IN_CLOSE_WRITE);
assert_eq!(events[2].name, Some(CString::new("test").unwrap()));
assert_eq!(events[2].name, Some(OsString::from("test")));

assert_eq!(events[3].mask, EventFlags::IN_MOVED_FROM);
assert_eq!(events[3].name, Some(CString::new("test").unwrap()));
assert_eq!(events[3].name, Some(OsString::from("test")));

assert_eq!(events[4].mask, EventFlags::IN_MOVED_TO);
assert_eq!(events[4].name, Some(CString::new("test2").unwrap()));
assert_eq!(events[4].name, Some(OsString::from("test2")));

assert_eq!(events[3].cookie, events[4].cookie);
}

0 comments on commit 2ec9c3d

Please sign in to comment.