diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2020-01-29 22:57:39 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2020-01-29 23:48:15 +0100 |
commit | 81e1b39d2ea9ffa07f11aed3f230a7f26792058f (patch) | |
tree | 509b61e4b3e0535e82d4277e809e3023ec8cf839 /openpgp-ffi | |
parent | e5ee74691f21f46bdc30556a6b67ecf5f9532ece (diff) |
openpgp-ffi: Add a general writer interface.
Diffstat (limited to 'openpgp-ffi')
-rw-r--r-- | openpgp-ffi/examples/Makefile | 1 | ||||
-rw-r--r-- | openpgp-ffi/examples/writer-cookie.c | 31 | ||||
-rw-r--r-- | openpgp-ffi/include/sequoia/io.h | 12 | ||||
-rw-r--r-- | openpgp-ffi/src/io.rs | 42 |
4 files changed, 86 insertions, 0 deletions
diff --git a/openpgp-ffi/examples/Makefile b/openpgp-ffi/examples/Makefile index f5dd0f8c..c8de2c1f 100644 --- a/openpgp-ffi/examples/Makefile +++ b/openpgp-ffi/examples/Makefile @@ -13,6 +13,7 @@ EXAMPLES = \ decrypt-with \ generate-key \ type-safety-demo use-after-free-demo immutable-reference-demo \ + writer-cookie \ CFLAGS = -I../include -O0 -g -Wall -Werror LDFLAGS = -L$(CARGO_TARGET_DIR)/debug -lsequoia_openpgp_ffi diff --git a/openpgp-ffi/examples/writer-cookie.c b/openpgp-ffi/examples/writer-cookie.c new file mode 100644 index 00000000..b22f1fc3 --- /dev/null +++ b/openpgp-ffi/examples/writer-cookie.c @@ -0,0 +1,31 @@ +#include <assert.h> +#include <stdio.h> +#include <unistd.h> +#include <sequoia/openpgp.h> + +int +main (int argv, char **argc) +{ + pgp_status_t rc; + + /* First, generate the key. */ + pgp_cert_builder_t builder = pgp_cert_builder_new (); + pgp_cert_builder_set_cipher_suite (&builder, PGP_CERT_CIPHER_SUITE_CV25519); + + pgp_cert_t cert; + pgp_signature_t revocation; + pgp_cert_builder_generate (NULL, builder, &cert, &revocation); + assert (cert); + assert (revocation); + pgp_signature_free (revocation); /* Free the generated revocation. */ + + /* As an example, use write(2) as the callback. */ + pgp_writer_t w = pgp_writer_from_callback ((pgp_writer_cb_t) write, + (void *) 1); + rc = pgp_cert_serialize (NULL, cert, w); + assert (rc == PGP_STATUS_SUCCESS); + + pgp_cert_free (cert); + pgp_writer_free (w); + return 0; +} diff --git a/openpgp-ffi/include/sequoia/io.h b/openpgp-ffi/include/sequoia/io.h index 103116ae..8cce06c5 100644 --- a/openpgp-ffi/include/sequoia/io.h +++ b/openpgp-ffi/include/sequoia/io.h @@ -84,6 +84,18 @@ pgp_writer_t pgp_writer_from_bytes (uint8_t *buf, size_t len); pgp_writer_t pgp_writer_alloc (void **buf, size_t *len); /*/ +/// The callback type for the generic callback-based writer interface. +/*/ +typedef ssize_t (*pgp_writer_cb_t) (void *cookie, const void *buf, size_t len); + +/*/ +/// Creates an writer from a callback and cookie. +/// +/// This writer calls the given callback to write data. +/*/ +pgp_writer_t pgp_writer_from_callback (pgp_writer_cb_t, void *); + +/*/ /// Frees a writer. /*/ void pgp_writer_free (pgp_writer_t writer); diff --git a/openpgp-ffi/src/io.rs b/openpgp-ffi/src/io.rs index f0314e19..e3488e07 100644 --- a/openpgp-ffi/src/io.rs +++ b/openpgp-ffi/src/io.rs @@ -228,6 +228,48 @@ impl Write for WriterAlloc { } } +/// The callback type for the generic callback-based writer interface. +type WriterCallbackFn = fn(*mut c_void, *const c_void, size_t) -> ssize_t; + +/// Creates an writer from a callback and cookie. +/// +/// This writer calls the given callback to write data. +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" +fn pgp_writer_from_callback(cb: WriterCallbackFn, + cookie: *mut c_void) + -> *mut Writer { + let w: Box<dyn io::Write> = Box::new(WriterCallback { + cb, cookie, + }); + w.move_into_raw() +} + +/// A generic callback-based writer implementation. +struct WriterCallback { + cb: WriterCallbackFn, + cookie: *mut c_void, +} + +impl Write for WriterCallback { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + let r = + (self.cb)(self.cookie, buf.as_ptr() as *const c_void, buf.len()); + if r < 0 { + use std::io as stdio; + Err(stdio::Error::new(stdio::ErrorKind::Other, + "Unknown error in write callback")) + } else { + Ok(r as usize) + } + } + + fn flush(&mut self) -> io::Result<()> { + // Do nothing. + // XXX: Should we add a callback for that? + Ok(()) + } +} + /// Writes up to `len` bytes of `buf` into `writer`. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C" fn pgp_writer_write(errp: Option<&mut *mut crate::error::Error>, |