use std::ffi::OsString;
use std::sync::Arc;
use bytes::{Buf, Bytes};
use zerocopy::IntoBytes;
use crate::raw::abi::{
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,
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,
};
use crate::raw::session::ResponseSender;
#[derive(Debug, Clone)]
pub struct Notify {
sender: Arc<ResponseSender>,
}
impl Notify {
pub(crate) fn new(sender: Arc<ResponseSender>) -> Self {
Self { sender }
}
async fn notify(&mut self, kind: NotifyKind) {
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 };
self.sender.send2(&out_header, wakeup_out.as_bytes()).await;
}
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,
};
self.sender
.send2(&out_header, invalid_inode_out.as_bytes())
.await;
}
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,
};
self.sender
.send2(&out_header, invalid_entry_out.as_bytes())
.await;
}
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,
};
self.sender.send2(&out_header, delete_out.as_bytes()).await;
}
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,
};
self.sender.send2(&out_header, store_out.as_bytes()).await;
}
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,
};
self.sender
.send2(&out_header, retrieve_out.as_bytes())
.await;
}
};
}
pub async fn wakeup(mut self, kh: u64) {
self.notify(NotifyKind::Wakeup { kh }).await;
}
pub async fn invalid_inode(mut self, inode: u64, offset: i64, len: i64) {
self.notify(NotifyKind::InvalidInode { inode, offset, len })
.await;
}
pub async fn invalid_entry(mut self, parent: u64, name: OsString) {
self.notify(NotifyKind::InvalidEntry { parent, name }).await;
}
pub async fn delete(mut self, parent: u64, child: u64, name: OsString) {
self.notify(NotifyKind::Delete {
parent,
child,
name,
})
.await;
}
pub async fn store(mut self, inode: u64, offset: u64, mut data: impl Buf) {
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) {
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,
},
}