From 9593fd370eb9a50b06bc8b36e71649ffd6b3baaf Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 20 Sep 2023 15:17:04 -0400 Subject: [PATCH] Demonstrate Rust code from sysroot This is a demo/prototype for starting to add new Rust code only for `OstreeSysroot`. https://github.com/ostreedev/ostree/issues/2427#issuecomment-1728210940 --- Cargo.toml | 2 +- Makefile-sysroot-rs.am | 23 ++++++++++++++++++++++ Makefile.am | 1 + src/libostree/ostree-sysroot.c | 35 +++++++++++++++++++++++++++++++--- src/sysroot-rs/Cargo.toml | 20 +++++++++++++++++++ src/sysroot-rs/src/lib.rs | 17 +++++++++++++++++ 6 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 Makefile-sysroot-rs.am create mode 100644 src/sysroot-rs/Cargo.toml create mode 100644 src/sysroot-rs/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 4633410ed5..4462f55613 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ name = "integration" path = "rust-bindings/tests/tests.rs" [workspace] -members = [".", "rust-bindings/sys"] +members = [".", "src/sysroot-rs", "rust-bindings/sys"] [dependencies] base64 = "0.20.0" diff --git a/Makefile-sysroot-rs.am b/Makefile-sysroot-rs.am new file mode 100644 index 0000000000..8a48152685 --- /dev/null +++ b/Makefile-sysroot-rs.am @@ -0,0 +1,23 @@ +# Makefile for Rust lib +# +# SPDX-License-Identifier: LGPL-2.0+ +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library. If not, see . + + +target/release/libostreesysrs.so: src/sysroot-rs/src/lib.rs + cargo build --release --workspace + +libostreesysrs_DATA = target/release/libostreesysrs.so +libostreesysrsdir = $(pkglibexecdir) diff --git a/Makefile.am b/Makefile.am index 19abc0c1e1..ba9db0d759 100644 --- a/Makefile.am +++ b/Makefile.am @@ -134,6 +134,7 @@ include Makefile-switchroot.am if BUILDOPT_FUSE include src/rofiles-fuse/Makefile-inc.am endif +include Makefile-sysroot-rs.am include Makefile-tests.am include Makefile-boot.am include Makefile-man.am diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 91b63f945a..498a17e7d8 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -21,6 +21,7 @@ #include "config.h" #include "otutil.h" +#include #include #include #include @@ -76,6 +77,29 @@ enum G_DEFINE_TYPE (OstreeSysroot, ostree_sysroot, G_TYPE_OBJECT) +static void * +load_sysroot_rs (void) +{ + static gssize initialized = 0; + static void *sysrootrs = NULL; + if (g_once_init_enter (&initialized)) + { + const char *uninstalled = g_getenv ("OSTREE_UNINSTALLED"); + g_autofree char *path = NULL; + if (uninstalled) + path = g_strdup_printf ("%s/target/release/libostreesysrs.so", uninstalled); + else + path = g_strdup_printf ("%s/libostreesysrs.so", PKGLIBEXECDIR); + sysrootrs = dlopen (path, RTLD_NOW); + if (sysrootrs == NULL) + { + errx (EXIT_FAILURE, "failed to initialize libostreesysrs.so: %s", dlerror ()); + } + g_once_init_leave (&initialized, 1); + } + return sysrootrs; +} + static void ostree_sysroot_finalize (GObject *object) { @@ -447,11 +471,16 @@ ostree_sysroot_is_booted (OstreeSysroot *self) gboolean _ostree_sysroot_bump_mtime (OstreeSysroot *self, GError **error) { + void *lib = load_sysroot_rs (); + int (*f) (int fd) = dlsym (lib, "_ostreesys_bump_mtime"); + g_assert (f); + /* Allow other systems to monitor for changes */ - if (utimensat (self->sysroot_fd, "ostree/deploy", NULL, 0) < 0) + int r = f (self->sysroot_fd); + if (r < 0) { - glnx_set_prefix_error_from_errno (error, "%s", "futimens"); - return FALSE; + errno = r; + return glnx_throw_errno_prefix (error, "futimens"); } return TRUE; } diff --git a/src/sysroot-rs/Cargo.toml b/src/sysroot-rs/Cargo.toml new file mode 100644 index 0000000000..35345a9356 --- /dev/null +++ b/src/sysroot-rs/Cargo.toml @@ -0,0 +1,20 @@ +[package] +description = "Internal Rust sysroot code" +edition = "2021" +keywords = ["ostree", "libostree"] +license = "MIT" +name = "ostreesysrs" +readme = "rust-bindings/README.md" +repository = "https://github.com/ostreedev/ostree" +rust-version = "1.70.0" +version = "0.0.0" +publish = false + +[lib] +name = "ostreesysrs" +crate-type = ["cdylib"] + +[dependencies] +ostree = { package = "ostree", path = "../..", version = "0.19", features = ["v2022_6"] } +libc = "0.2" +rustix = { version = "0.38", features = ["fs"] } diff --git a/src/sysroot-rs/src/lib.rs b/src/sysroot-rs/src/lib.rs new file mode 100644 index 0000000000..5c03e9d98d --- /dev/null +++ b/src/sysroot-rs/src/lib.rs @@ -0,0 +1,17 @@ +#[no_mangle] +pub extern "C" fn _ostreesys_bump_mtime(fd: libc::c_int) -> libc::c_int { + let fd = unsafe { std::os::fd::BorrowedFd::borrow_raw(fd) }; + let now = rustix::fs::Timespec { + tv_sec: 0, + tv_nsec: rustix::fs::UTIME_NOW, + }; + let ts = rustix::fs::Timestamps { + last_access: now.clone(), + last_modification: now.clone(), + }; + if let Err(e) = rustix::fs::utimensat(fd, "ostree/deploy", &ts, rustix::fs::AtFlags::empty()) { + e.raw_os_error().into() + } else { + 0 + } +}