Skip to content

Commit 1da348c

Browse files
committed
NixPath -> NixString and Error -> Errno
1 parent 745c791 commit 1da348c

25 files changed

+335
-428
lines changed

src/cstr.rs

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
use std::ffi::{OsStr, OsString, CString, NulError};
2+
use std::path::{Path, PathBuf};
3+
use std::os::unix::ffi::{OsStrExt, OsStringExt};
4+
5+
pub trait ToCString {
6+
fn to_cstring(&self) -> Result<CString, NulError>;
7+
fn into_cstring(self) -> Result<CString, NulError> where Self: Sized { unimplemented!() }
8+
}
9+
10+
impl ToCString for [u8] {
11+
fn to_cstring(&self) -> Result<CString, NulError> {
12+
CString::new(self)
13+
}
14+
}
15+
16+
impl ToCString for Vec<u8> {
17+
fn to_cstring(&self) -> Result<CString, NulError> {
18+
ToCString::to_cstring(&**self)
19+
}
20+
21+
fn into_cstring(self) -> Result<CString, NulError> {
22+
CString::new(self)
23+
}
24+
}
25+
26+
impl ToCString for str {
27+
fn to_cstring(&self) -> Result<CString, NulError> {
28+
CString::new(self.as_bytes())
29+
}
30+
}
31+
32+
impl ToCString for String {
33+
fn to_cstring(&self) -> Result<CString, NulError> {
34+
ToCString::to_cstring(&**self)
35+
}
36+
37+
fn into_cstring(self) -> Result<CString, NulError> {
38+
CString::new(self.into_bytes())
39+
}
40+
}
41+
42+
impl ToCString for OsStr {
43+
fn to_cstring(&self) -> Result<CString, NulError> {
44+
CString::new(self.as_bytes())
45+
}
46+
}
47+
48+
impl ToCString for OsString {
49+
fn to_cstring(&self) -> Result<CString, NulError> {
50+
ToCString::to_cstring(&**self)
51+
}
52+
53+
fn into_cstring(self) -> Result<CString, NulError> {
54+
CString::new(self.into_vec())
55+
}
56+
}
57+
58+
impl ToCString for Path {
59+
fn to_cstring(&self) -> Result<CString, NulError> {
60+
ToCString::to_cstring(self.as_os_str())
61+
}
62+
}
63+
64+
impl ToCString for PathBuf {
65+
fn to_cstring(&self) -> Result<CString, NulError> {
66+
ToCString::to_cstring(self.as_os_str())
67+
}
68+
69+
fn into_cstring(self) -> Result<CString, NulError> {
70+
ToCString::into_cstring(self.into_os_string())
71+
}
72+
}
73+
74+
// TODO: allow this in consts/statics
75+
#[macro_export]
76+
macro_rules! cstr {
77+
($s:expr) => {
78+
unsafe { ::std::ffi::CStr::from_ptr(concat!($s, "\0").as_ptr() as *const _) }
79+
}
80+
}

src/errno.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use libc::c_int;
2-
use std::{fmt, io, error};
3-
use {Error, Result};
2+
use std::{fmt, io, error, result};
43

54
pub use self::consts::*;
65
pub use self::consts::Errno::*;
@@ -74,7 +73,7 @@ impl Errno {
7473
/// should not be used when `-1` is not the errno sentinel value.
7574
pub fn result<S: ErrnoSentinel + PartialEq<S>>(value: S) -> Result<S> {
7675
if value == S::sentinel() {
77-
Err(Error::Sys(Self::last()))
76+
Err(Self::last())
7877
} else {
7978
Ok(value)
8079
}
@@ -117,6 +116,8 @@ impl From<Errno> for io::Error {
117116
}
118117
}
119118

119+
pub type Result<T> = result::Result<T, Errno>;
120+
120121
fn last() -> Errno {
121122
Errno::from_i32(errno())
122123
}

src/fcntl.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use {Errno, Result, NixPath};
1+
use {Errno, Result, NixString};
22
use libc::{c_int, c_uint};
33
use sys::stat::Mode;
44
use std::os::unix::io::RawFd;
@@ -96,10 +96,10 @@ mod ffi {
9696
}
9797
}
9898

