summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@pep-project.org>2017-11-23 14:34:45 +0100
committerJustus Winter <justus@pep-project.org>2017-11-23 14:36:36 +0100
commit9a5725fe55eb5e49cee09712364ac7b7dcefde51 (patch)
tree4f0b3b5e86a02236a06c503e8adcc03fc6fc1d7e
parent8cdab3036cfd2111fd3719abc38ab334bc72ebdc (diff)
Add a foreign function interface.
- For now, we keep the ffi in this crate, later on we may want to move it to sequoia-ffi. - Example code how to use the library from C is added as well.
-rw-r--r--Cargo.toml2
-rw-r--r--examples/Makefile3
-rw-r--r--examples/example.c44
-rw-r--r--src/ffi.rs40
-rw-r--r--src/lib.rs1
-rw-r--r--src/sequoia.h10
6 files changed, 100 insertions, 0 deletions
diff --git a/Cargo.toml b/Cargo.toml
index e39e4914..d59a30e3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,6 +4,7 @@ version = "0.1.0"
authors = ["Neal H. Walfield <neal@gnu.org>"]
[dependencies]
+libc = "0.2.33"
nom = "3.2.0"
num = "0.1.40"
num-derive = "0.1.41"
@@ -13,6 +14,7 @@ bzip2 = "0.3.2"
[lib]
name = "sequoia"
path = "src/lib.rs"
+crate-type = ["lib", "dylib"]
[[bin]]
doc = false
diff --git a/examples/Makefile b/examples/Makefile
new file mode 100644
index 00000000..59007930
--- /dev/null
+++ b/examples/Makefile
@@ -0,0 +1,3 @@
+CFLAGS = -I../src -O0 -g -Wall
+LDFLAGS = -L../target/debug -lsequoia
+all: example
diff --git a/examples/example.c b/examples/example.c
new file mode 100644
index 00000000..ae727b43
--- /dev/null
+++ b/examples/example.c
@@ -0,0 +1,44 @@
+#define _GNU_SOURCE
+#include <error.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <sequoia.h>
+
+int
+main (int argc, char **argv)
+{
+ struct stat st;
+ int fd;
+ char *b;
+ struct sq_tpk *tpk;
+
+ if (argc != 2)
+ error (1, 0, "Usage: %s <file>", argv[0]);
+
+ if (stat (argv[1], &st))
+ error (1, errno, "%s", argv[1]);
+
+ fd = open (argv[1], O_RDONLY);
+ if (fd == -1)
+ error (1, errno, "%s", argv[1]);
+
+ b = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (b == MAP_FAILED)
+ error (1, errno, "mmap");
+
+ tpk = sq_tpk_from_bytes (b, st.st_size);
+ if (tpk == NULL)
+ error (1, 0, "sq_tpk_from_bytes failed");
+
+ sq_tpk_dump (tpk);
+ sq_tpk_free (tpk);
+ munmap (b, st.st_size);
+ close (fd);
+ return 0;
+}
diff --git a/src/ffi.rs b/src/ffi.rs
new file mode 100644
index 00000000..3a7b1c66
--- /dev/null
+++ b/src/ffi.rs
@@ -0,0 +1,40 @@
+extern crate libc;
+use self::libc::{uint8_t, size_t};
+
+use std::ptr;
+use std::slice;
+use keys::TPK;
+use openpgp;
+
+#[no_mangle]
+pub extern "system" fn sq_tpk_from_bytes(b: *const uint8_t, len: size_t) -> *mut TPK {
+ assert!(!b.is_null());
+ let bytes = unsafe {
+ slice::from_raw_parts(b, len as usize)
+ };
+ let m = openpgp::Message::from_bytes(bytes);
+
+ if let Some(tpk) = m.ok().and_then(|m| TPK::from_message(m)) {
+ Box::into_raw(Box::new(tpk))
+ } else {
+ ptr::null_mut()
+ }
+}
+
+#[no_mangle]
+pub extern "system" fn sq_tpk_dump(tpk: *mut TPK) {
+ assert!(!tpk.is_null());
+ unsafe {
+ println!("{:?}", *tpk);
+ }
+}
+
+#[no_mangle]
+pub extern "system" fn sq_tpk_free(tpk: *mut TPK) {
+ if tpk.is_null() {
+ return
+ }
+ unsafe {
+ drop(Box::from_raw(tpk));
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index a69113c7..291db413 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -14,3 +14,4 @@ pub mod openpgp;
pub mod keys;
pub mod key_store;
pub mod net;
+pub mod ffi;
diff --git a/src/sequoia.h b/src/sequoia.h
new file mode 100644
index 00000000..0853b9aa
--- /dev/null
+++ b/src/sequoia.h
@@ -0,0 +1,10 @@
+#ifndef SEQUOIA_H
+#define SEQUOIA_H
+
+struct sq_tpk;
+
+struct sq_tpk *sq_tpk_from_bytes (const char *b, size_t len);
+void sq_tpk_dump (const struct sq_tpk *tpk);
+void sq_tpk_free (struct sq_tpk *tpk);
+
+#endif