diff --git a/apps/ll-driver-detect/src/nvidia_driver_detector.cpp b/apps/ll-driver-detect/src/nvidia_driver_detector.cpp index 46e704977..0ee17f9fc 100644 --- a/apps/ll-driver-detect/src/nvidia_driver_detector.cpp +++ b/apps/ll-driver-detect/src/nvidia_driver_detector.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2025 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -82,7 +82,9 @@ NVIDIADriverDetector::getPackageInfoFromRemoteRepo(const std::string &packageNam LINGLONG_TRACE("Check if NVIDIA driver package exists in repository"); - GraphicsDriverInfo driverInfo{ getDriverIdentify(), packageName }; + GraphicsDriverInfo driverInfo; + driverInfo.identify = getDriverIdentify(); + driverInfo.packageName = packageName; // Execute ll-cli search command to check driver package existence auto ret = linglong::utils::Cmd("ll-cli").exec({ "--json", "search", packageName }); if (!ret) { @@ -192,7 +194,9 @@ NVIDIADriverDetector::getInstalledGraphicsDriverInfo(const std::string &packageN LINGLONG_TRACE("Get installed NVIDIA graphics driver info"); - GraphicsDriverInfo driverInfo{ getDriverIdentify(), packageName }; + GraphicsDriverInfo driverInfo; + driverInfo.identify = getDriverIdentify(); + driverInfo.packageName = packageName; auto listResult = linglong::utils::Cmd("ll-cli").exec({ "--json", "list", "--type=extension" }); if (!listResult) { diff --git a/libs/linglong/CMakeLists.txt b/libs/linglong/CMakeLists.txt index 091f191ee..8a25eb20f 100644 --- a/libs/linglong/CMakeLists.txt +++ b/libs/linglong/CMakeLists.txt @@ -107,6 +107,8 @@ pfl_add_library( src/linglong/runtime/container_builder.h src/linglong/runtime/container.cpp src/linglong/runtime/container.h + src/linglong/runtime/layer.cpp + src/linglong/runtime/layer.h src/linglong/runtime/overlayfs_driver.cpp src/linglong/runtime/overlayfs_driver.h src/linglong/runtime/run_context.cpp diff --git a/libs/linglong/src/linglong/cli/cli.cpp b/libs/linglong/src/linglong/cli/cli.cpp index 96a793803..0e9b449d8 100644 --- a/libs/linglong/src/linglong/cli/cli.cpp +++ b/libs/linglong/src/linglong/cli/cli.cpp @@ -29,7 +29,6 @@ #include "linglong/common/dir.h" #include "linglong/common/error.h" #include "linglong/common/strings.h" -#include "linglong/oci-cfg-generators/container_cfg_builder.h" #include "linglong/package/layer_file.h" #include "linglong/package/reference.h" #include "linglong/repo/config.h" @@ -42,7 +41,6 @@ #include "linglong/utils/gettext.h" #include "linglong/utils/namespace.h" #include "linglong/utils/runtime_config.h" -#include "linglong/utils/xdg/directory.h" #include "linglong/utils/xdp.h" #include "ocppi/runtime/ExecOption.hpp" #include "ocppi/runtime/RunOption.hpp" diff --git a/libs/linglong/src/linglong/cli/cli.h b/libs/linglong/src/linglong/cli/cli.h index 22aac9c8b..d737f11b8 100644 --- a/libs/linglong/src/linglong/cli/cli.h +++ b/libs/linglong/src/linglong/cli/cli.h @@ -10,7 +10,6 @@ #include "linglong/api/dbus/v1/task.h" #include "linglong/api/types/v1/CommonOptions.hpp" #include "linglong/api/types/v1/PackageInfoDisplay.hpp" -#include "linglong/api/types/v1/RepositoryCacheLayersItem.hpp" #include "linglong/cli/interactive_notifier.h" #include "linglong/cli/printer.h" #include "linglong/common/serialize/json.h" diff --git a/libs/linglong/src/linglong/package_manager/package_task.cpp b/libs/linglong/src/linglong/package_manager/package_task.cpp index a2cfb27ea..f7ba38706 100644 --- a/libs/linglong/src/linglong/package_manager/package_task.cpp +++ b/libs/linglong/src/linglong/package_manager/package_task.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -15,8 +15,6 @@ #include -const auto TASK_DONE = 100; - namespace linglong::service { PackageTask::PackageTask(std::function job, QObject *parent) diff --git a/libs/linglong/src/linglong/repo/ostree_repo.cpp b/libs/linglong/src/linglong/repo/ostree_repo.cpp index f995c73f8..14a557049 100644 --- a/libs/linglong/src/linglong/repo/ostree_repo.cpp +++ b/libs/linglong/src/linglong/repo/ostree_repo.cpp @@ -1352,7 +1352,7 @@ OSTreeRepo::getRefStatistics(const RefMetaData &meta) const noexcept } g_clear_error(&gErr); - RefStatistics stat = { 0 }; + RefStatistics stat{}; #if OSTREE_CHECK_VERSION(2020, 1) g_autoptr(GPtrArray) sizes = NULL; @@ -2100,12 +2100,12 @@ utils::error::Result OSTreeRepo::exportDir(const std::string &appID, && common::strings::ends_with(target_path.string(), ".desktop")) { auto desktopExists = false; // 如果要导出的desktop已存在,则覆盖导出(无论是在default还是overlay中),避免桌面和任务栏的快捷方式失效 - const std::string appDirs[] = { oldAppDir, newAppDir }; + const std::array appDirs{ oldAppDir, newAppDir }; for (const auto &appDir : appDirs) { // 如果目标文件存在,删除再导出 - std::filesystem::path linkpath = + const std::filesystem::path linkpath = target_path.string().replace(0, oldAppDir.string().length(), appDir); - auto status = std::filesystem::symlink_status(linkpath, ec); + std::ignore = std::filesystem::symlink_status(linkpath, ec); if (!ec) { desktopExists = true; auto target = source_path.lexically_relative(linkpath.parent_path()); diff --git a/libs/linglong/src/linglong/runtime/container.cpp b/libs/linglong/src/linglong/runtime/container.cpp index b6f355808..759d58617 100644 --- a/libs/linglong/src/linglong/runtime/container.cpp +++ b/libs/linglong/src/linglong/runtime/container.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -143,10 +144,9 @@ auto ContainerContext::create(RunContext &context, CreateOptions options) } } - auto containerContext = - std::unique_ptr{ new ContainerContext(std::move(containerID), - std::move(*bundleDir), - std::move(options.appCache)) }; + auto containerContext = std::make_unique(containerID, + std::move(*bundleDir), + std::move(options.appCache)); return containerContext; } diff --git a/libs/linglong/src/linglong/runtime/container.h b/libs/linglong/src/linglong/runtime/container.h index c1f9de83c..e655aca97 100644 --- a/libs/linglong/src/linglong/runtime/container.h +++ b/libs/linglong/src/linglong/runtime/container.h @@ -51,7 +51,7 @@ class ContainerContext [[nodiscard]] auto getBundleDir() const -> const std::filesystem::path &; [[nodiscard]] auto getContainerCache() const -> const std::optional &; void addSecurityContext(std::unique_ptr securityContext); - auto setupOverlayFS(RunContext &context, bool readOnly) -> utils::error::Result; + auto setupOverlayFS(RunContext &context, bool persistent) -> utils::error::Result; auto genLdConf(const std::string &ldConf, bool overlayEnabled) -> utils::error::Result; private: diff --git a/libs/linglong/src/linglong/runtime/container_builder.cpp b/libs/linglong/src/linglong/runtime/container_builder.cpp index c7a3b18d2..a3dcb4026 100644 --- a/libs/linglong/src/linglong/runtime/container_builder.cpp +++ b/libs/linglong/src/linglong/runtime/container_builder.cpp @@ -62,7 +62,8 @@ auto getXDPDocumentsMountPoint() noexcept -> utils::error::Result()) { return LINGLONG_ERR( fmt::format("unexpected Documents portal mount point type: {}", value.typeName())); @@ -306,7 +307,7 @@ auto ContainerBuilder::prepareContainer(runtime::RunContext &context, } PreparedContainer prepared{ - .runContext = context, + .runContext = &context, .context = std::move(*containerContext), .mode = mode, }; @@ -323,7 +324,7 @@ auto ContainerBuilder::prepareContainer(runtime::RunContext &context, auto uid = getuid(); auto gid = getgid(); - prepared.cfgBuilder.setAppId(prepared.runContext.get().getTargetID()) + prepared.cfgBuilder.setAppId(prepared.runContext->getTargetID()) .setBundlePath(prepared.context->getBundleDir()) .addUIdMapping(uid, uid, 1) .addGIdMapping(gid, gid, 1) @@ -353,8 +354,7 @@ auto ContainerBuilder::finalizeContainer(PreparedContainer &prepared) noexcept bool useOverlayMode = true; bool needGenLdConf = false; if (prepared.mode == ContainerMode::Init) { - auto &runContext = prepared.runContext.get(); - const auto &appLayer = runContext.getAppLayer(); + const auto &appLayer = prepared.runContext->getAppLayer(); if (!appLayer) { return LINGLONG_ERR("app layer not found"); } @@ -407,8 +407,7 @@ auto ContainerBuilder::configureBuildContainer(PreparedContainer &prepared, prepared.cfgBuilder.isolateNetWork(); } - auto &runContext = prepared.runContext.get(); - auto res = normalizeContainerRootfs(options.basePath, runContext.getConfig()); + auto res = normalizeContainerRootfs(options.basePath, prepared.runContext->getConfig()); if (!res) { return LINGLONG_ERR(res); } @@ -460,7 +459,7 @@ auto ContainerBuilder::configureInitContainer(PreparedContainer &prepared) noexc { LINGLONG_TRACE("configure init container"); - auto &runContext = prepared.runContext.get(); + auto &runContext = *prepared.runContext; prepared.cfgBuilder.bindXDGRuntime().bindHostRoot().bindHostStatics().forwardDefaultEnv(); @@ -582,7 +581,7 @@ auto ContainerBuilder::configureRunContainer(PreparedContainer &prepared, capabilities.insert(capabilities.end(), extraCapabilities.begin(), extraCapabilities.end()); prepared.cfgBuilder.setCapabilities(std::move(capabilities)); - auto &runContext = prepared.runContext.get(); + auto &runContext = *prepared.runContext; for (const auto &type : options.getSecurityContexts()) { auto manager = getSecurityContextManager(type); if (!manager) { diff --git a/libs/linglong/src/linglong/runtime/container_builder.h b/libs/linglong/src/linglong/runtime/container_builder.h index 45c2e7f77..77c2f454a 100644 --- a/libs/linglong/src/linglong/runtime/container_builder.h +++ b/libs/linglong/src/linglong/runtime/container_builder.h @@ -95,7 +95,7 @@ class ContainerBuilder -> utils::error::Result>; private: - enum class ContainerMode { + enum class ContainerMode : uint8_t { Init, Build, Run, @@ -104,7 +104,7 @@ class ContainerBuilder struct PreparedContainer { generator::ContainerCfgBuilder cfgBuilder; - std::reference_wrapper runContext; + runtime::RunContext *runContext{ nullptr }; std::unique_ptr context; ContainerMode mode{ ContainerMode::Run }; }; diff --git a/libs/linglong/src/linglong/runtime/layer.cpp b/libs/linglong/src/linglong/runtime/layer.cpp new file mode 100644 index 000000000..dff5bed4d --- /dev/null +++ b/libs/linglong/src/linglong/runtime/layer.cpp @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "linglong/runtime/layer.h" + +#include "linglong/runtime/run_context.h" +#include "linglong/utils/log/log.h" + +#include + +namespace linglong::runtime { +utils::error::Result RuntimeLayer::create(package::Reference ref, + const RunContext &context) +{ + LINGLONG_TRACE(fmt::format("create runtime layer from ref {}", ref.toString())); + + try { + return RuntimeLayer(std::move(ref), context); + } catch (const std::exception &e) { + return LINGLONG_ERR("failed to create runtime layer", e); + } +} + +RuntimeLayer::RuntimeLayer(package::Reference ref, const RunContext &context) + : reference(std::move(ref)) + , runContext(&context) + , temporary(false) +{ + const auto &repo = context.getRepo(); + auto item = repo.getLayerItem(reference); + if (!item) { + throw std::runtime_error("no cached item found"); + } + cachedItem = std::move(item).value(); +} + +RuntimeLayer::~RuntimeLayer() noexcept +{ + if (temporary && layerDir) { + std::error_code ec; + const auto &path = layerDir->path(); + std::filesystem::remove_all(path, ec); + if (ec) { + LogI("failed to remove all files under {}: {}", path, ec.message()); + } + } +} + +utils::error::Result RuntimeLayer::resolveLayer(const std::vector &modules, + const std::optional &subRef) +{ + LINGLONG_TRACE("resolve layer"); + + if (this->runContext == nullptr) { + return LINGLONG_ERR("runContext is nullptr"); + } + + auto &repo = runContext->getRepo(); + utils::error::Result layer(LINGLONG_ERR("null")); + if (modules.empty() || (modules.size() == 1 && modules.at(0) == "binary")) { + layer = repo.getMergedModuleDir(reference, true, subRef); + } else if (modules.size() > 1) { + layer = repo.createTempMergedModuleDir(reference, modules); + temporary = true; + LogD("create temp merged module dir: {}", layer->path()); + } else { + return LINGLONG_ERR( + fmt::format("resolve module {} is not supported", fmt::join(modules, ","))); + } + + if (!layer) { + return LINGLONG_ERR("layer doesn't exist: " + reference.toString(), layer); + } + + layerDir = *layer; + return LINGLONG_OK; +} +} // namespace linglong::runtime diff --git a/libs/linglong/src/linglong/runtime/layer.h b/libs/linglong/src/linglong/runtime/layer.h new file mode 100644 index 000000000..3469542dd --- /dev/null +++ b/libs/linglong/src/linglong/runtime/layer.h @@ -0,0 +1,74 @@ +// SPDX-FileCopyrightText: 2026 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +#include "linglong/api/types/v1/RepositoryCacheLayersItem.hpp" +#include "linglong/package/layer_dir.h" +#include "linglong/package/reference.h" +#include "linglong/utils/error/error.h" + +#include +#include +#include +#include + +namespace linglong::runtime { + +class RunContext; + +class RuntimeLayer +{ +public: + RuntimeLayer(const RuntimeLayer &) = delete; + RuntimeLayer &operator=(const RuntimeLayer &) = delete; + RuntimeLayer(RuntimeLayer &&) = default; + RuntimeLayer &operator=(RuntimeLayer &&) = default; + + static utils::error::Result create(package::Reference ref, + const RunContext &context); + ~RuntimeLayer() noexcept; + + struct ExtensionRuntimeLayerInfo + { + api::types::v1::ExtensionDefine extensionInfo; + std::reference_wrapper extensionLayer; + std::string forRef; + }; + + utils::error::Result + resolveLayer(const std::vector &modules = {}, + const std::optional &subRef = std::nullopt); + + [[nodiscard]] const api::types::v1::RepositoryCacheLayersItem &getCachedItem() const noexcept + { + return cachedItem; + } + + [[nodiscard]] const package::Reference &getReference() const noexcept { return reference; } + + [[nodiscard]] const std::optional &getLayerDir() const noexcept + { + return layerDir; + } + + void setExtensionInfo(ExtensionRuntimeLayerInfo info) noexcept { extensionOf = info; } + + [[nodiscard]] const std::optional &getExtensionInfo() const noexcept + { + return extensionOf; + } + +private: + RuntimeLayer(package::Reference ref, const RunContext &context); + + package::Reference reference; + const RunContext *runContext{ nullptr }; + std::optional layerDir; + api::types::v1::RepositoryCacheLayersItem cachedItem; + bool temporary{ false }; + std::optional extensionOf; +}; + +}; // namespace linglong::runtime diff --git a/libs/linglong/src/linglong/runtime/run_context.cpp b/libs/linglong/src/linglong/runtime/run_context.cpp index c7ca4e96a..cace512f8 100644 --- a/libs/linglong/src/linglong/runtime/run_context.cpp +++ b/libs/linglong/src/linglong/runtime/run_context.cpp @@ -2,7 +2,7 @@ * SPDX-License-Identifier: LGPL-3.0-or-later */ -#include "run_context.h" +#include "linglong/runtime/run_context.h" #include "linglong/cdi/cdi.h" #include "linglong/common/display.h" @@ -40,68 +40,10 @@ std::optional timezoneFromPath(const std::filesystem::path &path, } // namespace -utils::error::Result RuntimeLayer::create(package::Reference ref, RunContext &context) -{ - LINGLONG_TRACE(fmt::format("create runtime layer from ref {}", ref.toString())); - - try { - return RuntimeLayer(ref, context); - } catch (const std::exception &e) { - return LINGLONG_ERR("failed to create runtime layer", e); - } -} - -RuntimeLayer::RuntimeLayer(package::Reference ref, RunContext &context) - : reference(std::move(ref)) - , runContext(context) - , temporary(false) -{ - const auto &repo = context.getRepo(); - auto item = repo.getLayerItem(reference); - if (!item) { - throw std::runtime_error("no cached item found"); - } - cachedItem = std::move(item).value(); -} - -RuntimeLayer::~RuntimeLayer() -{ - if (temporary && layerDir) { - std::error_code ec; - std::filesystem::remove_all(layerDir->path(), ec); - } -} - -utils::error::Result RuntimeLayer::resolveLayer(const std::vector &modules, - const std::optional &subRef) -{ - LINGLONG_TRACE("resolve layer"); - - auto &repo = runContext.get().getRepo(); - utils::error::Result layer(LINGLONG_ERR("null")); - if (modules.empty() || (modules.size() == 1 && modules[0] == "binary")) { - layer = repo.getMergedModuleDir(reference, true, subRef); - } else if (modules.size() > 1) { - layer = repo.createTempMergedModuleDir(reference, modules); - temporary = true; - LogD("create temp merged module dir: {}", layer->path()); - } else { - return LINGLONG_ERR( - fmt::format("resolve module {} is not supported", fmt::join(modules, ","))); - } - - if (!layer) { - return LINGLONG_ERR("layer doesn't exist: " + reference.toString(), layer); - } - - layerDir = *layer; - return LINGLONG_OK; -} - -RunContext::~RunContext() { } +RunContext::~RunContext() = default; utils::error::Result RunContext::resolve(const linglong::package::Reference &runnable, - const ResolveOptions &options) + const ResolveOptions &opts) { LINGLONG_TRACE("resolve RunContext from runnable " + runnable.toString()); @@ -116,7 +58,7 @@ utils::error::Result RunContext::resolve(const linglong::package::Referenc baseLayer = std::move(layer).value(); } else if (info.kind == "app") { appLayer = std::move(layer).value(); - auto runtime = options.runtimeRef.value_or(info.runtime.value_or("")); + auto runtime = opts.runtimeRef.value_or(info.runtime.value_or("")); if (!runtime.empty()) { auto runtimeFuzzyRef = package::FuzzyReference::parse(runtime); if (!runtimeFuzzyRef) { @@ -146,7 +88,7 @@ utils::error::Result RunContext::resolve(const linglong::package::Referenc // base layer must be resolved for all kinds if (!baseLayer) { - auto baseRef = options.baseRef.value_or(info.base); + auto baseRef = opts.baseRef.value_or(info.base); auto baseFuzzyRef = package::FuzzyReference::parse(baseRef); if (!baseFuzzyRef) { return LINGLONG_ERR(baseFuzzyRef); @@ -171,7 +113,7 @@ utils::error::Result RunContext::resolve(const linglong::package::Referenc // resolve base extension auto ret = resolveLayerExtensions( *baseLayer, - matchedExtensionDefines(baseLayer->getReference(), options.externalExtensionDefs)); + matchedExtensionDefines(baseLayer->getReference(), opts.externalExtensionDefs)); if (!ret) { return LINGLONG_ERR(ret); } @@ -180,7 +122,7 @@ utils::error::Result RunContext::resolve(const linglong::package::Referenc if (runtimeLayer) { auto ret = resolveLayerExtensions( *runtimeLayer, - matchedExtensionDefines(runtimeLayer->getReference(), options.externalExtensionDefs)); + matchedExtensionDefines(runtimeLayer->getReference(), opts.externalExtensionDefs)); if (!ret) { return LINGLONG_ERR(ret); } @@ -190,15 +132,15 @@ utils::error::Result RunContext::resolve(const linglong::package::Referenc if (appLayer) { auto ret = resolveLayerExtensions( *appLayer, - matchedExtensionDefines(appLayer->getReference(), options.externalExtensionDefs)); + matchedExtensionDefines(appLayer->getReference(), opts.externalExtensionDefs)); if (!ret) { return LINGLONG_ERR(ret); } } // 手动解析多个扩展 - if (options.extensionRefs && !options.extensionRefs->empty()) { - auto manualExtensionDef = makeManualExtensionDefine(*options.extensionRefs); + if (opts.extensionRefs && !opts.extensionRefs->empty()) { + auto manualExtensionDef = makeManualExtensionDefine(*opts.extensionRefs); if (!manualExtensionDef) { return LINGLONG_ERR(manualExtensionDef); } @@ -228,13 +170,12 @@ utils::error::Result RunContext::resolve(const linglong::package::Referenc return LINGLONG_ERR("failed to resolve timezone", timezoneRet); } - if (options.cdiDevices) { - contextCfg.cdiDevices = options.cdiDevices.value(); + if (opts.cdiDevices) { + contextCfg.cdiDevices = opts.cdiDevices.value(); } // all reference are cleard , we can get actual layer directory now - return resolveLayer(options.depsBinaryOnly, - options.appModules.value_or(std::vector{})); + return resolveLayer(opts.depsBinaryOnly, opts.appModules.value_or(std::vector{})); } utils::error::Result RunContext::resolve(const api::types::v1::BuilderProject &target, @@ -962,10 +903,8 @@ utils::error::Result RunContext::fillExtraAppMounts(generator::ContainerCf { LINGLONG_TRACE("fill extra app mounts"); - auto fillPermissionsBinds = - [&builder, &bundlePath, this](RuntimeLayer &layer) -> utils::error::Result { - LINGLONG_TRACE("fill permissions binds"); - + auto fillPermissionsBinds = [&builder, + &bundlePath](RuntimeLayer &layer) -> utils::error::Result { const auto &info = layer.getCachedItem().info; if (info.permissions) { @@ -986,7 +925,7 @@ utils::error::Result RunContext::fillExtraAppMounts(generator::ContainerCf auto bindInnerMount = [&applicationMounts, &bundlePath]( const api::types::v1::ApplicationConfigurationPermissionsInnerBind &bind) { - std::filesystem::path source = bind.source; + const std::filesystem::path source = bind.source; applicationMounts.push_back(ocppi::runtime::config::types::Mount{ .destination = bind.destination, .gidMappings = {}, diff --git a/libs/linglong/src/linglong/runtime/run_context.h b/libs/linglong/src/linglong/runtime/run_context.h index 3e049e1f9..54567cbb8 100644 --- a/libs/linglong/src/linglong/runtime/run_context.h +++ b/libs/linglong/src/linglong/runtime/run_context.h @@ -11,11 +11,11 @@ #include "linglong/api/types/v1/ExtensionDefine.hpp" #include "linglong/api/types/v1/RunContextConfig.hpp" #include "linglong/repo/ostree_repo.h" +#include "linglong/runtime/layer.h" #include "linglong/utils/error/error.h" #include "ocppi/runtime/config/types/Generators.hpp" #include -#include namespace linglong::generator { class ContainerCfgBuilder; @@ -23,51 +23,6 @@ class ContainerCfgBuilder; namespace linglong::runtime { -class RunContext; - -class RuntimeLayer -{ -public: - RuntimeLayer(const RuntimeLayer &) = delete; - RuntimeLayer &operator=(const RuntimeLayer &) = delete; - RuntimeLayer(RuntimeLayer &&) = default; - RuntimeLayer &operator=(RuntimeLayer &&) = default; - - static utils::error::Result create(package::Reference ref, RunContext &context); - ~RuntimeLayer(); - - struct ExtensionRuntimeLayerInfo - { - api::types::v1::ExtensionDefine extensionInfo; - std::reference_wrapper extensionLayer; - std::string forRef; - }; - - utils::error::Result - resolveLayer(const std::vector &modules = {}, - const std::optional &subRef = std::nullopt); - - const api::types::v1::RepositoryCacheLayersItem &getCachedItem() const { return cachedItem; } - - const package::Reference &getReference() const { return reference; } - - const std::optional &getLayerDir() const { return layerDir; } - - void setExtensionInfo(ExtensionRuntimeLayerInfo info) { extensionOf = info; } - - const std::optional &getExtensionInfo() const { return extensionOf; } - -private: - RuntimeLayer(package::Reference ref, RunContext &context); - - package::Reference reference; - std::reference_wrapper runContext; - std::optional layerDir; - api::types::v1::RepositoryCacheLayersItem cachedItem; - bool temporary; - std::optional extensionOf; -}; - struct ResolveOptions { bool depsBinaryOnly{ false }; @@ -83,7 +38,7 @@ struct ResolveOptions class RunContext { public: - RunContext(repo::OSTreeRepo &r) + explicit RunContext(repo::OSTreeRepo &r) : repo(r) { } @@ -98,7 +53,7 @@ class RunContext utils::error::Result resolve(const api::types::v1::RunContextConfig &config); - const api::types::v1::RunContextConfig &getConfig() const { return contextCfg; } + [[nodiscard]] const api::types::v1::RunContextConfig &getConfig() const { return contextCfg; } utils::error::Result fillContextCfg(generator::ContainerCfgBuilder &builder, const std::filesystem::path &bundlePath); @@ -106,24 +61,33 @@ class RunContext bool applyHooks = true) const; api::types::v1::ContainerProcessStateInfo stateInfo(); - repo::OSTreeRepo &getRepo() const { return repo; } + [[nodiscard]] repo::OSTreeRepo &getRepo() const noexcept { return repo; } - const std::string &getContainerId() const { return containerID; } + [[nodiscard]] const std::string &getContainerId() const noexcept { return containerID; } - const std::string &getTargetID() const { return targetId; } + [[nodiscard]] const std::string &getTargetID() const noexcept { return targetId; } - const std::optional &getBaseLayer() const { return baseLayer; } + [[nodiscard]] const std::optional &getBaseLayer() const noexcept + { + return baseLayer; + } - const std::optional &getRuntimeLayer() const { return runtimeLayer; } + [[nodiscard]] const std::optional &getRuntimeLayer() const noexcept + { + return runtimeLayer; + } - const std::optional &getAppLayer() const { return appLayer; } + [[nodiscard]] const std::optional &getAppLayer() const noexcept + { + return appLayer; + } - utils::error::Result getBaseLayerPath() const; - utils::error::Result getRuntimeLayerPath() const; + [[nodiscard]] utils::error::Result getBaseLayerPath() const; + [[nodiscard]] utils::error::Result getRuntimeLayerPath() const; utils::error::Result getCachedAppItem(); - bool hasRuntime() const { return !!runtimeLayer; } + [[nodiscard]] bool hasRuntime() const noexcept { return !!runtimeLayer; } private: utils::error::Result resolveLayer(bool depsBinaryOnly, diff --git a/libs/linglong/src/linglong/runtime/security_context.h b/libs/linglong/src/linglong/runtime/security_context.h index a8f112546..de4b4370e 100644 --- a/libs/linglong/src/linglong/runtime/security_context.h +++ b/libs/linglong/src/linglong/runtime/security_context.h @@ -15,7 +15,7 @@ namespace linglong::runtime { class ContainerContext; class RunContext; -enum class SecurityContextType { +enum class SecurityContextType : uint8_t { WAYLAND, UNKNOWN, }; diff --git a/libs/linglong/tests/ll-tests/src/linglong/runtime/run_context_test.cpp b/libs/linglong/tests/ll-tests/src/linglong/runtime/run_context_test.cpp index 44cf37163..f4c057a9c 100644 --- a/libs/linglong/tests/ll-tests/src/linglong/runtime/run_context_test.cpp +++ b/libs/linglong/tests/ll-tests/src/linglong/runtime/run_context_test.cpp @@ -17,12 +17,8 @@ #include using namespace linglong; -using ::testing::_; using ::testing::AtLeast; -using ::testing::ElementsAre; -using ::testing::IsEmpty; using ::testing::Return; -using ::testing::WithArg; namespace { @@ -113,7 +109,7 @@ TEST_F(RunContextTest, layerExist) mockItem.info.channel = "stable"; mockItem.info.arch = { std::string{ "x86_64" } }; - EXPECT_CALL(*repo, getLayerItem(_, _, _)).WillOnce(Return(mockItem)); + EXPECT_CALL(*repo, getLayerItem(testing::_, testing::_, testing::_)).WillOnce(Return(mockItem)); // Create runtime layer RunContext context(*this->repo); @@ -130,7 +126,8 @@ TEST_F(RunContextTest, layerNotExist) ASSERT_TRUE(ref.has_value()) << "Failed to create reference: " << ref.error().message(); // Mock failed layer item retrieval (layer doesn't exist) - EXPECT_CALL(*repo, getLayerItem(_, _, _)).WillOnce(Return(LINGLONG_ERR("Layer not found"))); + EXPECT_CALL(*repo, getLayerItem(testing::_, testing::_, testing::_)) + .WillOnce(Return(LINGLONG_ERR("Layer not found"))); // Attempt to create runtime layer RunContext context(*this->repo); @@ -154,11 +151,12 @@ TEST_F(RunContextTest, resolveBinaryModule) mockItem.info.channel = "stable"; mockItem.info.arch = { std::string{ "x86_64" } }; - EXPECT_CALL(*repo, getLayerItem(_, _, _)).WillOnce(Return(mockItem)); + EXPECT_CALL(*repo, getLayerItem(testing::_, testing::_, testing::_)).WillOnce(Return(mockItem)); // Mock successful layer directory retrieval for binary module package::LayerDir mockLayerDir(tempDir->path() / "merged"); - EXPECT_CALL(*repo, getMergedModuleDir(_, true, _)).WillOnce(Return(mockLayerDir)); + EXPECT_CALL(*repo, getMergedModuleDir(testing::_, true, testing::_)) + .WillOnce(Return(mockLayerDir)); // Create runtime layer RunContext context(*this->repo); @@ -188,11 +186,13 @@ TEST_F(RunContextTest, resolveMultiModules) mockItem.info.channel = "stable"; mockItem.info.arch = { std::string{ "x86_64" } }; - EXPECT_CALL(*repo, getLayerItem(_, _, _)).WillOnce(Return(mockItem)); + EXPECT_CALL(*repo, getLayerItem(testing::_, testing::_, testing::_)).WillOnce(Return(mockItem)); // Mock successful merged module directory retrieval for multiple modules package::LayerDir mockLayerDir(tempDir->path() / "merged"); - EXPECT_CALL(*repo, createTempMergedModuleDir(_, std::vector{ "binary", "debug" })) + EXPECT_CALL( + *repo, + createTempMergedModuleDir(testing::_, std::vector{ "binary", "debug" })) .WillOnce(Return(mockLayerDir)); // Create runtime layer @@ -224,12 +224,13 @@ TEST_F(RunContextTest, resolveSubRef) mockItem.info.arch = { std::string{ "x86_64" } }; mockItem.info.uuid = "test-uuid-12345"; - EXPECT_CALL(*repo, getLayerItem(_, _, _)).WillOnce(Return(mockItem)); + EXPECT_CALL(*repo, getLayerItem(testing::_, testing::_, testing::_)).WillOnce(Return(mockItem)); // Mock successful layer directory retrieval with sub-reference package::LayerDir mockLayerDir(tempDir->path() / "merged"); - EXPECT_CALL(*repo, - getMergedModuleDir(_, "binary", std::optional("test-uuid-12345"))) + EXPECT_CALL( + *repo, + getMergedModuleDir(testing::_, "binary", std::optional("test-uuid-12345"))) .WillOnce(Return(mockLayerDir)); // Create runtime layer @@ -286,20 +287,22 @@ TEST_F(RunContextTest, resolveRunnableWithApp) baseItem.info.channel = "stable"; baseItem.info.arch = { std::string{ "x86_64" } }; - EXPECT_CALL(*repo, getLayerItem(*runnableRef, _, _)).WillOnce(Return(appItem)); - EXPECT_CALL(*repo, clearReference(_, _, _, _)) + EXPECT_CALL(*repo, getLayerItem(*runnableRef, testing::_, testing::_)) + .WillOnce(Return(appItem)); + EXPECT_CALL(*repo, clearReference(testing::_, testing::_, testing::_, testing::_)) .WillOnce(Return(*runtimeRef)) .WillOnce(Return(*baseRef)); - EXPECT_CALL(*repo, getLayerItem(*runtimeRef, _, _)).WillOnce(Return(runtimeItem)); - EXPECT_CALL(*repo, getLayerItem(*baseRef, _, _)).WillOnce(Return(baseItem)); + EXPECT_CALL(*repo, getLayerItem(*runtimeRef, testing::_, testing::_)) + .WillOnce(Return(runtimeItem)); + EXPECT_CALL(*repo, getLayerItem(*baseRef, testing::_, testing::_)).WillOnce(Return(baseItem)); package::LayerDir mockLayerDir(tempDir->path() / "merged"); - EXPECT_CALL(*repo, getMergedModuleDir(*runnableRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*runnableRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); - EXPECT_CALL(*repo, getMergedModuleDir(*runtimeRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*runtimeRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); - EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); RunContext context(*this->repo); @@ -340,15 +343,17 @@ TEST_F(RunContextTest, resolveRunnableWithRuntime) baseItem.info.channel = "stable"; baseItem.info.arch = { std::string{ "x86_64" } }; - EXPECT_CALL(*repo, getLayerItem(*runnableRef, _, _)).WillOnce(Return(runtimeItem)); - EXPECT_CALL(*repo, clearReference(_, _, _, _)).WillOnce(Return(*baseRef)); + EXPECT_CALL(*repo, getLayerItem(*runnableRef, testing::_, testing::_)) + .WillOnce(Return(runtimeItem)); + EXPECT_CALL(*repo, clearReference(testing::_, testing::_, testing::_, testing::_)) + .WillOnce(Return(*baseRef)); - EXPECT_CALL(*repo, getLayerItem(*baseRef, _, _)).WillOnce(Return(baseItem)); + EXPECT_CALL(*repo, getLayerItem(*baseRef, testing::_, testing::_)).WillOnce(Return(baseItem)); package::LayerDir mockLayerDir(tempDir->path() / "merged"); - EXPECT_CALL(*repo, getMergedModuleDir(*runnableRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*runnableRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); - EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); RunContext context(*this->repo); @@ -375,10 +380,11 @@ TEST_F(RunContextTest, resolveRunnableWithBase) baseItem.info.channel = "stable"; baseItem.info.arch = { std::string{ "x86_64" } }; - EXPECT_CALL(*repo, getLayerItem(*runnableRef, _, _)).WillOnce(Return(baseItem)); + EXPECT_CALL(*repo, getLayerItem(*runnableRef, testing::_, testing::_)) + .WillOnce(Return(baseItem)); package::LayerDir mockLayerDir(tempDir->path() / "merged"); - EXPECT_CALL(*repo, getMergedModuleDir(*runnableRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*runnableRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); RunContext context(*this->repo); @@ -405,7 +411,8 @@ TEST_F(RunContextTest, resolveRunnableWithInvalidKind) invalidItem.info.channel = "stable"; invalidItem.info.arch = { std::string{ "x86_64" } }; - EXPECT_CALL(*repo, getLayerItem(*runnableRef, _, _)).WillOnce(Return(invalidItem)); + EXPECT_CALL(*repo, getLayerItem(*runnableRef, testing::_, testing::_)) + .WillOnce(Return(invalidItem)); RunContext context(*this->repo); auto result = context.resolve(*runnableRef); @@ -465,25 +472,28 @@ TEST_F(RunContextTest, toConfig) extensionItem.info.channel = "stable"; extensionItem.info.arch = { std::string{ "x86_64" } }; - EXPECT_CALL(*repo, getLayerItem(*runnableRef, _, _)).WillOnce(Return(appItem)); - EXPECT_CALL(*repo, clearReference(_, _, _, _)) + EXPECT_CALL(*repo, getLayerItem(*runnableRef, testing::_, testing::_)) + .WillOnce(Return(appItem)); + EXPECT_CALL(*repo, clearReference(testing::_, testing::_, testing::_, testing::_)) .Times(AtLeast(2)) .WillOnce(Return(*runtimeRef)) .WillOnce(Return(*baseRef)) .WillOnce(Return(*extensionRef)); - EXPECT_CALL(*repo, getLayerItem(*runtimeRef, _, _)).WillOnce(Return(runtimeItem)); - EXPECT_CALL(*repo, getLayerItem(*baseRef, _, _)).WillOnce(Return(baseItem)); - EXPECT_CALL(*repo, getLayerItem(*extensionRef, _, _)).WillOnce(Return(extensionItem)); + EXPECT_CALL(*repo, getLayerItem(*runtimeRef, testing::_, testing::_)) + .WillOnce(Return(runtimeItem)); + EXPECT_CALL(*repo, getLayerItem(*baseRef, testing::_, testing::_)).WillOnce(Return(baseItem)); + EXPECT_CALL(*repo, getLayerItem(*extensionRef, testing::_, testing::_)) + .WillOnce(Return(extensionItem)); package::LayerDir mockLayerDir(tempDir->path() / "merged"); - EXPECT_CALL(*repo, getMergedModuleDir(*runnableRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*runnableRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); - EXPECT_CALL(*repo, getMergedModuleDir(*runtimeRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*runtimeRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); - EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); - EXPECT_CALL(*repo, getMergedModuleDir(*extensionRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*extensionRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); RunContext context(*this->repo); @@ -560,26 +570,28 @@ TEST_F(RunContextTest, resolveFromConfig) extensionItem.info.channel = "stable"; extensionItem.info.arch = { std::string{ "x86_64" } }; - EXPECT_CALL(*repo, getLayerItem(*baseRef, _, _)).WillOnce(Return(baseItem)); - EXPECT_CALL(*repo, getLayerItem(*runtimeRef, _, _)).WillOnce(Return(runtimeItem)); - EXPECT_CALL(*repo, getLayerItem(*appRef, _, _)).WillOnce(Return(appItem)); - EXPECT_CALL(*repo, getLayerItem(*extensionRef, _, _)).WillOnce(Return(extensionItem)); + EXPECT_CALL(*repo, getLayerItem(*baseRef, testing::_, testing::_)).WillOnce(Return(baseItem)); + EXPECT_CALL(*repo, getLayerItem(*runtimeRef, testing::_, testing::_)) + .WillOnce(Return(runtimeItem)); + EXPECT_CALL(*repo, getLayerItem(*appRef, testing::_, testing::_)).WillOnce(Return(appItem)); + EXPECT_CALL(*repo, getLayerItem(*extensionRef, testing::_, testing::_)) + .WillOnce(Return(extensionItem)); package::LayerDir mockLayerDir(tempDir->path() / "merged"); - EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); - EXPECT_CALL(*repo, getMergedModuleDir(*runtimeRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*runtimeRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); - EXPECT_CALL(*repo, getMergedModuleDir(*appRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*appRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); - EXPECT_CALL(*repo, getMergedModuleDir(*extensionRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*extensionRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); RunContext context(*this->repo); auto result = context.resolve(config); ASSERT_TRUE(result.has_value()) << "Failed to resolve config: " << result.error().message(); - auto &retConfig = context.getConfig(); + const auto &retConfig = context.getConfig(); EXPECT_EQ(retConfig.version, "1"); EXPECT_TRUE(retConfig.base.has_value()); EXPECT_EQ(retConfig.base.value(), baseRef->toString()); @@ -618,10 +630,10 @@ TEST_F(RunContextTest, resolveFromConfigBaseOnly) baseItem.info.channel = "stable"; baseItem.info.arch = { std::string{ "x86_64" } }; - EXPECT_CALL(*repo, getLayerItem(*baseRef, _, _)).WillOnce(Return(baseItem)); + EXPECT_CALL(*repo, getLayerItem(*baseRef, testing::_, testing::_)).WillOnce(Return(baseItem)); package::LayerDir mockLayerDir(tempDir->path() / "merged"); - EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); RunContext context(*this->repo); @@ -649,10 +661,10 @@ TEST_F(RunContextTest, resolveWithCDIDevicesInOptions) baseItem.info.channel = "stable"; baseItem.info.arch = { std::string{ "x86_64" } }; - EXPECT_CALL(*repo, getLayerItem(*baseRef, _, _)).WillOnce(Return(baseItem)); + EXPECT_CALL(*repo, getLayerItem(*baseRef, testing::_, testing::_)).WillOnce(Return(baseItem)); package::LayerDir mockLayerDir(tempDir->path() / "merged"); - EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); const auto specPath = tempDir->path() / "vendor.yaml"; @@ -691,8 +703,8 @@ kind: "vendor.com/device" EXPECT_EQ(retConfig.cdiDevices->at(0).spec.path, specPath.string()); EXPECT_FALSE(retConfig.cdiDevices->at(0).spec.checksum.empty()); - EXPECT_CALL(*repo, getLayerItem(*baseRef, _, _)).WillOnce(Return(baseItem)); - EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, _, _)) + EXPECT_CALL(*repo, getLayerItem(*baseRef, testing::_, testing::_)).WillOnce(Return(baseItem)); + EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); RunContext restored(*this->repo); @@ -720,10 +732,10 @@ TEST_F(RunContextTest, cdiEnvPreservesEqualsInValue) baseItem.info.channel = "stable"; baseItem.info.arch = { std::string{ "x86_64" } }; - EXPECT_CALL(*repo, getLayerItem(*baseRef, _, _)).WillOnce(Return(baseItem)); + EXPECT_CALL(*repo, getLayerItem(*baseRef, testing::_, testing::_)).WillOnce(Return(baseItem)); package::LayerDir mockLayerDir(tempDir->path() / "merged"); - EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, _, _)) + EXPECT_CALL(*repo, getMergedModuleDir(*baseRef, testing::_, testing::_)) .WillOnce(Return(utils::error::Result(mockLayerDir))); const auto specPath = tempDir->path() / "vendor-env.yaml"; diff --git a/libs/utils/src/linglong/utils/cmd.cpp b/libs/utils/src/linglong/utils/cmd.cpp index 25f9b7ac4..d7d3b74c8 100644 --- a/libs/utils/src/linglong/utils/cmd.cpp +++ b/libs/utils/src/linglong/utils/cmd.cpp @@ -78,22 +78,28 @@ utils::error::Result Cmd::exec(const std::vector &args return LINGLONG_ERR(fmt::format("command not found: {}", m_command)); } - int stdoutPipe[2]; - if (pipe(stdoutPipe) == -1) { + std::array stdoutPipe{ -1, -1 }; + if (pipe2(stdoutPipe.data(), O_CLOEXEC) == -1) { return LINGLONG_ERR(fmt::format("pipe error: {}", common::error::errorString(errno))); } - auto stdoutPipeCloser = utils::finally::finally([stdoutPipe]() { - close(stdoutPipe[0]); - close(stdoutPipe[1]); + auto stdoutPipeCloser = utils::finally::finally([&stdoutPipe]() { + for (auto fd : stdoutPipe) { + if (fd >= 0) { + close(fd); + } + } }); - int stdinPipe[2]; - if (pipe(stdinPipe) == -1) { + std::array stdinPipe{ -1, -1 }; + if (pipe2(stdinPipe.data(), O_CLOEXEC) == -1) { return LINGLONG_ERR(fmt::format("pipe error: {}", common::error::errorString(errno))); } - auto stdinPipeCloser = utils::finally::finally([stdinPipe]() { - close(stdinPipe[0]); - close(stdinPipe[1]); + auto stdinPipeCloser = utils::finally::finally([&stdinPipe]() { + for (auto fd : stdinPipe) { + if (fd >= 0) { + close(fd); + } + } }); // Pre-allocate environment variables before fork to avoid memory allocation issues @@ -101,28 +107,30 @@ utils::error::Result Cmd::exec(const std::vector &args std::vector envp; // Copy current environment - for (char **env = environ; *env != nullptr; ++env) { + for (char *const *env = environ; *env != nullptr; ++env) { envStrings.emplace_back(*env); } // Add or override environment variables - for (const auto &[name, value] : m_envs) { + for (auto it = m_envs.cbegin(); it != m_envs.cend(); ++it) { + const auto &name = it->first; + const auto &value = it->second; if (value.empty()) { // Remove the environment variable if value is empty envStrings.erase(std::remove_if(envStrings.begin(), envStrings.end(), [&name](const std::string &env) { return env.size() > name.size() - && env.substr(0, name.size()) == name + && env.compare(0, name.size(), name) == 0 && env[name.size()] == '='; }), envStrings.end()); } else { // Add or update environment variable - std::string envVar = name + "=" + value; + const auto envVar = (name + "=").append(value); bool found = false; for (auto &env : envStrings) { - if (env.size() > name.size() && env.substr(0, name.size()) == name + if (env.size() > name.size() && env.compare(0, name.size(), name) == 0 && env[name.size()] == '=') { env = envVar; found = true; @@ -144,7 +152,7 @@ utils::error::Result Cmd::exec(const std::vector &args LogD("execute {} with args [{}]", commandPath, fmt::join(args, ", ")); - pid_t pid = fork(); + const pid_t pid = fork(); if (pid == -1) { return LINGLONG_ERR(fmt::format("fork error: {}", common::error::errorString(errno))); } @@ -155,7 +163,7 @@ utils::error::Result Cmd::exec(const std::vector &args close(stdoutPipe[0]); close(stdinPipe[1]); if (dup2(stdoutPipe[1], STDOUT_FILENO) == -1 || dup2(stdinPipe[0], STDIN_FILENO) == -1) { - exit(1); + _exit(EXIT_FAILURE); } close(stdoutPipe[1]); close(stdinPipe[0]); @@ -172,12 +180,14 @@ utils::error::Result Cmd::exec(const std::vector &args std::cout << "execvpe failed: " << common::error::errorString(errno) << std::endl; - _exit(1); + _exit(EXIT_FAILURE); } // parent process close(stdoutPipe[1]); + stdoutPipe[1] = -1; close(stdinPipe[0]); + stdinPipe[0] = -1; auto setNonBlock = [](int fd) { int flags = fcntl(fd, F_GETFL, 0); @@ -223,6 +233,7 @@ utils::error::Result Cmd::exec(const std::vector &args } else { // If no input, close write end immediately to send EOF to child close(stdinPipe[1]); + stdinPipe[1] = -1; } std::string output; @@ -299,11 +310,13 @@ utils::error::Result Cmd::exec(const std::vector &args int exitCode = WEXITSTATUS(status); if (exitCode == 0) { return output; - } else { - return LINGLONG_ERR( - fmt::format("command execute failed with exit code {}: {}", exitCode, output)); } - } else if (WIFSIGNALED(status)) { + + return LINGLONG_ERR( + fmt::format("command execute failed with exit code {}: {}", exitCode, output)); + } + + if (WIFSIGNALED(status)) { return LINGLONG_ERR(fmt::format("command killed by signal: {}", WTERMSIG(status))); } diff --git a/libs/utils/src/linglong/utils/cmd.h b/libs/utils/src/linglong/utils/cmd.h index 1da3bc079..4e3b5c93a 100644 --- a/libs/utils/src/linglong/utils/cmd.h +++ b/libs/utils/src/linglong/utils/cmd.h @@ -21,7 +21,7 @@ class Cmd { public: explicit Cmd(std::string command) noexcept; - ~Cmd(); + virtual ~Cmd(); virtual bool exists() noexcept; virtual utils::error::Result diff --git a/libs/utils/src/linglong/utils/file.cpp b/libs/utils/src/linglong/utils/file.cpp index c2fd3648a..3ea1749be 100644 --- a/libs/utils/src/linglong/utils/file.cpp +++ b/libs/utils/src/linglong/utils/file.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// SPDX-FileCopyrightText: 2024 - 2026 UnionTech Software Technology Co., Ltd. // // SPDX-License-Identifier: LGPL-3.0-or-later @@ -283,7 +283,7 @@ linglong::utils::error::Result relinkFileTo(const std::filesystem::path &l auto tmpPath = link.string() + ".linyaps.tmp"; std::error_code ec; - std::filesystem::symlink_status(tmpPath, ec); + std::ignore = std::filesystem::symlink_status(tmpPath, ec); if (!ec) { std::filesystem::remove(tmpPath, ec); }