mun_libloader/temp_library.rs
1use std::fs;
2use std::path::Path;
3
4use anyhow::Error;
5use libloading::Library;
6
7/// A structure that holds a `Library` instance but creates a unique file per load. This enables
8/// writing to the original library and ensures that each shared object on Linux is loaded
9/// separately.
10///
11/// There is no risk of cleaning the temporary file while it is used because loading the library
12/// keeps the file open (Windows) or keeping the file is not required in the first place (*nix).
13pub struct TempLibrary {
14 _tmp_path: tempfile::TempPath,
15 library: Library,
16}
17
18impl TempLibrary {
19 /// Find and load a dynamic library.
20 ///
21 /// The `filename` argument may be either:
22 ///
23 /// * A library filename;
24 /// * The absolute path to the library;
25 /// * A relative (to the current working directory) path to the library.
26 ///
27 /// # Safety
28 ///
29 /// When a library is loaded, initialisation routines contained within it are executed.
30 /// For the purposes of safety, the execution of these routines is conceptually the same calling
31 /// an unknown foreign function and may impose arbitrary requirements on the caller for the call
32 /// to be sound.
33 ///
34 /// Additionally, the callers of this function must also ensure that execution of the
35 /// termination routines contained within the library is safe as well. These routines may be
36 /// executed when the library is unloaded.
37 ///
38 /// See [`libloading::Library::new`] for more information.
39 pub unsafe fn new(path: &Path) -> Result<Self, Error> {
40 let tmp_path = tempfile::NamedTempFile::new()?.into_temp_path();
41 fs::copy(path, &tmp_path)?;
42 let library = Library::new(&tmp_path)?;
43 Ok(TempLibrary {
44 _tmp_path: tmp_path,
45 library,
46 })
47 }
48
49 /// Returns the loaded library
50 pub fn library(&self) -> &Library {
51 &self.library
52 }
53}