extern crate blkid_sys;
extern crate errno;
extern crate libc;
use std::error::Error as err;
use std::ffi::{CStr, CString, IntoStringError, NulError};
use std::fmt;
use std::io::Error;
use std::path::Path;
use std::ptr;
use std::string::FromUtf8Error;
use blkid_sys::*;
use errno::errno;
#[derive(Debug)]
pub enum BlkidError {
FromUtf8Error(FromUtf8Error),
NulError(NulError),
Error(String),
IoError(Error),
IntoStringError(IntoStringError),
}
impl fmt::Display for BlkidError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.description())
}
}
impl err for BlkidError {
fn description(&self) -> &str {
match *self {
BlkidError::FromUtf8Error(ref e) => e.description(),
BlkidError::NulError(ref e) => e.description(),
BlkidError::Error(ref e) => &e,
BlkidError::IoError(ref e) => e.description(),
BlkidError::IntoStringError(ref e) => e.description(),
}
}
fn cause(&self) -> Option<&err> {
match *self {
BlkidError::FromUtf8Error(ref e) => e.cause(),
BlkidError::NulError(ref e) => e.cause(),
BlkidError::Error(_) => None,
BlkidError::IoError(ref e) => e.cause(),
BlkidError::IntoStringError(ref e) => e.cause(),
}
}
}
impl BlkidError {
fn new(err: String) -> BlkidError {
BlkidError::Error(err)
}
pub fn to_string(&self) -> String {
match *self {
BlkidError::FromUtf8Error(ref err) => err.utf8_error().to_string(),
BlkidError::NulError(ref err) => err.description().to_string(),
BlkidError::Error(ref err) => err.to_string(),
BlkidError::IoError(ref err) => err.description().to_string(),
BlkidError::IntoStringError(ref err) => err.description().to_string(),
}
}
}
impl From<NulError> for BlkidError {
fn from(err: NulError) -> BlkidError {
BlkidError::NulError(err)
}
}
impl From<FromUtf8Error> for BlkidError {
fn from(err: FromUtf8Error) -> BlkidError {
BlkidError::FromUtf8Error(err)
}
}
impl From<IntoStringError> for BlkidError {
fn from(err: IntoStringError) -> BlkidError {
BlkidError::IntoStringError(err)
}
}
impl From<Error> for BlkidError {
fn from(err: Error) -> BlkidError {
BlkidError::IoError(err)
}
}
fn get_error() -> String {
let error = errno();
format!("{}", error)
}
pub struct BlkId {
probe: blkid_probe,
}
impl BlkId {
pub fn new(file: &Path) -> Result<BlkId, BlkidError> {
let path = try!(CString::new(file.as_os_str().to_string_lossy().as_ref()));
unsafe {
let probe = blkid_new_probe_from_filename(path.as_ptr());
Ok(BlkId { probe: probe })
}
}
pub fn do_probe(&self) -> Result<(), BlkidError> {
unsafe {
let ret_code = blkid_do_probe(self.probe);
if ret_code < 0 {
return Err(BlkidError::new(get_error()));
}
}
Ok(())
}
pub fn lookup_value(&self, name: &str) -> Result<String, BlkidError> {
let name = try!(CString::new(name));
let mut data_ptr: *const ::libc::c_char = ptr::null();
let mut len = 0;
unsafe {
let ret_code =
blkid_probe_lookup_value(self.probe, name.as_ptr(), &mut data_ptr, &mut len);
if ret_code < 0 {
return Err(BlkidError::new(get_error()));
}
let data_value = CStr::from_ptr(data_ptr as *const ::libc::c_char);
Ok(data_value.to_string_lossy().into_owned())
}
}
pub fn has_value(&self, name: &str) -> Result<bool, BlkidError> {
let name = try!(CString::new(name));
unsafe {
let ret_code = blkid_probe_has_value(self.probe, name.as_ptr());
if ret_code < 0 {
return Err(BlkidError::new(get_error()));
}
match ret_code {
0 => Ok(false),
1 => Ok(true),
_ => {
Err(BlkidError::new(format!("Unknown return code from \
blkid_probe_has_value: {}",
ret_code)))
}
}
}
}
pub fn numof_values(&self) -> Result<i32, BlkidError> {
unsafe {
let ret_code = blkid_probe_numof_values(self.probe);
if ret_code < 0 {
return Err(BlkidError::new(get_error()));
}
Ok(ret_code)
}
}
pub fn get_devno(&self) -> u64 {
unsafe { blkid_probe_get_devno(self.probe) }
}
pub fn get_wholedisk_devno(&self) -> u64 {
unsafe { blkid_probe_get_wholedisk_devno(self.probe) }
}
pub fn is_wholedisk(&self) -> Result<bool, BlkidError> {
unsafe {
let ret_code = blkid_probe_is_wholedisk(self.probe);
match ret_code {
0 => Ok(false),
1 => Ok(true),
_ => {
Err(BlkidError::new(format!("Unknown return code from \
blkid_probe_has_value: {}",
ret_code)))
}
}
}
}
pub fn get_size(&self) -> Result<i64, BlkidError> {
unsafe {
let ret_code = blkid_probe_get_size(self.probe);
if ret_code < 0 {
return Err(BlkidError::new(get_error()));
}
Ok(ret_code)
}
}
pub fn get_offset(&self) -> Result<i64, BlkidError> {
unsafe {
let ret_code = blkid_probe_get_offset(self.probe);
if ret_code < 0 {
return Err(BlkidError::new(get_error()));
}
Ok(ret_code)
}
}
pub fn get_sectorsize(&self) -> u32 {
unsafe { blkid_probe_get_sectorsize(self.probe) }
}
pub fn get_sectors(&self) -> Result<i64, BlkidError> {
unsafe {
let ret_code = blkid_probe_get_sectors(self.probe);
if ret_code < 0 {
return Err(BlkidError::new(get_error()));
}
Ok(ret_code)
}
}
pub fn get_fd(&self) -> Result<i32, BlkidError> {
unsafe { Ok(blkid_probe_get_fd(self.probe)) }
}
pub fn known_fstype(&self, fstype: &str) -> Result<bool, BlkidError> {
let fstype = try!(CString::new(fstype));
unsafe {
let ret_code = blkid_known_fstype(fstype.as_ptr());
match ret_code {
0 => Ok(false),
1 => Ok(true),
_ => {
Err(BlkidError::new(format!("Unknown return code from blkid_known_fstype: {}",
ret_code)))
}
}
}
}
pub fn enable_topology(&self) -> Result<(), BlkidError> {
unsafe {
let ret_code = blkid_probe_enable_topology(self.probe, 1);
if ret_code < 0 {
return Err(BlkidError::new(get_error()));
}
}
Ok(())
}
pub fn get_topology(&self) -> Result<blkid_topology, BlkidError> {
unsafe { Ok(blkid_probe_get_topology(self.probe)) }
}
pub fn get_topology_alignment_offset(tp: blkid_topology) -> u64 {
unsafe { blkid_topology_get_alignment_offset(tp) }
}
pub fn get_topology_minimum_io_size(tp: blkid_topology) -> u64 {
unsafe { blkid_topology_get_minimum_io_size(tp) }
}
pub fn get_topology_optimal_io_size(tp: blkid_topology) -> u64 {
unsafe { blkid_topology_get_optimal_io_size(tp) }
}
pub fn get_topology_logical_sector_size(tp: blkid_topology) -> u64 {
unsafe { blkid_topology_get_logical_sector_size(tp) }
}
pub fn get_topology_physical_sector_size(tp: blkid_topology) -> u64 {
unsafe { blkid_topology_get_physical_sector_size(tp) }
}
}
impl Drop for BlkId {
fn drop(&mut self) {
if self.probe.is_null() {
return;
}
unsafe {
blkid_free_probe(self.probe);
}
}
}