use std::ffi::CString;
use std::{mem, str};
use crate::connect::Connect;
use crate::error::Error;
use crate::storage_pool::StoragePool;
use crate::stream::Stream;
#[derive(Clone, Debug)]
pub struct StorageVolInfo {
pub kind: u32,
pub capacity: u64,
pub allocation: u64,
}
impl StorageVolInfo {
pub unsafe fn from_ptr(ptr: sys::virStorageVolInfoPtr) -> StorageVolInfo {
StorageVolInfo {
kind: (*ptr).type_ as sys::virStorageVolType,
capacity: (*ptr).capacity,
allocation: (*ptr).allocation,
}
}
}
#[derive(Debug)]
pub struct StorageVol {
ptr: Option<sys::virStorageVolPtr>,
}
impl Drop for StorageVol {
fn drop(&mut self) {
if self.ptr.is_some() {
if let Err(e) = self.free() {
panic!("Unable to drop memory for StorageVol: {}", e)
}
}
}
}
impl StorageVol {
pub fn new(ptr: sys::virStorageVolPtr) -> StorageVol {
StorageVol { ptr: Some(ptr) }
}
pub fn as_ptr(&self) -> sys::virStorageVolPtr {
self.ptr.unwrap()
}
pub fn get_connect(&self) -> Result<Connect, Error> {
unsafe {
let ptr = sys::virStorageVolGetConnect(self.as_ptr());
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(Connect::new(ptr))
}
}
pub fn create_xml(
pool: &StoragePool,
xml: &str,
flags: sys::virStorageVolCreateFlags,
) -> Result<StorageVol, Error> {
unsafe {
let xml_buf = CString::new(xml).unwrap();
let ptr =
sys::virStorageVolCreateXML(pool.as_ptr(), xml_buf.as_ptr(), flags as libc::c_uint);
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(StorageVol::new(ptr))
}
}
pub fn create_xml_from(
pool: &StoragePool,
xml: &str,
vol: &StorageVol,
flags: sys::virStorageVolCreateFlags,
) -> Result<StorageVol, Error> {
unsafe {
let xml_buf = CString::new(xml).unwrap();
let ptr = sys::virStorageVolCreateXMLFrom(
pool.as_ptr(),
xml_buf.as_ptr(),
vol.as_ptr(),
flags as libc::c_uint,
);
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(StorageVol::new(ptr))
}
}
pub fn lookup_by_name(pool: &StoragePool, name: &str) -> Result<StorageVol, Error> {
unsafe {
let name_buf = CString::new(name).unwrap();
let ptr = sys::virStorageVolLookupByName(pool.as_ptr(), name_buf.as_ptr());
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(StorageVol::new(ptr))
}
}
pub fn lookup_by_key(conn: &Connect, key: &str) -> Result<StorageVol, Error> {
unsafe {
let key_buf = CString::new(key).unwrap();
let ptr = sys::virStorageVolLookupByKey(conn.as_ptr(), key_buf.as_ptr());
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(StorageVol::new(ptr))
}
}
pub fn lookup_by_path(conn: &Connect, path: &str) -> Result<StorageVol, Error> {
unsafe {
let path_buf = CString::new(path).unwrap();
let ptr = sys::virStorageVolLookupByPath(conn.as_ptr(), path_buf.as_ptr());
if ptr.is_null() {
return Err(Error::last_error());
}
Ok(StorageVol::new(ptr))
}
}
pub fn get_name(&self) -> Result<String, Error> {
unsafe {
let n = sys::virStorageVolGetName(self.as_ptr());
if n.is_null() {
return Err(Error::last_error());
}
Ok(c_chars_to_string!(n, nofree))
}
}
pub fn get_key(&self) -> Result<String, Error> {
unsafe {
let n = sys::virStorageVolGetKey(self.as_ptr());
if n.is_null() {
return Err(Error::last_error());
}
Ok(c_chars_to_string!(n, nofree))
}
}
pub fn get_path(&self) -> Result<String, Error> {
unsafe {
let n = sys::virStorageVolGetPath(self.as_ptr());
if n.is_null() {
return Err(Error::last_error());
}
Ok(c_chars_to_string!(n))
}
}
pub fn get_xml_desc(&self, flags: u32) -> Result<String, Error> {
unsafe {
let xml = sys::virStorageVolGetXMLDesc(self.as_ptr(), flags);
if xml.is_null() {
return Err(Error::last_error());
}
Ok(c_chars_to_string!(xml))
}
}
pub fn delete(&self, flags: u32) -> Result<(), Error> {
unsafe {
if sys::virStorageVolDelete(self.as_ptr(), flags as libc::c_uint) == -1 {
return Err(Error::last_error());
}
Ok(())
}
}
pub fn wipe(&self, flags: u32) -> Result<(), Error> {
unsafe {
if sys::virStorageVolWipe(self.as_ptr(), flags as libc::c_uint) == -1 {
return Err(Error::last_error());
}
Ok(())
}
}
pub fn wipe_pattern(
&self,
algo: sys::virStorageVolWipeAlgorithm,
flags: u32,
) -> Result<(), Error> {
unsafe {
if sys::virStorageVolWipePattern(
self.as_ptr(),
algo as libc::c_uint,
flags as libc::c_uint,
) == -1
{
return Err(Error::last_error());
}
Ok(())
}
}
pub fn free(&mut self) -> Result<(), Error> {
unsafe {
if sys::virStorageVolFree(self.as_ptr()) == -1 {
return Err(Error::last_error());
}
self.ptr = None;
Ok(())
}
}
pub fn resize(&self, capacity: u64, flags: u32) -> Result<u32, Error> {
unsafe {
let ret = sys::virStorageVolResize(
self.as_ptr(),
capacity as libc::c_ulonglong,
flags as libc::c_uint,
);
if ret == -1 {
return Err(Error::last_error());
}
Ok(ret as u32)
}
}
pub fn get_info(&self) -> Result<StorageVolInfo, Error> {
unsafe {
let mut pinfo = mem::MaybeUninit::uninit();
let res = sys::virStorageVolGetInfo(self.as_ptr(), pinfo.as_mut_ptr());
if res == -1 {
return Err(Error::last_error());
}
Ok(StorageVolInfo::from_ptr(&mut pinfo.assume_init()))
}
}
pub fn get_info_flags(&self, flags: u32) -> Result<StorageVolInfo, Error> {
unsafe {
let mut pinfo = mem::MaybeUninit::uninit();
let res = sys::virStorageVolGetInfoFlags(
self.as_ptr(),
pinfo.as_mut_ptr(),
flags as libc::c_uint,
);
if res == -1 {
return Err(Error::last_error());
}
Ok(StorageVolInfo::from_ptr(&mut pinfo.assume_init()))
}
}
pub fn download(
&self,
stream: &Stream,
offset: u64,
length: u64,
flags: u32,
) -> Result<(), Error> {
unsafe {
let ret = sys::virStorageVolDownload(
self.as_ptr(),
stream.as_ptr(),
offset as libc::c_ulonglong,
length as libc::c_ulonglong,
flags as libc::c_uint,
);
if ret == -1 {
return Err(Error::last_error());
}
Ok(())
}
}
pub fn upload(
&self,
stream: &Stream,
offset: u64,
length: u64,
flags: u32,
) -> Result<(), Error> {
unsafe {
let ret = sys::virStorageVolUpload(
self.as_ptr(),
stream.as_ptr(),
offset as libc::c_ulonglong,
length as libc::c_ulonglong,
flags as libc::c_uint,
);
if ret == -1 {
return Err(Error::last_error());
}
Ok(())
}
}
}