From: Olaf Wintermann Date: Sat, 20 Jun 2026 17:21:50 +0000 (+0200) Subject: begin rust bindings for libidav X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;p=note.git begin rust bindings for libidav --- diff --git a/Cargo.lock b/Cargo.lock index 6db192c..bcbe107 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -666,6 +666,13 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "dav-rs" +version = "0.1.0" +dependencies = [ + "libc", +] + [[package]] name = "der" version = "0.7.10" @@ -1515,6 +1522,7 @@ dependencies = [ name = "note" version = "0.1.0" dependencies = [ + "dav-rs", "entity", "migration", "sea-orm", diff --git a/Cargo.toml b/Cargo.toml index 4065e4a..4497b47 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "ui-rs", "ui-rs-derive", + "dav-rs", "application", "entity", "migration" diff --git a/application/Cargo.toml b/application/Cargo.toml index ed6f7a6..af0ace5 100644 --- a/application/Cargo.toml +++ b/application/Cargo.toml @@ -5,6 +5,7 @@ edition = "2024" [dependencies] ui-rs = { path = "../ui-rs" } +dav-rs = { path = "../dav-rs" } entity = { path = "../entity" } migration = { path = "../migration" } sea-orm = { version = "2.0.0-rc", features = [ "sqlx-sqlite", "sqlx-postgres", "runtime-tokio-native-tls", "macros" ] } diff --git a/dav-rs/Cargo.toml b/dav-rs/Cargo.toml new file mode 100644 index 0000000..05db057 --- /dev/null +++ b/dav-rs/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "dav-rs" +version = "0.1.0" +edition = "2024" + +[dependencies] +libc = "0.2" diff --git a/dav-rs/build.rs b/dav-rs/build.rs new file mode 100644 index 0000000..58d97f0 --- /dev/null +++ b/dav-rs/build.rs @@ -0,0 +1,71 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +use std::path::Path; +use std::fs; + +fn main() { + let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); + let lib_dir = Path::new(&manifest_dir).join("../build/lib"); + let config_mk = Path::new(&manifest_dir).join("../config.mk"); + + println!("cargo:rustc-link-search=native={}", lib_dir.display()); + println!("cargo:rustc-link-lib=static=uitk"); + println!("cargo:rustc-link-lib=static=ucx"); + + // read the toolkit linker flags from the config.mk file + let content = fs::read_to_string(&config_mk) + .expect(&format!("Failed to read {}", config_mk.display())); + let mut tokens = vec![]; + for line in content.lines() { + if line.starts_with("TK_LDFLAGS += ") || line.starts_with("DAV_LDFLAGS = ") { + tokens.extend(line.split_whitespace().skip(2)); // skip "DAV_LDFLAGS =" + } + } + + let mut iter = tokens.iter(); + while let Some(token) = iter.next() { + if let Some(lib) = token.strip_prefix("-l") { + println!("cargo:rustc-link-lib={}", lib); + } else if token.starts_with("-L") { + let path = &token[2..]; + println!("cargo:rustc-link-search=native={}", path); + } else if token.starts_with("-R") { + let path = &token[2..]; + println!("cargo:rustc-link-arg=-Wl,-rpath,{}", path); + } else if token == &"-framework" { + // The next token is the framework name + if let Some(framework) = iter.next() { + println!("cargo:rustc-link-lib=framework={}", framework); + } + } else { + println!("cargo:rustc-link-arg={}", token); + } + } + +} diff --git a/dav-rs/src/dav/context.rs b/dav-rs/src/dav/context.rs new file mode 100644 index 0000000..5090278 --- /dev/null +++ b/dav-rs/src/dav/context.rs @@ -0,0 +1,68 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#![allow(dead_code)] + +use crate::dav::ffi; + +pub struct DavContext { + pub ptr: *mut ffi::DavContext +} + +impl DavContext { + pub fn new() -> DavContext { + unsafe { + DavContext { ptr: dav_context_new() } + } + } +} + +impl Drop for DavContext { + fn drop(&mut self) { + unsafe { + dav_context_unref(self.ptr); + } + } +} + +impl Clone for DavContext { + fn clone(&self) -> Self { + unsafe { + dav_context_ref(self.ptr); + } + DavContext { ptr: self.ptr } + } +} + + + +unsafe extern "C" { + fn dav_context_new() -> *mut ffi::DavContext; + + fn dav_context_ref(ctx: *mut ffi::DavContext); + fn dav_context_unref(ctx: *mut ffi::DavContext); +} \ No newline at end of file diff --git a/dav-rs/src/dav/ffi.rs b/dav-rs/src/dav/ffi.rs new file mode 100644 index 0000000..93279af --- /dev/null +++ b/dav-rs/src/dav/ffi.rs @@ -0,0 +1,65 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +use std::ffi::{c_char, c_int, c_void}; +use libc::time_t; + +#[repr(C)] +pub struct DavContext { + _private: [u8; 0], +} + +#[repr(C)] +pub struct DavSession { + _private: [u8; 0], +} + +#[repr(C)] +pub struct DavResource { + pub session: *mut DavSession, + pub prev: *mut DavResource, + pub next: *mut DavResource, + pub parent: *mut DavResource, + pub children: *mut DavResource, + + pub name: *mut c_char, + pub path: *mut c_char, + pub href: *mut c_char, + + pub contentlength: u64, + + pub contenttype: *mut c_char, + + pub creationdate: time_t, + pub lastmodified: time_t, + + pub data: *mut c_void, + + pub iscollection: c_int, + pub exists: c_int, +} diff --git a/dav-rs/src/dav/mod.rs b/dav-rs/src/dav/mod.rs new file mode 100644 index 0000000..19d865a --- /dev/null +++ b/dav-rs/src/dav/mod.rs @@ -0,0 +1,32 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +mod context; +mod ffi; +mod session; +mod resource; \ No newline at end of file diff --git a/dav-rs/src/dav/resource.rs b/dav-rs/src/dav/resource.rs new file mode 100644 index 0000000..9f58871 --- /dev/null +++ b/dav-rs/src/dav/resource.rs @@ -0,0 +1,86 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#![allow(dead_code)] + +use std::ffi::{c_char, c_int, CString}; +use crate::dav::context::DavContext; +use crate::dav::ffi; +use crate::dav::session::Session; + +pub struct Resource { + pub ptr: *mut ffi::DavResource, +} + +impl Drop for Resource { + fn drop(&mut self) { + unsafe { + dav_resource_free_all(self.ptr); + } + } +} + +impl Resource { + pub fn create(&self) -> bool { + unsafe { + dav_resource_create(self.ptr) != 0 + } + } + + pub fn delete(&self) -> bool { + unsafe { + dav_resource_delete(self.ptr) != 0 + } + } + + pub fn exists(&self) -> bool { + unsafe { + dav_resource_exists(self.ptr) != 0 + } + } +} + +impl Session { + pub fn new_resource(&self, path: &str) -> Resource { + let cstr = CString::new(path).unwrap(); + unsafe { + Resource { + ptr: dav_resource_new(self.ptr, cstr.as_ptr()) + } + } + } +} + +unsafe extern "C" { + fn dav_resource_new(sn: *mut ffi::DavSession, path: *const c_char) -> *mut ffi::DavResource; + fn dav_resource_new_child(sn: *mut ffi::DavSession, parent: *mut ffi::DavResource, name: *const c_char) -> *mut ffi::DavResource; + fn dav_resource_free_all(res: *mut ffi::DavResource); + + fn dav_resource_create(res: *mut ffi::DavResource) -> c_int; + fn dav_resource_delete(res: *mut ffi::DavResource) -> c_int; + fn dav_resource_exists(res: *mut ffi::DavResource) -> c_int; +} \ No newline at end of file diff --git a/dav-rs/src/dav/session.rs b/dav-rs/src/dav/session.rs new file mode 100644 index 0000000..f63c41e --- /dev/null +++ b/dav-rs/src/dav/session.rs @@ -0,0 +1,91 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#![allow(dead_code)] + +use std::ffi::{c_char, CString}; +use crate::dav::context::DavContext; +use crate::dav::ffi; + +pub struct Session { + pub ptr: *mut ffi::DavSession +} + +impl Drop for Session { + fn drop(&mut self) { + unsafe { + dav_session_unref(self.ptr); + } + } +} + +impl Clone for Session { + fn clone(&self) -> Self { + unsafe { + Session { + ptr: dav_session_clone(self.ptr) + } + } + } +} + +impl Session { + pub fn set_auth(&self, user: &str, password: &str) { + let user_cstr = CString::new(user).unwrap(); + let password_cstr = CString::new(password).unwrap(); + unsafe { + dav_session_set_auth(self.ptr, user_cstr.as_ptr(), password_cstr.as_ptr()); + } + } +} + + +impl DavContext { + pub fn create_session(&self, base_url: &str) -> Session { + let cstr = CString::new(base_url).unwrap(); + unsafe { + Session { + ptr: dav_session_new(self.ptr, cstr.as_ptr()) + } + } + } + + pub fn create_session_with_auth(&self, base_url: &str, user: &str, password: &str) -> Session { + let sn = self.create_session(base_url); + sn.set_auth(user, password); + sn + } +} + + +unsafe extern "C" { + fn dav_session_new(ctx: *mut ffi::DavContext, base_url: *const libc::c_char) -> *mut ffi::DavSession; + //fn dav_session_ref(sn: *mut ffi::DavSession); + fn dav_session_unref(sn: *mut ffi::DavSession); + fn dav_session_clone(sn: *mut ffi::DavSession) -> *mut ffi::DavSession; + fn dav_session_set_auth(sn: *mut ffi::DavSession, user: *const c_char, password: *const c_char); +} \ No newline at end of file diff --git a/dav-rs/src/lib.rs b/dav-rs/src/lib.rs new file mode 100644 index 0000000..e8f9469 --- /dev/null +++ b/dav-rs/src/lib.rs @@ -0,0 +1,31 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#![allow(unused_imports)] + +pub mod dav; \ No newline at end of file diff --git a/libidav/atomic.h b/libidav/atomic.h new file mode 100644 index 0000000..8f63d46 --- /dev/null +++ b/libidav/atomic.h @@ -0,0 +1,57 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DAV_ATOMIC_H +#define DAV_ATOMIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__gnu_linux__) || defined(OSX) || defined(BSD) + +#define dav_atomic_inc32(intptr) __sync_fetch_and_add(intptr, 1) +#define dav_atomic_dec32(intptr) (__sync_fetch_and_sub(intptr, 1) - 1) + +#else +// use atomic.h +#include + +#define dav_atomic_inc32(intptr) atomic_inc_32_nv(intptr) +#define dav_atomic_dec32(intptr) atomic_dec_32_nv(intptr) +// TODO + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* DAV_ATOMIC_H */ + diff --git a/libidav/resource.c b/libidav/resource.c index bf57861..3b55213 100644 --- a/libidav/resource.c +++ b/libidav/resource.c @@ -761,7 +761,7 @@ void dav_set_content(DavResource *res, void *stream, dav_read_func read_func, da data->length = 0; } -void dav_set_content_data(DavResource *res, char *content, size_t length) { +void dav_set_content_data(DavResource *res, const char *content, size_t length) { DavSession *sn = res->session; DavResourceData *data = res->data; data->content = dav_session_malloc(sn, length); diff --git a/libidav/session.c b/libidav/session.c index bf66e79..e922593 100644 --- a/libidav/session.c +++ b/libidav/session.c @@ -38,6 +38,7 @@ #include "session.h" #include "resource.h" #include "methods.h" +#include "atomic.h" DavSession* dav_session_new(DavContext *context, char *base_url) { if(!base_url) { @@ -95,6 +96,9 @@ DavSession* dav_session_new(DavContext *context, char *base_url) { // add to context dav_context_add_session(context, sn); sn->context = context; + dav_context_ref(context); + + sn->ref = 1; return sn; } @@ -138,10 +142,23 @@ DavSession* dav_session_clone(DavSession *sn) { // add to context dav_context_add_session(sn->context, newsn); newsn->context = sn->context; + dav_context_ref(sn->context); + + newsn->ref = 1; return newsn; } +void dav_session_ref(DavSession *sn) { + dav_atomic_inc32(&sn->ref); +} + +void dav_session_unref(DavSession *sn) { + if(dav_atomic_dec32(&sn->ref) == 0) { + dav_session_destroy(sn); + } +} + void dav_session_set_auth(DavSession *sn, const char *user, const char *password) { if(user && password) { dav_session_set_auth_s(sn, cx_str(user), cx_str(password)); @@ -344,15 +361,19 @@ void dav_session_set_errstr(DavSession *sn, const char *str) { void dav_session_destroy(DavSession *sn) { // remove session from context - if (dav_context_remove_session(sn->context, sn)) { + DavContext *ctx = sn->context; + dav_context_ref(ctx); + if (dav_context_remove_session(ctx, sn)) { fprintf(stderr, "Error: session not found in ctx->sessions\n"); dav_session_destructor(sn); } + dav_context_unref(ctx); } void dav_session_destructor(DavSession *sn) { cxMempoolFree(sn->mp); curl_easy_cleanup(sn->handle); + dav_context_unref(sn->context); free(sn); } diff --git a/libidav/webdav.c b/libidav/webdav.c index 0a4afed..a7dc580 100644 --- a/libidav/webdav.c +++ b/libidav/webdav.c @@ -41,6 +41,7 @@ #include #include "davqlparser.h" #include "davqlexec.h" +#include "atomic.h" DavContext* dav_context_new(void) { @@ -94,10 +95,22 @@ DavContext* dav_context_new(void) { dav_context_destroy(context); return NULL; } + + context->ref = 1; return context; } +void dav_context_ref(DavContext *ctx) { + dav_atomic_inc32(&ctx->ref); +} + +void dav_context_unref(DavContext *ctx) { + if(dav_atomic_dec32(&ctx->ref) == 0) { + dav_context_destroy(ctx); + } +} + void dav_context_destroy(DavContext *ctx) { // destroy all sessions assoziated with this context // ctx->sessions destructor must be dav_session_destructor diff --git a/libidav/webdav.h b/libidav/webdav.h index 3bd60ac..e1efa31 100644 --- a/libidav/webdav.h +++ b/libidav/webdav.h @@ -189,17 +189,20 @@ struct DavSession { void(*get_progress)(DavResource *res, int64_t total, int64_t now, void *userdata); void(*put_progress)(DavResource *res, int64_t total, int64_t now, void *userdata); void *progress_userdata; + + unsigned int ref; }; struct DavContext { - CxMap *namespaces; - CxMap *namespaceinfo; - CxMap *keys; - CxList *sessions; - DavProxy *http_proxy; - DavProxy *https_proxy; - DAV_MUTEX mutex; - DavBool mtsafe; + CxMap *namespaces; + CxMap *namespaceinfo; + CxMap *keys; + CxList *sessions; + DavProxy *http_proxy; + DavProxy *https_proxy; + DAV_MUTEX mutex; + DavBool mtsafe; + unsigned int ref; }; struct DavProxy { @@ -264,6 +267,8 @@ struct DavXmlAttr { }; DavContext* dav_context_new(void); +void dav_context_ref(DavContext *ctx); +void dav_context_unref(DavContext *ctx); void dav_context_destroy(DavContext *ctx); void dav_context_set_mtsafe(DavContext *ctx, DavBool enable); @@ -290,6 +295,8 @@ DavSession* dav_session_new_auth( char *user, char *password); DavSession* dav_session_clone(DavSession *sn); +void dav_session_ref(DavSession *sn); +void dav_session_unref(DavSession *sn); void dav_session_set_auth(DavSession *sn, const char *user, const char *password); void dav_session_set_auth_s(DavSession *sn, cxstring user, cxstring password); void dav_session_set_baseurl(DavSession *sn, char *base_url); @@ -371,7 +378,7 @@ void dav_remove_encrypted_property_ns(DavResource *res, char *ns, char *name); DavPropName* dav_get_property_names(DavResource *res, size_t *count); void dav_set_content(DavResource *res, void *stream, dav_read_func read_func, dav_seek_func seek_func); -void dav_set_content_data(DavResource *res, char *content, size_t length); +void dav_set_content_data(DavResource *res, const char *content, size_t length); void dav_set_content_length(DavResource *res, size_t length); int dav_load(DavResource *res);