99-
pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
100-
let fd = try!(path.with_nix_path(|cstr| {
101-
unsafe { ffi::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
102-
}));
99+
pub fn open<P: NixString>(path: P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
100+
let fd = unsafe {
101+
ffi::open(path.as_ref().as_ptr(), oflag.bits(), mode.bits() as c_uint)
102+
};
103103

104104
Errno::result(fd)
105105
}

src/lib.rs

+7-184
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@ extern crate nix_test as nixtest;
2020

2121
// Re-exports
2222
pub use libc::{c_int, c_void};
23-
pub use errno::Errno;
23+
pub use errno::{Errno, Result};
24+
pub use nix_string::NixString;
25+
26+
mod nix_string;
27+
28+
#[macro_use]
29+
pub mod cstr;
2430

2531
pub mod errno;
2632
pub mod features;
@@ -42,186 +48,3 @@ pub mod sched;
4248

4349
pub mod sys;
4450
pub mod unistd;
45-
46-
/*
47-
*
48-
* ===== Result / Error =====
49-
*
50-
*/
51-
52-
use libc::c_char;
53-
use std::{ptr, result};
54-
use std::ffi::{CStr, OsStr};
55-
use std::path::{Path, PathBuf};
56-
use std::os::unix::ffi::OsStrExt;
57-
use std::io;
58-
use std::fmt;
59-
use std::error;
60-
use libc::PATH_MAX;
61-
62-
pub type Result<T> = result::Result<T, Error>;
63-
64-
#[derive(Clone, Copy, Debug, PartialEq)]
65-
pub enum Error {
66-
Sys(errno::Errno),
67-
InvalidPath,
68-
}
69-
70-
impl Error {
71-
pub fn from_errno(errno: errno::Errno) -> Error {
72-
Error::Sys(errno)
73-
}
74-
75-
pub fn last() -> Error {
76-
Error::Sys(errno::Errno::last())
77-
}
78-
79-
pub fn invalid_argument() -> Error {
80-
Error::Sys(errno::EINVAL)
81-
}
82-
83-
pub fn errno(&self) -> errno::Errno {
84-
match *self {
85-
Error::Sys(errno) => errno,
86-
Error::InvalidPath => errno::Errno::EINVAL,
87-
}
88-
}
89-
}
90-
91-
impl From<errno::Errno> for Error {
92-
fn from(errno: errno::Errno) -> Error { Error::from_errno(errno) }
93-
}
94-
95-
impl error::Error for Error {
96-
fn description(&self) -> &str {
97-
match self {
98-
&Error::InvalidPath => "Invalid path",
99-
&Error::Sys(ref errno) => errno.desc(),
100-
}
101-
}
102-
}
103-
104-
impl fmt::Display for Error {
105-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106-
match self {
107-
&Error::InvalidPath => write!(f, "Invalid path"),
108-
&Error::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()),
109-
}
110-
}
111-
}
112-
113-
impl From<Error> for io::Error {
114-
fn from(err: Error) -> Self {
115-
match err {
116-
Error::InvalidPath => io::Error::new(io::ErrorKind::InvalidInput, err),
117-
Error::Sys(errno) => io::Error::from_raw_os_error(errno as i32),
118-
}
119-
}
120-
}
121-
122-
pub trait NixPath {
123-
fn len(&self) -> usize;
124-
125-
fn with_nix_path<T, F>(&self, f: F) -> Result<T>
126-
where F: FnOnce(&CStr) -> T;
127-
}
128-
129-
impl NixPath for str {
130-
fn len(&self) -> usize {
131-
NixPath::len(OsStr::new(self))
132-
}
133-
134-
fn with_nix_path<T, F>(&self, f: F) -> Result<T>
135-
where F: FnOnce(&CStr) -> T {
136-
OsStr::new(self).with_nix_path(f)
137-
}
138-
}
139-
140-
impl NixPath for OsStr {
141-
fn len(&self) -> usize {
142-
self.as_bytes().len()
143-
}
144-
145-
fn with_nix_path<T, F>(&self, f: F) -> Result<T>
146-
where F: FnOnce(&CStr) -> T {
147-
self.as_bytes().with_nix_path(f)
148-
}
149-
}
150-
151-
impl NixPath for CStr {
152-
fn len(&self) -> usize {
153-
self.to_bytes().len()
154-
}
155-
156-
fn with_nix_path<T, F>(&self, f: F) -> Result<T>
157-
where F: FnOnce(&CStr) -> T {
158-
// Equivalence with the [u8] impl.
159-
if self.len() >= PATH_MAX as usize {
160-
return Err(Error::InvalidPath);
161-
}
162-
163-
Ok(f(self))
164-
}
165-
}
166-
167-
impl NixPath for [u8] {
168-
fn len(&self) -> usize {
169-
self.len()
170-
}
171-
172-
fn with_nix_path<T, F>(&self, f: F) -> Result<T>
173-
where F: FnOnce(&CStr) -> T {
174-
let mut buf = [0u8; PATH_MAX as usize];
175-
176-
if self.len() >= PATH_MAX as usize {
177-
return Err(Error::InvalidPath);
178-
}
179-
180-
match self.iter().position(|b| *b == 0) {
181-
Some(_) => Err(Error::InvalidPath),
182-
None => {
183-
unsafe {
184-
// TODO: Replace with bytes::copy_memory. rust-lang/rust#24028
185-
ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len());
186-
Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char)))
187-
}
188-
189-
}
190-
}
191-
}
192-
}
193-
194-
impl NixPath for Path {
195-
fn len(&self) -> usize {
196-
NixPath::len(self.as_os_str())
197-
}
198-
199-
fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
200-
self.as_os_str().with_nix_path(f)
201-
}
202-
}
203-
204-
impl NixPath for PathBuf {
205-
fn len(&self) -> usize {
206-
NixPath::len(self.as_os_str())
207-
}
208-
209-
fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
210-
self.as_os_str().with_nix_path(f)
211-
}
212-
}
213-
214-
/// Treats `None` as an empty string.
215-
impl<'a, NP: ?Sized + NixPath> NixPath for Option<&'a NP> {
216-
fn len(&self) -> usize {
217-
self.map_or(0, NixPath::len)
218-
}
219-
220-
fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
221-
if let Some(nix_path) = *self {
222-
nix_path.with_nix_path(f)
223-
} else {
224-
unsafe { CStr::from_ptr("\0".as_ptr() as *const _).with_nix_path(f) }
225-
}
226-
}
227-
}

0 commit comments

Comments
 (0)