From 3732aa02f6e1ac6a08a0de33ec85d2b9d6940a2c Mon Sep 17 00:00:00 2001 From: Rubens Brandao Date: Mon, 27 May 2024 08:58:59 -0300 Subject: [PATCH] add `TemporaryFile` implementation --- rust/src/databuffer.rs | 1 + rust/src/fileaccessor.rs | 64 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/rust/src/databuffer.rs b/rust/src/databuffer.rs index c3d268cd3..cdd1765d1 100644 --- a/rust/src/databuffer.rs +++ b/rust/src/databuffer.rs @@ -25,6 +25,7 @@ pub struct DataBuffer(*mut BNDataBuffer); impl DataBuffer { pub(crate) fn from_raw(raw: *mut BNDataBuffer) -> Self { + assert!(!raw.is_null()); DataBuffer(raw) } pub(crate) fn as_raw(&self) -> *mut BNDataBuffer { diff --git a/rust/src/fileaccessor.rs b/rust/src/fileaccessor.rs index cf94e902b..b661bd50d 100644 --- a/rust/src/fileaccessor.rs +++ b/rust/src/fileaccessor.rs @@ -12,11 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -use binaryninjacore_sys::BNFileAccessor; +use binaryninjacore_sys::*; use std::io::{Read, Seek, SeekFrom, Write}; use std::marker::PhantomData; +use std::path::PathBuf; use std::slice; +use crate::databuffer::DataBuffer; +use crate::string::BnString; + pub struct FileAccessor<'a> { pub(crate) api_object: BNFileAccessor, _ref: PhantomData<&'a mut ()>, @@ -88,3 +92,61 @@ impl<'a> FileAccessor<'a> { } } } + +pub struct TemporaryFile(*mut BNTemporaryFile); + +impl TemporaryFile { + pub fn new_from_contents(value: &DataBuffer) -> Result { + let new = unsafe { BNCreateTemporaryFileWithContents(value.as_raw()) }; + if new.is_null() { + return Err(()); + } + Ok(Self(new)) + } + + /// create a new reference to the same file + pub fn clone_reference(&self) -> Self { + let new = unsafe { BNNewTemporaryFileReference(self.0) }; + assert!(!new.is_null()); + Self(new) + } + + pub fn path(&self) -> PathBuf { + let path = unsafe { BnString::from_raw(BNGetTemporaryFilePath(self.0)) }; + PathBuf::from(path.to_string()) + } + + // TODO is databuffer lifetime associated with the TemporaryFile? + // can we modify the DataBuffer without affecting the temp file? + pub fn contents(&self) -> DataBuffer { + unsafe { DataBuffer::from_raw(BNGetTemporaryFileContents(self.0)) } + } +} + +impl Default for TemporaryFile { + fn default() -> Self { + Self(unsafe { BNCreateTemporaryFile() }) + } +} + +impl Drop for TemporaryFile { + fn drop(&mut self) { + unsafe { BNFreeTemporaryFile(self.0) } + } +} + +#[cfg(test)] +mod test { + use crate::databuffer::DataBuffer; + + use super::TemporaryFile; + + #[test] + pub fn create_tmp_file() { + const DATA: &[u8] = b"test 123"; + let data = DataBuffer::new(DATA).unwrap(); + let tmp_file = TemporaryFile::new_from_contents(&data).unwrap(); + let data_read = tmp_file.contents(); + assert_eq!(data_read.get_data(), DATA); + } +}