Skip to content

Commit 74299a1

Browse files
wip: gobject
1 parent b1ae93c commit 74299a1

11 files changed

Lines changed: 1631 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: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
use glib::{
2+
Quark,
3+
error::ErrorDomain,
4+
translate::{FromGlib, IntoGlib, TryFromGlib},
5+
};
6+
7+
/// Error codes for the Oo7 error domain
8+
#[repr(i32)]
9+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10+
pub enum Oo7ErrorCode {
11+
// File backend errors
12+
FileHeaderMismatch = 1,
13+
VersionMismatch = 2,
14+
NoData = 3,
15+
NoParentDir = 4,
16+
GVariantDeserialization = 5,
17+
SaltSizeMismatch = 6,
18+
WeakKey = 7,
19+
Io = 8,
20+
MacError = 9,
21+
ChecksumMismatch = 10,
22+
HashedAttributeMac = 11,
23+
NoDataDir = 12,
24+
TargetFileChanged = 13,
25+
Portal = 14,
26+
InvalidItemIndex = 15,
27+
Utf8 = 16,
28+
AlgorithmMismatch = 17,
29+
IncorrectSecret = 18,
30+
PartiallyCorruptedKeyring = 19,
31+
Crypto = 20,
32+
Locked = 21,
33+
34+
// DBus backend errors
35+
ZBus = 100,
36+
ServiceError = 101,
37+
Deleted = 102,
38+
Dismissed = 103,
39+
NotFound = 104,
40+
IsLocked = 105,
41+
NoSession = 106,
42+
NoSuchObject = 107,
43+
44+
// Generic/unknown error
45+
Unknown = 999,
46+
}
47+
48+
impl IntoGlib for Oo7ErrorCode {
49+
type GlibType = i32;
50+
51+
fn into_glib(self) -> i32 {
52+
self as i32
53+
}
54+
}
55+
56+
impl TryFromGlib<i32> for Oo7ErrorCode {
57+
type Error = glib::value::ValueTypeMismatchError;
58+
59+
unsafe fn try_from_glib(value: i32) -> Result<Self, Self::Error> {
60+
match value {
61+
1 => Ok(Self::FileHeaderMismatch),
62+
2 => Ok(Self::VersionMismatch),
63+
3 => Ok(Self::NoData),
64+
4 => Ok(Self::NoParentDir),
65+
5 => Ok(Self::GVariantDeserialization),
66+
6 => Ok(Self::SaltSizeMismatch),
67+
7 => Ok(Self::WeakKey),
68+
8 => Ok(Self::Io),
69+
9 => Ok(Self::MacError),
70+
10 => Ok(Self::ChecksumMismatch),
71+
11 => Ok(Self::HashedAttributeMac),
72+
12 => Ok(Self::NoDataDir),
73+
13 => Ok(Self::TargetFileChanged),
74+
14 => Ok(Self::Portal),
75+
15 => Ok(Self::InvalidItemIndex),
76+
16 => Ok(Self::Utf8),
77+
17 => Ok(Self::AlgorithmMismatch),
78+
18 => Ok(Self::IncorrectSecret),
79+
19 => Ok(Self::PartiallyCorruptedKeyring),
80+
20 => Ok(Self::Crypto),
81+
21 => Ok(Self::Locked),
82+
100 => Ok(Self::ZBus),
83+
101 => Ok(Self::ServiceError),
84+
102 => Ok(Self::Deleted),
85+
103 => Ok(Self::Dismissed),
86+
104 => Ok(Self::NotFound),
87+
105 => Ok(Self::IsLocked),
88+
106 => Ok(Self::NoSession),
89+
107 => Ok(Self::NoSuchObject),
90+
999 => Ok(Self::Unknown),
91+
_ => Ok(Self::Unknown),
92+
}
93+
}
94+
}
95+
96+
impl ErrorDomain for Oo7ErrorCode {
97+
fn domain() -> Quark {
98+
unsafe { Quark::from_glib(oo7_error_quark()) }
99+
}
100+
101+
fn code(self) -> i32 {
102+
self.into_glib()
103+
}
104+
105+
fn from(code: i32) -> Option<Self>
106+
where
107+
Self: Sized,
108+
{
109+
unsafe { Self::try_from_glib(code).ok() }
110+
}
111+
}
112+
113+
/// Custom GError domain for oo7 errors
114+
#[unsafe(no_mangle)]
115+
pub extern "C" fn oo7_error_quark() -> glib::ffi::GQuark {
116+
Quark::from_str("oo7-error-quark").into_glib()
117+
}
118+
119+
/// Convert an oo7_rs::Error to a glib::Error with proper error codes and
120+
/// messages
121+
pub fn to_glib_error(error: oo7_rs::Error) -> glib::Error {
122+
match error {
123+
oo7_rs::Error::File(e) => file_error_to_glib(e),
124+
oo7_rs::Error::DBus(e) => dbus_error_to_glib(e),
125+
}
126+
}
127+
128+
fn file_error_to_glib(error: oo7_rs::file::Error) -> glib::Error {
129+
use oo7_rs::file::Error;
130+
131+
let (code, message) = match error {
132+
Error::FileHeaderMismatch(_) => (Oo7ErrorCode::FileHeaderMismatch, error.to_string()),
133+
Error::VersionMismatch(_) => (Oo7ErrorCode::VersionMismatch, error.to_string()),
134+
Error::NoData => (Oo7ErrorCode::NoData, error.to_string()),
135+
Error::NoParentDir(_) => (Oo7ErrorCode::NoParentDir, error.to_string()),
136+
Error::GVariantDeserialization(_) => {
137+
(Oo7ErrorCode::GVariantDeserialization, error.to_string())
138+
}
139+
Error::SaltSizeMismatch(_, _) => (Oo7ErrorCode::SaltSizeMismatch, error.to_string()),
140+
Error::WeakKey(_) => (Oo7ErrorCode::WeakKey, error.to_string()),
141+
Error::Io(_) => (Oo7ErrorCode::Io, error.to_string()),
142+
Error::MacError => (Oo7ErrorCode::MacError, error.to_string()),
143+
Error::ChecksumMismatch => (Oo7ErrorCode::ChecksumMismatch, error.to_string()),
144+
Error::HashedAttributeMac(_) => (Oo7ErrorCode::HashedAttributeMac, error.to_string()),
145+
Error::NoDataDir => (Oo7ErrorCode::NoDataDir, error.to_string()),
146+
Error::TargetFileChanged(_) => (Oo7ErrorCode::TargetFileChanged, error.to_string()),
147+
Error::Portal(_) => (Oo7ErrorCode::Portal, error.to_string()),
148+
Error::InvalidItemIndex(_) => (Oo7ErrorCode::InvalidItemIndex, error.to_string()),
149+
Error::Utf8(_) => (Oo7ErrorCode::Utf8, error.to_string()),
150+
Error::AlgorithmMismatch(_) => (Oo7ErrorCode::AlgorithmMismatch, error.to_string()),
151+
Error::IncorrectSecret => (Oo7ErrorCode::IncorrectSecret, error.to_string()),
152+
Error::PartiallyCorruptedKeyring { .. } => {
153+
(Oo7ErrorCode::PartiallyCorruptedKeyring, error.to_string())
154+
}
155+
Error::Crypto(_) => (Oo7ErrorCode::Crypto, error.to_string()),
156+
Error::Locked => (Oo7ErrorCode::Locked, error.to_string()),
157+
};
158+
159+
glib::Error::new(code, &message)
160+
}
161+
162+
fn dbus_error_to_glib(error: oo7_rs::dbus::Error) -> glib::Error {
163+
use oo7_rs::dbus::{Error, ServiceError};
164+
165+
let (code, message) = match error {
166+
Error::ZBus(_) => (Oo7ErrorCode::ZBus, error.to_string()),
167+
Error::Service(ref service_err) => match service_err {
168+
ServiceError::ZBus(_) => (Oo7ErrorCode::ZBus, error.to_string()),
169+
ServiceError::IsLocked(_) => (Oo7ErrorCode::IsLocked, error.to_string()),
170+
ServiceError::NoSession(_) => (Oo7ErrorCode::NoSession, error.to_string()),
171+
ServiceError::NoSuchObject(_) => (Oo7ErrorCode::NoSuchObject, error.to_string()),
172+
},
173+
Error::Deleted => (Oo7ErrorCode::Deleted, error.to_string()),
174+
Error::Dismissed => (Oo7ErrorCode::Dismissed, error.to_string()),
175+
Error::NotFound(_) => (Oo7ErrorCode::NotFound, error.to_string()),
176+
Error::IO(_) => (Oo7ErrorCode::Io, error.to_string()),
177+
Error::Crypto(_) => (Oo7ErrorCode::Crypto, error.to_string()),
178+
};
179+
180+
glib::Error::new(code, &message)
181+
}

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)