Skip to content

Commit 56c94b4

Browse files
wip: gobject
1 parent b1ae93c commit 56c94b4

11 files changed

Lines changed: 1569 additions & 103 deletions

File tree

Cargo.lock

Lines changed: 273 additions & 103 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ members = [
55
"cargo-credential",
66
"client",
77
"cli",
8+
"gobject",
89
"pam",
910
"portal",
1011
"python",

gobject/Cargo.toml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[package]
2+
name = "oo7-gobject"
3+
version.workspace = true
4+
edition.workspace = true
5+
authors.workspace = true
6+
keywords.workspace = true
7+
categories.workspace = true
8+
repository.workspace = true
9+
homepage.workspace = true
10+
license.workspace = true
11+
rust-version.workspace = true
12+
description = "GObject bindings for oo7"
13+
14+
[lib]
15+
name = "oo7"
16+
crate-type = ["staticlib", "cdylib"]
17+
18+
[dependencies]
19+
oo7_rs = { package = "oo7", path = "../client", version = "0.6", default-features = false, features = ["async-std", "native_crypto"] }
20+
gobject-ffi = { git = "https://github.com/bilelmoussaoui/gobject-ffi", version = "0.1" }
21+
glib = "0.21"
22+
gio = "0.21"
23+
futures-util = "0.3"
24+

gobject/meson.build

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
project('oo7-gobject', ['c', 'rust'],
2+
version: '0.6.0',
3+
license: 'MIT',
4+
meson_version: '>= 1.7',
5+
)
6+
7+
prefix = get_option('prefix')
8+
libdir = get_option('libdir')
9+
includedir = get_option('includedir')
10+
11+
# Dependencies
12+
glib_dep = dependency('glib-2.0', version: '>= 2.56')
13+
gobject_dep = dependency('gobject-2.0', version: '>= 2.56')
14+
gio_dep = dependency('gio-2.0', version: '>= 2.56')
15+
16+
# Cargo build
17+
cargo = find_program('cargo')
18+
19+
cargo_options = ['--target-dir', meson.project_build_root()]
20+
21+
if get_option('buildtype') == 'release'
22+
cargo_options += ['--release']
23+
rust_target = 'release'
24+
else
25+
rust_target = 'debug'
26+
endif
27+
28+
# Build the Rust library
29+
rust_lib = custom_target(
30+
'cargo-build',
31+
build_by_default: true,
32+
build_always_stale: true,
33+
output: 'liboo7.so',
34+
console: true,
35+
install: true,
36+
install_dir: libdir,
37+
command: [
38+
cargo, 'build',
39+
cargo_options,
40+
'&&',
41+
'cp', rust_target / 'liboo7.so', '@OUTPUT@',
42+
]
43+
)
44+
45+
# Headers
46+
headers = [
47+
'src/oo7.h',
48+
]
49+
50+
install_headers(headers, subdir: 'oo7-1.0')
51+
52+
# pkg-config
53+
pkg = import('pkgconfig')
54+
pkg.generate(
55+
name: 'oo7-1.0',
56+
description: 'GObject bindings for oo7 - Linux Secret Service API',
57+
version: meson.project_version(),
58+
libraries: ['-L${libdir}', '-loo7'],
59+
requires: ['glib-2.0', 'gobject-2.0', 'gio-2.0'],
60+
subdirs: 'oo7-1.0',
61+
)
62+
63+
# Tests
64+
test_keyring = executable(
65+
'test-keyring',
66+
'tests/test_keyring.c',
67+
dependencies: [glib_dep, gobject_dep, gio_dep],
68+
link_with: rust_lib,
69+
include_directories: include_directories('src'),
70+
)
71+
72+
test('keyring', test_keyring)
73+

gobject/src/error.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
use gobject_ffi::{c_return_type, ffi_impl};
2+
3+
/// Error codes for the Oo7 error domain
4+
#[derive(Debug, Clone, Copy, PartialEq, Eq, glib::Enum, glib::ErrorDomain)]
5+
#[repr(i32)]
6+
#[enum_type(name = "Oo7Error")]
7+
#[error_domain(name = "oo7-error-quark")]
8+
pub enum Error {
9+
// File backend errors
10+
FileHeaderMismatch = 1,
11+
VersionMismatch = 2,
12+
NoData = 3,
13+
NoParentDir = 4,
14+
GVariantDeserialization = 5,
15+
SaltSizeMismatch = 6,
16+
WeakKey = 7,
17+
Io = 8,
18+
MacError = 9,
19+
ChecksumMismatch = 10,
20+
HashedAttributeMac = 11,
21+
NoDataDir = 12,
22+
TargetFileChanged = 13,
23+
Portal = 14,
24+
InvalidItemIndex = 15,
25+
Utf8 = 16,
26+
AlgorithmMismatch = 17,
27+
IncorrectSecret = 18,
28+
PartiallyCorruptedKeyring = 19,
29+
Crypto = 20,
30+
Locked = 21,
31+
32+
// DBus backend errors
33+
ZBus = 100,
34+
ServiceError = 101,
35+
Deleted = 102,
36+
Dismissed = 103,
37+
NotFound = 104,
38+
IsLocked = 105,
39+
NoSession = 106,
40+
NoSuchObject = 107,
41+
42+
// Generic/unknown error
43+
#[enum_value(name = "Unknown", nick = "unknown")]
44+
Unknown = 999,
45+
}
46+
47+
#[ffi_impl(prefix = "oo7", ty = "enum")]
48+
impl Error {
49+
#[c_return_type(u32, transfer=primitive)]
50+
fn quark() -> glib::Quark {
51+
<Error as glib::prelude::ErrorDomain>::domain()
52+
}
53+
}
54+
55+
/// Convert an oo7_rs::Error to a glib::Error with proper error codes and
56+
/// messages
57+
pub fn to_glib_error(error: oo7_rs::Error) -> glib::Error {
58+
match error {
59+
oo7_rs::Error::File(e) => file_error_to_glib(e),
60+
oo7_rs::Error::DBus(e) => dbus_error_to_glib(e),
61+
}
62+
}
63+
64+
fn file_error_to_glib(error: oo7_rs::file::Error) -> glib::Error {
65+
let (code, message) = match error {
66+
oo7_rs::file::Error::FileHeaderMismatch(_) => {
67+
(Error::FileHeaderMismatch, error.to_string())
68+
}
69+
oo7_rs::file::Error::VersionMismatch(_) => (Error::VersionMismatch, error.to_string()),
70+
oo7_rs::file::Error::NoData => (Error::NoData, error.to_string()),
71+
oo7_rs::file::Error::NoParentDir(_) => (Error::NoParentDir, error.to_string()),
72+
oo7_rs::file::Error::GVariantDeserialization(_) => {
73+
(Error::GVariantDeserialization, error.to_string())
74+
}
75+
oo7_rs::file::Error::SaltSizeMismatch(_, _) => (Error::SaltSizeMismatch, error.to_string()),
76+
oo7_rs::file::Error::WeakKey(_) => (Error::WeakKey, error.to_string()),
77+
oo7_rs::file::Error::Io(_) => (Error::Io, error.to_string()),
78+
oo7_rs::file::Error::MacError => (Error::MacError, error.to_string()),
79+
oo7_rs::file::Error::ChecksumMismatch => (Error::ChecksumMismatch, error.to_string()),
80+
oo7_rs::file::Error::HashedAttributeMac(_) => {
81+
(Error::HashedAttributeMac, error.to_string())
82+
}
83+
oo7_rs::file::Error::NoDataDir => (Error::NoDataDir, error.to_string()),
84+
oo7_rs::file::Error::TargetFileChanged(_) => (Error::TargetFileChanged, error.to_string()),
85+
oo7_rs::file::Error::Portal(_) => (Error::Portal, error.to_string()),
86+
oo7_rs::file::Error::InvalidItemIndex(_) => (Error::InvalidItemIndex, error.to_string()),
87+
oo7_rs::file::Error::Utf8(_) => (Error::Utf8, error.to_string()),
88+
oo7_rs::file::Error::AlgorithmMismatch(_) => (Error::AlgorithmMismatch, error.to_string()),
89+
oo7_rs::file::Error::IncorrectSecret => (Error::IncorrectSecret, error.to_string()),
90+
oo7_rs::file::Error::PartiallyCorruptedKeyring { .. } => {
91+
(Error::PartiallyCorruptedKeyring, error.to_string())
92+
}
93+
oo7_rs::file::Error::Crypto(_) => (Error::Crypto, error.to_string()),
94+
oo7_rs::file::Error::Locked => (Error::Locked, error.to_string()),
95+
};
96+
97+
glib::Error::new(code, &message)
98+
}
99+
100+
fn dbus_error_to_glib(error: oo7_rs::dbus::Error) -> glib::Error {
101+
use oo7_rs::dbus::ServiceError;
102+
103+
let (code, message) = match error {
104+
oo7_rs::dbus::Error::ZBus(_) => (Error::ZBus, error.to_string()),
105+
oo7_rs::dbus::Error::Service(ref service_err) => match service_err {
106+
ServiceError::ZBus(_) => (Error::ZBus, error.to_string()),
107+
ServiceError::IsLocked(_) => (Error::IsLocked, error.to_string()),
108+
ServiceError::NoSession(_) => (Error::NoSession, error.to_string()),
109+
ServiceError::NoSuchObject(_) => (Error::NoSuchObject, error.to_string()),
110+
},
111+
oo7_rs::dbus::Error::Deleted => (Error::Deleted, error.to_string()),
112+
oo7_rs::dbus::Error::Dismissed => (Error::Dismissed, error.to_string()),
113+
oo7_rs::dbus::Error::NotFound(_) => (Error::NotFound, error.to_string()),
114+
oo7_rs::dbus::Error::IO(_) => (Error::Io, error.to_string()),
115+
oo7_rs::dbus::Error::Crypto(_) => (Error::Crypto, error.to_string()),
116+
};
117+
118+
glib::Error::new(code, &message)
119+
}

gobject/src/ffi_wrappers.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use std::collections::HashMap;
2+
3+
use glib::translate::*;
4+
use gobject_ffi::FfiConvert;
5+
6+
#[derive(Clone, glib::Boxed)]
7+
#[boxed_type(name = "Oo7Attributes")]
8+
pub struct Attributes(pub(crate) HashMap<String, String>);
9+
10+
impl Attributes {
11+
pub fn into_inner(self) -> HashMap<String, String> {
12+
self.0
13+
}
14+
}
15+
16+
impl ToGlibPtr<'_, *mut glib::ffi::GHashTable> for Attributes {
17+
type Storage = HashMap<String, String>;
18+
19+
fn to_glib_none(&self) -> Stash<'_, *mut glib::ffi::GHashTable, Self> {
20+
let ptr = self.0.to_glib_full();
21+
Stash(ptr, self.0.clone())
22+
}
23+
24+
fn to_glib_full(&self) -> *mut glib::ffi::GHashTable {
25+
self.0.to_glib_full()
26+
}
27+
}
28+
29+
impl FromGlibPtrNone<*mut glib::ffi::GHashTable> for Attributes {
30+
unsafe fn from_glib_none(ptr: *mut glib::ffi::GHashTable) -> Self {
31+
let map = unsafe { HashMap::<String, String>::from_glib_none(ptr) };
32+
Self(map)
33+
}
34+
}
35+
36+
impl FfiConvert for Attributes {
37+
type CType = *mut glib::ffi::GHashTable;
38+
39+
unsafe fn from_c_borrowed(value: Self::CType) -> Self {
40+
unsafe { FromGlibPtrNone::from_glib_none(value) }
41+
}
42+
43+
fn to_c_owned(self) -> Self::CType {
44+
ToGlibPtr::to_glib_full(&self)
45+
}
46+
47+
fn c_error_value() -> Self::CType {
48+
std::ptr::null_mut()
49+
}
50+
}
51+
52+
#[derive(Clone, glib::Boxed)]
53+
#[boxed_type(name = "Oo7ItemVec")]
54+
pub struct ItemVec(pub(crate) std::sync::Arc<Vec<std::sync::Arc<oo7_rs::Item>>>);
55+
56+
impl ToGlibPtr<'_, *mut glib::ffi::GList> for ItemVec {
57+
type Storage = std::ptr::NonNull<glib::ffi::GList>;
58+
59+
fn to_glib_none(&self) -> Stash<'_, *mut glib::ffi::GList, Self> {
60+
let glist = items_vec_to_glist(&self.0);
61+
Stash(glist, std::ptr::NonNull::new(glist).unwrap())
62+
}
63+
64+
fn to_glib_full(&self) -> *mut glib::ffi::GList {
65+
items_vec_to_glist(&self.0)
66+
}
67+
}
68+
69+
fn items_vec_to_glist(
70+
items: &std::sync::Arc<Vec<std::sync::Arc<oo7_rs::Item>>>,
71+
) -> *mut glib::ffi::GList {
72+
let mut list: *mut glib::ffi::GList = std::ptr::null_mut();
73+
for item_arc in items.iter() {
74+
let gobject_item = crate::Item::from_arc(std::sync::Arc::clone(item_arc));
75+
let ptr: *mut crate::item::ffi::Item = gobject_item.into_glib_ptr();
76+
unsafe {
77+
list = glib::ffi::g_list_append(list, ptr as glib::ffi::gpointer);
78+
}
79+
}
80+
list
81+
}
82+
83+
impl FfiConvert for ItemVec {
84+
type CType = *mut glib::ffi::GList;
85+
86+
unsafe fn from_c_borrowed(_value: Self::CType) -> Self {
87+
unimplemented!("ItemVec::from_c_borrowed is not implemented")
88+
}
89+
90+
fn to_c_owned(self) -> Self::CType {
91+
ToGlibPtr::to_glib_full(&self)
92+
}
93+
94+
fn c_error_value() -> Self::CType {
95+
std::ptr::null_mut()
96+
}
97+
}

0 commit comments

Comments
 (0)