xattr 0.1.4

unix extended filesystem attributes
Documentation
use std::ffi::OsStr;
use std::os::unix::ffi::OsStrExt;
use std::io;
use std::ptr;
use std::ffi::CString;
use std::path::Path;

use ::libc::{ERANGE, ssize_t};

pub fn name_to_c(name: &OsStr) -> io::Result<CString> {
    match CString::new(name.as_bytes()) {
        Ok(name) => Ok(name),
        Err(_) => Err(io::Error::new(io::ErrorKind::InvalidInput, "name must not contain null bytes"))
    }
}

pub fn path_to_c(path: &Path) -> io::Result<CString> {
    match CString::new(path.as_os_str().as_bytes()) {
        Ok(name) => Ok(name),
        Err(_) => Err(io::Error::new(io::ErrorKind::NotFound , "file not found"))
    }
}


pub unsafe fn allocate_loop<F: FnMut(*mut u8, usize) -> ssize_t>(mut f: F) -> io::Result<Vec<u8>> {
    let mut vec: Vec<u8> = Vec::new();
    loop {
        let ret = (f)(ptr::null_mut(), 0);
        if ret < 0 {
            return Err(io::Error::last_os_error());
        } else if ret == 0 {
            break;
        }
        vec.reserve_exact(ret as usize);

        let ret = (f)(vec.as_mut_ptr(), vec.capacity());
        if ret >= 0 {
            vec.set_len(ret as usize);
            break;
        } else {
            let error = io::Error::last_os_error();
            if error.raw_os_error() == Some(ERANGE) {
                continue;
            }
            return Err(error);
        }
    }
    vec.shrink_to_fit();
    Ok(vec)

}