1use std::ffi::CString;
2use std::ffi::OsStr;
3use std::io;
4use std::os::unix::ffi::OsStrExt;
5use std::path::Path;
6use std::ptr;
7
8use libc::{ssize_t, ERANGE};
9
10// Need to use this one as libc only defines this on supported platforms. Given
11// that we want to at least compile on unsupported platforms, we define this in
12// our platform-specific modules.
13use sys::ENOATTR;
14
15#[allow(dead_code)]
16pub fn name_to_c(name: &OsStr) -> io::Result<CString> {
17 match CString::new(name.as_bytes()) {
18 Ok(name: CString) => Ok(name),
19 Err(_) => Err(io::Error::new(
20 kind:io::ErrorKind::InvalidInput,
21 error:"name must not contain null bytes",
22 )),
23 }
24}
25
26pub fn path_to_c(path: &Path) -> io::Result<CString> {
27 match CString::new(path.as_os_str().as_bytes()) {
28 Ok(name: CString) => Ok(name),
29 Err(_) => Err(io::Error::new(kind:io::ErrorKind::NotFound, error:"file not found")),
30 }
31}
32
33pub fn extract_noattr(result: io::Result<Vec<u8>>) -> io::Result<Option<Vec<u8>>> {
34 result.map(Some).or_else(|e: Error| match e.raw_os_error() {
35 Some(ENOATTR) => Ok(None),
36 _ => Err(e),
37 })
38}
39
40pub unsafe fn allocate_loop<F: FnMut(*mut u8, usize) -> ssize_t>(mut f: F) -> io::Result<Vec<u8>> {
41 let mut vec: Vec<u8> = Vec::new();
42 loop {
43 let ret = (f)(ptr::null_mut(), 0);
44 if ret < 0 {
45 return Err(io::Error::last_os_error());
46 } else if ret == 0 {
47 break;
48 }
49 vec.reserve_exact(ret as usize);
50
51 let ret = (f)(vec.as_mut_ptr(), vec.capacity());
52 if ret >= 0 {
53 vec.set_len(ret as usize);
54 break;
55 } else {
56 let error = io::Error::last_os_error();
57 if error.raw_os_error() == Some(ERANGE) {
58 continue;
59 }
60 return Err(error);
61 }
62 }
63 vec.shrink_to_fit();
64 Ok(vec)
65}
66