use std::ffi::OsString;
use std::os::unix::ffi::OsStrExt;
use bincode::Options;
use bytes::{Buf, Bytes};
use futures_channel::mpsc::UnboundedSender;
use futures_util::sink::SinkExt;
use crate::helper::get_bincode_config;
use crate::raw::abi::{
fuse_notify_code, fuse_notify_delete_out, fuse_notify_inval_entry_out,
fuse_notify_inval_inode_out, fuse_notify_poll_wakeup_out, fuse_notify_retrieve_out,
fuse_notify_store_out, fuse_out_header, FUSE_NOTIFY_DELETE_OUT_SIZE,
FUSE_NOTIFY_INVAL_ENTRY_OUT_SIZE, FUSE_NOTIFY_INVAL_INODE_OUT_SIZE,
FUSE_NOTIFY_POLL_WAKEUP_OUT_SIZE, FUSE_NOTIFY_RETRIEVE_OUT_SIZE, FUSE_NOTIFY_STORE_OUT_SIZE,
FUSE_OUT_HEADER_SIZE,
};
#[derive(Debug, Clone)]
pub struct Notify {
sender: UnboundedSender<Vec<u8>>,
}
impl Notify {
pub(crate) fn new(sender: UnboundedSender<Vec<u8>>) -> Self {
Self { sender }
}
async fn notify(&mut self, kind: NotifyKind) -> std::result::Result<(), NotifyKind> {
let data = match &kind {
NotifyKind::Wakeup { kh } => {
let out_header = fuse_out_header {
len: (FUSE_OUT_HEADER_SIZE + FUSE_NOTIFY_POLL_WAKEUP_OUT_SIZE) as u32,
error: fuse_notify_code::FUSE_POLL as i32,
unique: 0,
};
let wakeup_out = fuse_notify_poll_wakeup_out { kh: *kh };
let mut data =
Vec::with_capacity(FUSE_OUT_HEADER_SIZE + FUSE_NOTIFY_POLL_WAKEUP_OUT_SIZE);
get_bincode_config()
.serialize_into(&mut data, &out_header)
.expect("vec size is not enough");
get_bincode_config()
.serialize_into(&mut data, &wakeup_out)
.expect("vec size is not enough");
data
}
NotifyKind::InvalidInode { inode, offset, len } => {
let out_header = fuse_out_header {
len: (FUSE_OUT_HEADER_SIZE + FUSE_NOTIFY_INVAL_INODE_OUT_SIZE) as u32,
error: fuse_notify_code::FUSE_NOTIFY_INVAL_INODE as i32,
unique: 0,
};
let invalid_inode_out = fuse_notify_inval_inode_out {
ino: *inode,
off: *offset,
len: *len,
};
let mut data =
Vec::with_capacity(FUSE_OUT_HEADER_SIZE + FUSE_NOTIFY_INVAL_INODE_OUT_SIZE);
get_bincode_config()
.serialize_into(&mut data, &out_header)
.expect("vec size is not enough");
get_bincode_config()
.serialize_into(&mut data, &invalid_inode_out)
.expect("vec size is not enough");
data
}
NotifyKind::InvalidEntry { parent, name } => {
let out_header = fuse_out_header {
len: (FUSE_OUT_HEADER_SIZE + FUSE_NOTIFY_INVAL_ENTRY_OUT_SIZE) as u32,
error: fuse_notify_code::FUSE_NOTIFY_INVAL_ENTRY as i32,
unique: 0,
};
let invalid_entry_out = fuse_notify_inval_entry_out {
parent: *parent,
namelen: name.len() as _,
padding: 0,
};
let mut data = Vec::with_capacity(
FUSE_OUT_HEADER_SIZE + FUSE_NOTIFY_INVAL_ENTRY_OUT_SIZE + name.len(),
);
get_bincode_config()
.serialize_into(&mut data, &out_header)
.expect("vec size is not enough");
get_bincode_config()
.serialize_into(&mut data, &invalid_entry_out)
.expect("vec size is not enough");
data.extend_from_slice(name.as_bytes());
data
}
NotifyKind::Delete {
parent,
child,
name,
} => {
let out_header = fuse_out_header {
len: (FUSE_OUT_HEADER_SIZE + FUSE_NOTIFY_DELETE_OUT_SIZE) as u32,
error: fuse_notify_code::FUSE_NOTIFY_DELETE as i32,
unique: 0,
};
let delete_out = fuse_notify_delete_out {
parent: *parent,
child: *child,
namelen: name.len() as _,
padding: 0,
};
let mut data = Vec::with_capacity(
FUSE_OUT_HEADER_SIZE + FUSE_NOTIFY_DELETE_OUT_SIZE + name.len(),
);
get_bincode_config()
.serialize_into(&mut data, &out_header)
.expect("vec size is not enough");
get_bincode_config()
.serialize_into(&mut data, &delete_out)
.expect("vec size is not enough");
data.extend_from_slice(name.as_bytes());
data
}
NotifyKind::Store {
inode,
offset,
data,
} => {
let out_header = fuse_out_header {
len: (FUSE_OUT_HEADER_SIZE + FUSE_NOTIFY_STORE_OUT_SIZE) as u32,
error: fuse_notify_code::FUSE_NOTIFY_STORE as i32,
unique: 0,
};
let store_out = fuse_notify_store_out {
nodeid: *inode,
offset: *offset,
size: data.len() as _,
padding: 0,
};
let mut data_buf = Vec::with_capacity(
FUSE_OUT_HEADER_SIZE + FUSE_NOTIFY_STORE_OUT_SIZE + data.len(),
);
get_bincode_config()
.serialize_into(&mut data_buf, &out_header)
.expect("vec size is not enough");
get_bincode_config()
.serialize_into(&mut data_buf, &store_out)
.expect("vec size is not enough");
data_buf.extend_from_slice(data);
data_buf
}
NotifyKind::Retrieve {
notify_unique,
inode,
offset,
size,
} => {
let out_header = fuse_out_header {
len: (FUSE_OUT_HEADER_SIZE + FUSE_NOTIFY_RETRIEVE_OUT_SIZE) as u32,
error: fuse_notify_code::FUSE_NOTIFY_RETRIEVE as i32,
unique: 0,
};
let retrieve_out = fuse_notify_retrieve_out {
notify_unique: *notify_unique,
nodeid: *inode,
offset: *offset,
size: *size,
padding: 0,
};
let mut data =
Vec::with_capacity(FUSE_OUT_HEADER_SIZE + FUSE_NOTIFY_RETRIEVE_OUT_SIZE);
get_bincode_config()
.serialize_into(&mut data, &out_header)
.expect("vec size is not enough");
get_bincode_config()
.serialize_into(&mut data, &retrieve_out)
.expect("vec size is not enough");
data
}
};
self.sender.send(data).await.or(Err(kind))
}
pub async fn wakeup(mut self, kh: u64) {
let _ = self.notify(NotifyKind::Wakeup { kh }).await;
}
pub async fn invalid_inode(mut self, inode: u64, offset: i64, len: i64) {
let _ = self
.notify(NotifyKind::InvalidInode { inode, offset, len })
.await;
}
pub async fn invalid_entry(mut self, parent: u64, name: OsString) {
let _ = self.notify(NotifyKind::InvalidEntry { parent, name }).await;
}
pub async fn delete(mut self, parent: u64, child: u64, name: OsString) {
let _ = self
.notify(NotifyKind::Delete {
parent,
child,
name,
})
.await;
}
pub async fn store(mut self, inode: u64, offset: u64, mut data: impl Buf) {
let _ = self
.notify(NotifyKind::Store {
inode,
offset,
data: data.copy_to_bytes(data.remaining()),
})
.await;
}
pub async fn retrieve(mut self, notify_unique: u64, inode: u64, offset: u64, size: u32) {
let _ = self
.notify(NotifyKind::Retrieve {
notify_unique,
inode,
offset,
size,
})
.await;
}
}
#[derive(Debug)]
enum NotifyKind {
Wakeup { kh: u64 },
InvalidInode { inode: u64, offset: i64, len: i64 },
InvalidEntry { parent: u64, name: OsString },
Delete {
parent: u64,
child: u64,
name: OsString,
},
Store {
inode: u64,
offset: u64,
data: Bytes,
},
Retrieve {
notify_unique: u64,
inode: u64,
offset: u64,
size: u32,
},
}