summaryrefslogtreecommitdiffstats
path: root/openpgp-ffi
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-02-04 15:12:48 +0100
committerJustus Winter <justus@sequoia-pgp.org>2019-02-05 17:56:29 +0100
commit83faf100849705e1d090a130975ed90ccb3a3738 (patch)
treea6d1cb7515c124ad7fb005684421553d470280f7 /openpgp-ffi
parent2d1f6bb425e14d34f7ad40f59022d5e0a34fb79e (diff)
openpgp-ffi: Convert pgp_reader_t to the new framework.
Diffstat (limited to 'openpgp-ffi')
-rw-r--r--openpgp-ffi/src/armor.rs84
-rw-r--r--openpgp-ffi/src/common.rs18
-rw-r--r--openpgp-ffi/src/io.rs100
-rw-r--r--openpgp-ffi/src/parse.rs7
4 files changed, 120 insertions, 89 deletions
diff --git a/openpgp-ffi/src/armor.rs b/openpgp-ffi/src/armor.rs
index 3c1039c2..bec0ab80 100644
--- a/openpgp-ffi/src/armor.rs
+++ b/openpgp-ffi/src/armor.rs
@@ -7,13 +7,18 @@
use std::mem::size_of;
use std::ptr;
use std::slice;
-use std::io::{Read, Write};
+use std::io::Write;
use libc::{self, uint8_t, c_char, c_int, size_t};
extern crate sequoia_openpgp;
use self::sequoia_openpgp::armor;
+use super::io::{Reader, ReaderKind};
+use Maybe;
use MoveIntoRaw;
+use MoveResultIntoRaw;
+use RefRaw;
+use RefMutRaw;
/// Represents a (key, value) pair in an armor header.
#[repr(C)]
@@ -102,28 +107,28 @@ fn kind_to_int(kind: Option<armor::Kind>) -> c_int {
/// pgp_reader_free (bytes);
/// ```
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
-pub extern "system" fn pgp_armor_reader_new(inner: *mut Box<Read>,
- kind: c_int)
- -> *mut Box<Read> {
- let inner = ffi_param_ref_mut!(inner);
+pub extern "system" fn pgp_armor_reader_new(inner: *mut Reader,
+ kind: c_int)
+ -> *mut Reader {
+ let inner = inner.ref_mut_raw();
let kind = int_to_kind(kind);
- box_raw!(Box::new(armor::Reader::new(inner, kind)))
+ ReaderKind::Armored(armor::Reader::new(inner, kind)).move_into_raw()
}
/// Creates a `Reader` from a file.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
pub extern "system" fn pgp_armor_reader_from_file(errp: Option<&mut *mut ::error::Error>,
- filename: *const c_char,
- kind: c_int)
- -> *mut Box<Read> {
- ffi_make_fry_from_errp!(errp);
+ filename: *const c_char,
+ kind: c_int)
+ -> Maybe<Reader> {
let filename = ffi_param_cstr!(filename).to_string_lossy().into_owned();
let kind = int_to_kind(kind);
- ffi_try_box!(armor::Reader::from_file(&filename, kind)
- .map(|r| Box::new(r))
- .map_err(|e| ::failure::Error::from(e)))
+ armor::Reader::from_file(&filename, kind)
+ .map(|r| ReaderKind::Armored(r))
+ .map_err(|e| ::failure::Error::from(e))
+ .move_into_raw(errp)
}
/// Creates a `Reader` from a buffer.
@@ -180,17 +185,17 @@ pub extern "system" fn pgp_armor_reader_from_file(errp: Option<&mut *mut ::error
///
/// pgp_reader_free (armor);
/// ```
-#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
-pub extern "system" fn pgp_armor_reader_from_bytes(b: *const uint8_t, len: size_t,
- kind: c_int)
- -> *mut Box<Read> {
+#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "system"
+fn pgp_armor_reader_from_bytes(b: *const uint8_t, len: size_t,
+ kind: c_int)
+ -> *mut Reader {
assert!(!b.is_null());
let buf = unsafe {
slice::from_raw_parts(b, len as usize)
};
let kind = int_to_kind(kind);
- box_raw!(Box::new(armor::Reader::from_bytes(buf, kind)))
+ ReaderKind::Armored(armor::Reader::from_bytes(buf, kind)).move_into_raw()
}
/// Returns the kind of data this reader is for.
@@ -205,16 +210,16 @@ pub extern "system" fn pgp_armor_reader_from_bytes(b: *const uint8_t, len: size_
///
/// [this]: fn.pgp_armor_reader_new.html
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
-pub extern "system" fn pgp_armor_reader_kind(reader: *mut Box<Read>)
- -> c_int {
- // We need to downcast `reader`. To do that, we need to do a
- // little dance. We will momentarily take ownership of `reader`,
- // wrapping it in a Box again. Then, at the end of the function,
- // we will leak it again.
- let reader = ffi_param_move!(reader as *mut Box<armor::Reader>);
- let kind = kind_to_int(reader.kind());
- Box::into_raw(reader);
- kind
+pub extern "system" fn pgp_armor_reader_kind(reader: *const Reader)
+ -> c_int {
+ if let ReaderKind::Armored(ref armor_reader) = reader.ref_raw()
+ {
+ kind_to_int(armor_reader.kind())
+ } else {
+ panic!(
+ "FFI contract violation: Wrong parameter type: \
+ expected an armor reader")
+ }
}
/// Returns the armored headers.
@@ -236,21 +241,20 @@ pub extern "system" fn pgp_armor_reader_kind(reader: *mut Box<Read>)
/// [this]: fn.pgp_armor_reader_new.html
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
pub extern "system" fn pgp_armor_reader_headers(errp: Option<&mut *mut ::error::Error>,
- reader: *mut Box<Read>,
+ reader: *mut Reader,
len: *mut size_t)
-> *mut ArmorHeader {
ffi_make_fry_from_errp!(errp);
let len = ffi_param_ref_mut!(len);
- // We need to downcast `reader`. To do that, we need to do a
- // little dance. We will momentarily take ownership of `reader`,
- // wrapping it in a Box again. Then, at the end of the function,
- // we will leak it again.
- let mut reader = ffi_param_move!(reader as *mut Box<armor::Reader>);
+ let reader = if let ReaderKind::Armored(ref mut reader) = reader.ref_mut_raw() {
+ reader
+ } else {
+ panic!("FFI contract violation: Wrong parameter type: \
+ expected armor reader");
+ };
- // We need to be extra careful here in order not to keep ownership
- // of `reader` in case of errors.
- let result = match reader.headers().map_err(|e| ::failure::Error::from(e)) {
+ match reader.headers().map_err(|e| ::failure::Error::from(e)) {
Ok(headers) => {
// Allocate space for the result.
let buf = unsafe {
@@ -276,11 +280,7 @@ pub extern "system" fn pgp_armor_reader_headers(errp: Option<&mut *mut ::error::
}
ptr::null_mut()
},
- };
-
- // Release temporary ownership.
- Box::into_raw(reader);
- result
+ }
}
/// Constructs a new filter for the given type of data.
diff --git a/openpgp-ffi/src/common.rs b/openpgp-ffi/src/common.rs
index e6c67db4..45d788e0 100644
--- a/openpgp-ffi/src/common.rs
+++ b/openpgp-ffi/src/common.rs
@@ -573,8 +573,8 @@ impl VerificationHelper for VHelper {
}
}
-fn verify_real<'a>(input: &'a mut Box<'a + Read>,
- dsig: Option<&'a mut Box<'a + Read>>,
+fn verify_real<'a>(input: &'a mut Read,
+ dsig: Option<&mut io::ReaderKind>,
output: Option<&'a mut Box<'a + Write>>,
get_public_keys: GetPublicKeysCallback,
check_signatures: CheckSignaturesCallback,
@@ -624,8 +624,8 @@ fn verify_real<'a>(input: &'a mut Box<'a + Read>,
/// Note: output may be NULL, if the output is not required.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
pub fn pgp_verify<'a>(errp: Option<&mut *mut ::error::Error>,
- input: *mut Box<'a + Read>,
- dsig: Option<&'a mut Box<'a + Read>>,
+ input: *mut io::Reader,
+ dsig: Maybe<io::Reader>,
output: Option<&'a mut Box<'a + Write>>,
get_public_keys: GetPublicKeysCallback,
check_signatures: CheckSignaturesCallback,
@@ -633,9 +633,9 @@ pub fn pgp_verify<'a>(errp: Option<&mut *mut ::error::Error>,
-> Status
{
ffi_make_fry_from_errp!(errp);
- let input = ffi_param_ref_mut!(input);
+ let input = input.ref_mut_raw();
- let r = verify_real(input, dsig, output,
+ let r = verify_real(input, dsig.ref_mut_raw(), output,
get_public_keys, check_signatures, cookie);
ffi_try_status!(r)
@@ -707,7 +707,7 @@ impl DecryptionHelper for DHelper {
// A helper function that returns a Result so that we can use ? to
// propagate errors.
-fn decrypt_real<'a>(input: &'a mut Box<'a + Read>,
+fn decrypt_real<'a>(input: &'a mut io::ReaderKind,
output: &'a mut Box<'a + Write>,
get_public_keys: GetPublicKeysCallback,
get_secret_keys: GetSecretKeysCallback,
@@ -747,7 +747,7 @@ fn decrypt_real<'a>(input: &'a mut Box<'a + Read>,
/// Note: all of the parameters are required; none may be NULL.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
pub fn pgp_decrypt<'a>(errp: Option<&mut *mut ::error::Error>,
- input: *mut Box<'a + Read>,
+ input: *mut io::Reader,
output: *mut Box<'a + Write>,
get_public_keys: GetPublicKeysCallback,
get_secret_keys: GetSecretKeysCallback,
@@ -756,7 +756,7 @@ pub fn pgp_decrypt<'a>(errp: Option<&mut *mut ::error::Error>,
-> Status
{
ffi_make_fry_from_errp!(errp);
- let input = ffi_param_ref_mut!(input);
+ let input = input.ref_mut_raw();
let output = ffi_param_ref_mut!(output);
let r = decrypt_real(input, output,
diff --git a/openpgp-ffi/src/io.rs b/openpgp-ffi/src/io.rs
index e6ca0eda..42f78558 100644
--- a/openpgp-ffi/src/io.rs
+++ b/openpgp-ffi/src/io.rs
@@ -9,57 +9,87 @@ use libc::{uint8_t, c_void, c_char, c_int, size_t, ssize_t, realloc};
#[cfg(unix)]
use std::os::unix::io::FromRawFd;
+extern crate sequoia_openpgp as openpgp;
+
+use Maybe;
+
+/// Wraps a generic reader.
+#[::ffi_wrapper_type(prefix = "pgp_")]
+pub struct Reader(ReaderKind);
+
+/// Specializes readers.
+///
+/// In some cases, we want to call functions on concrete types. To
+/// avoid nasty hacks, we have specialized variants for that.
+pub(crate) enum ReaderKind {
+ Generic(Box<io::Read>),
+ Armored(openpgp::armor::Reader<'static>),
+}
+
+impl Read for ReaderKind {
+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+ use self::ReaderKind::*;
+ match self {
+ Generic(ref mut r) => r.read(buf),
+ Armored(ref mut r) => r.read(buf),
+ }
+ }
+}
+
/// Opens a file returning a reader.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
pub extern "system" fn pgp_reader_from_file(errp: Option<&mut *mut ::error::Error>,
- filename: *const c_char)
- -> *mut Box<Read> {
- ffi_make_fry_from_errp!(errp);
+ filename: *const c_char)
+ -> Maybe<Reader> {
let filename = ffi_param_cstr!(filename).to_string_lossy().into_owned();
- ffi_try_box!(File::open(Path::new(&filename))
- .map(|r| Box::new(r))
- .map_err(|e| ::failure::Error::from(e)))
+ File::open(Path::new(&filename))
+ .map(|r| ReaderKind::Generic(Box::new(r)))
+ .map_err(|e| ::failure::Error::from(e))
+ .move_into_raw(errp)
}
/// Opens a file descriptor returning a reader.
#[cfg(unix)]
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
pub extern "system" fn pgp_reader_from_fd(fd: c_int)
- -> *mut Box<Read> {
- box_raw!(Box::new(unsafe { File::from_raw_fd(fd) }))
+ -> *mut Reader {
+ ReaderKind::Generic(Box::new(unsafe {
+ File::from_raw_fd(fd)
+ })).move_into_raw()
}
/// Creates a reader from a buffer.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
pub extern "system" fn pgp_reader_from_bytes(buf: *const uint8_t,
- len: size_t)
- -> *mut Box<Read> {
+ len: size_t)
+ -> *mut Reader {
assert!(!buf.is_null());
let buf = unsafe {
slice::from_raw_parts(buf, len as usize)
};
- box_raw!(Box::new(Cursor::new(buf)))
-}
-
-/// Frees a reader.
-#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
-pub extern "system" fn pgp_reader_free(reader: Option<&mut Box<Read>>) {
- ffi_free!(reader)
+ ReaderKind::Generic(Box::new(Cursor::new(buf))).move_into_raw()
}
/// Reads up to `len` bytes into `buf`.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
pub extern "system" fn pgp_reader_read(errp: Option<&mut *mut ::error::Error>,
- reader: *mut Box<Read>,
- buf: *mut uint8_t, len: size_t)
- -> ssize_t {
- ffi_make_fry_from_errp!(errp);
- let reader = ffi_param_ref_mut!(reader);
+ reader: *mut Reader,
+ buf: *mut uint8_t, len: size_t)
+ -> ssize_t {
assert!(!buf.is_null());
let buf = unsafe {
slice::from_raw_parts_mut(buf, len as usize)
};
- ffi_try_or!(reader.read(buf).map_err(|e| ::failure::Error::from(e)), -1) as ssize_t
+ reader.ref_mut_raw().read(buf)
+ .map(|n_read| n_read as ssize_t)
+ .unwrap_or_else(|e| {
+ if let Some(errp) = errp {
+ *errp = ::failure::Error::from(e).move_into_raw();
+ };
+
+ // Signal failure.
+ -1
+ })
}
@@ -69,28 +99,28 @@ pub extern "system" fn pgp_reader_read(errp: Option<&mut *mut ::error::Error>,
/// otherwise. If you need more control, use `pgp_writer_from_fd`.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
pub extern "system" fn pgp_writer_from_file(errp: Option<&mut *mut ::error::Error>,
- filename: *const c_char)
- -> *mut Box<Write> {
+ filename: *const c_char)
+ -> *mut Box<Write> {
ffi_make_fry_from_errp!(errp);
let filename = ffi_param_cstr!(filename).to_string_lossy().into_owned();
ffi_try_box!(File::create(Path::new(&filename))
- .map(|r| Box::new(r))
- .map_err(|e| ::failure::Error::from(e)))
+ .map(|r| Box::new(r))
+ .map_err(|e| ::failure::Error::from(e)))
}
/// Opens a file descriptor returning a writer.
#[cfg(unix)]
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
pub extern "system" fn pgp_writer_from_fd(fd: c_int)
- -> *mut Box<Write> {
+ -> *mut Box<Write> {
box_raw!(Box::new(unsafe { File::from_raw_fd(fd) }))
}
/// Creates a writer from a buffer.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
pub extern "system" fn pgp_writer_from_bytes(buf: *mut uint8_t,
- len: size_t)
- -> *mut Box<Write> {
+ len: size_t)
+ -> *mut Box<Write> {
assert!(!buf.is_null());
let buf = unsafe {
slice::from_raw_parts_mut(buf, len as usize)
@@ -108,8 +138,8 @@ pub extern "system" fn pgp_writer_from_bytes(buf: *mut uint8_t,
/// destroyed.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
pub extern "system" fn pgp_writer_alloc(buf: *mut *mut c_void,
- len: *mut size_t)
- -> *mut Box<Write> {
+ len: *mut size_t)
+ -> *mut Box<Write> {
let buf = ffi_param_ref_mut!(buf);
let len = ffi_param_ref_mut!(len);
@@ -161,9 +191,9 @@ pub extern "system" fn pgp_writer_free(writer: Option<&mut Box<Write>>) {
/// Writes up to `len` bytes of `buf` into `writer`.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
pub extern "system" fn pgp_writer_write(errp: Option<&mut *mut ::error::Error>,
- writer: *mut Box<Write>,
- buf: *const uint8_t, len: size_t)
- -> ssize_t {
+ writer: *mut Box<Write>,
+ buf: *const uint8_t, len: size_t)
+ -> ssize_t {
ffi_make_fry_from_errp!(errp);
let writer = ffi_param_ref_mut!(writer);
assert!(!buf.is_null());
diff --git a/openpgp-ffi/src/parse.rs b/openpgp-ffi/src/parse.rs
index 3cdba933..d3a1567a 100644
--- a/openpgp-ffi/src/parse.rs
+++ b/openpgp-ffi/src/parse.rs
@@ -9,7 +9,6 @@
use std::mem::forget;
use std::ptr;
use std::slice;
-use std::io::Read;
use libc::{uint8_t, c_char, c_int, size_t};
extern crate sequoia_openpgp as openpgp;
@@ -25,8 +24,10 @@ use self::openpgp::parse::{
PacketParserEOF,
};
+use super::io::Reader;
use error::Status;
use MoveIntoRaw;
+use RefMutRaw;
/// Starts parsing OpenPGP packets stored in a `pgp_reader_t`
/// object.
@@ -35,10 +36,10 @@ use MoveIntoRaw;
/// the stream.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
pub extern "system" fn pgp_packet_parser_from_reader<'a>
- (errp: Option<&mut *mut ::error::Error>, reader: *mut Box<'a + Read>)
+ (errp: Option<&mut *mut ::error::Error>, reader: *mut Reader)
-> *mut PacketParserResult<'a> {
ffi_make_fry_from_errp!(errp);
- let reader = ffi_param_ref_mut!(reader);
+ let reader = reader.ref_mut_raw();
ffi_try_box!(PacketParser::from_reader(reader))
}