diff options
-rw-r--r-- | examples/example.c | 6 | ||||
-rw-r--r-- | src/ffi.rs | 48 | ||||
-rw-r--r-- | src/lib.rs | 65 | ||||
-rw-r--r-- | src/sequoia.h | 5 |
4 files changed, 123 insertions, 1 deletions
diff --git a/examples/example.c b/examples/example.c index ae727b43..81209a7e 100644 --- a/examples/example.c +++ b/examples/example.c @@ -16,11 +16,16 @@ main (int argc, char **argv) struct stat st; int fd; char *b; + struct sq_context *ctx; struct sq_tpk *tpk; if (argc != 2) error (1, 0, "Usage: %s <file>", argv[0]); + ctx = sq_context_new(NULL, NULL); + if (ctx == NULL) + error (1, 0, "Initializing sequoia failed."); + if (stat (argv[1], &st)) error (1, errno, "%s", argv[1]); @@ -38,6 +43,7 @@ main (int argc, char **argv) sq_tpk_dump (tpk); sq_tpk_free (tpk); + sq_context_free (ctx); munmap (b, st.st_size); close (fd); return 0; @@ -1,10 +1,56 @@ extern crate libc; -use self::libc::{uint8_t, size_t}; +use self::libc::{uint8_t, c_char, size_t}; +use std::ffi::CStr; use std::ptr; use std::slice; +use std::str; + use keys::TPK; use openpgp; +use super::Context; + +/// Create a context object. +/// +/// If `home` is not `NULL`, it is used as directory containing shared +/// state and rendezvous nodes. If `lib` is not `NULL`, it is used as +/// directory containing backend servers. If either argument is +/// `NULL`, a reasonable default is used. +/// +/// Returns `NULL` on errors. +#[no_mangle] +pub extern "system" fn sq_context_new(home: *const c_char, + lib: *const c_char) -> *mut Context { + let home = unsafe { + if home.is_null() { None } else { Some(CStr::from_ptr(home)) } + }; + let lib = unsafe { + if lib.is_null() { None } else { Some(CStr::from_ptr(lib)) } + }; + + let mut pre = Context::new(); + + if let Some(home) = home { + pre = pre.home(home.to_string_lossy().as_ref()); + } + if let Some(lib) = lib { + pre = pre.lib(lib.to_string_lossy().as_ref()); + } + + if let Ok(context) = pre.finalize() { + Box::into_raw(Box::new(context)) + } else { + ptr::null_mut() + } +} + +/// Free a context. +#[no_mangle] +pub extern "system" fn sq_context_free(context: *mut Context) { + unsafe { + drop(Box::from_raw(context)); + } +} #[no_mangle] pub extern "system" fn sq_tpk_from_bytes(b: *const uint8_t, len: size_t) -> *mut TPK { @@ -16,3 +16,68 @@ pub mod key_store; pub mod net; pub mod ffi; pub mod armor; + +use std::env; +use std::fs; +use std::io; +use std::path::{Path, PathBuf}; + +/// A `&Context` is required for many operations. +pub struct Context { + home: PathBuf, + lib: PathBuf, +} + +fn prefix() -> PathBuf { + /* XXX: Windows support. */ + PathBuf::from(option_env!("PREFIX").or(Some("/usr/local")).unwrap()) +} + +impl Context { + /// Create a `Pre(Context)` with reasonable defaults. `Pre(Context)`s + /// can be modified, and have to be finalized in order to turn + /// them into a Context. + pub fn new() -> Pre { + Pre(Context { + home: env::home_dir().unwrap_or(env::temp_dir()) + .join(".sequoia"), + lib: prefix().join("lib").join("sequoia"), + }) + } + + /// Return the directory containing shared state and rendezvous + /// nodes. + pub fn home(&self) -> &Path { + &self.home + } + + /// Return the directory containing backend servers. + pub fn lib(&self) -> &Path { + &self.lib + } +} + +/// A `Pre(Context)` is a context object that can be modified. +pub struct Pre(Context); + +impl Pre { + /// Finalize the configuration and return a `Context`. + pub fn finalize(self) -> io::Result<Context> { + let c = self.0; + fs::create_dir_all(c.home())?; + Ok(c) + } + + /// Set the directory containing shared state and rendezvous + /// nodes. + pub fn home<P: AsRef<Path>>(mut self, new: P) -> Self { + self.0.home = PathBuf::new().join(new); + self + } + + /// Set the directory containing backend servers. + pub fn lib<P: AsRef<Path>>(mut self, new: P) -> Self { + self.0.lib = PathBuf::new().join(new); + self + } +} diff --git a/src/sequoia.h b/src/sequoia.h index 0853b9aa..7b3f9cf2 100644 --- a/src/sequoia.h +++ b/src/sequoia.h @@ -1,6 +1,11 @@ #ifndef SEQUOIA_H #define SEQUOIA_H +struct sq_context; + +struct sq_context *sq_context_new(const char *home, const char *lib); +void sq_context_free(struct sq_context *context); + struct sq_tpk; struct sq_tpk *sq_tpk_from_bytes (const char *b, size_t len); |