diff options
Diffstat (limited to '0117-NRI-add-nri-head-file-and-common-func.patch')
-rw-r--r-- | 0117-NRI-add-nri-head-file-and-common-func.patch | 1051 |
1 files changed, 1051 insertions, 0 deletions
diff --git a/0117-NRI-add-nri-head-file-and-common-func.patch b/0117-NRI-add-nri-head-file-and-common-func.patch new file mode 100644 index 0000000..61c287e --- /dev/null +++ b/0117-NRI-add-nri-head-file-and-common-func.patch @@ -0,0 +1,1051 @@ +From d21dc88cb33049ec5d9ce8e16eb1a2f9c070219b Mon Sep 17 00:00:00 2001 +From: zhongtao <zhongtao17@huawei.com> +Date: Tue, 30 Jul 2024 20:17:08 +0800 +Subject: [PATCH 117/121] [NRI] add nri head file and common func + +Signed-off-by: zhongtao <zhongtao17@huawei.com> +--- + cmake/checker.cmake | 8 ++ + cmake/options.cmake | 13 ++- + src/CMakeLists.txt | 10 +++ + src/daemon/CMakeLists.txt | 9 ++ + src/daemon/common/CMakeLists.txt | 5 ++ + src/daemon/common/nri/CMakeLists.txt | 13 +++ + src/daemon/common/nri/nri_convert.h | 36 ++++++++ + src/daemon/common/nri/nri_spec.h | 24 ++++++ + src/daemon/common/nri/nri_utils.h | 71 ++++++++++++++++ + src/daemon/config/isulad_config.h | 16 ++++ + src/daemon/modules/api/specs_api.h | 10 ++- + src/daemon/modules/spec/specs.c | 67 ++++++++++++++- + src/daemon/nri/CMakeLists.txt | 6 ++ + src/daemon/nri/nri_adaption.h | 123 +++++++++++++++++++++++++++ + src/daemon/nri/nri_helpers.h | 63 ++++++++++++++ + src/daemon/nri/nri_plugin_ops.h | 38 +++++++++ + src/daemon/nri/nri_result.h | 114 +++++++++++++++++++++++++ + src/daemon/nri/plugin.h | 95 +++++++++++++++++++++ + src/utils/cpputils/transform.cc | 16 ++++ + src/utils/cpputils/transform.h | 2 + + src/utils/cutils/utils.c | 7 ++ + src/utils/cutils/utils.h | 2 + + src/utils/tar/util_archive.c | 7 -- + 23 files changed, 744 insertions(+), 11 deletions(-) + create mode 100644 src/daemon/common/nri/CMakeLists.txt + create mode 100644 src/daemon/common/nri/nri_convert.h + create mode 100644 src/daemon/common/nri/nri_spec.h + create mode 100644 src/daemon/common/nri/nri_utils.h + create mode 100644 src/daemon/nri/CMakeLists.txt + create mode 100644 src/daemon/nri/nri_adaption.h + create mode 100644 src/daemon/nri/nri_helpers.h + create mode 100644 src/daemon/nri/nri_plugin_ops.h + create mode 100644 src/daemon/nri/nri_result.h + create mode 100644 src/daemon/nri/plugin.h + +diff --git a/cmake/checker.cmake b/cmake/checker.cmake +index 13f0fd62..b877c1c8 100644 +--- a/cmake/checker.cmake ++++ b/cmake/checker.cmake +@@ -113,6 +113,14 @@ if (ENABLE_SHIM_V2) + _CHECK(LIBSHIM_V2_LIBRARY "LIBSHIM_V2_LIBRARY-NOTFOUND" "libshim_v2.so") + endif() + ++if (ENABLE_NRI) ++ find_path(NRI_INCLUDE_DIR nri_plugin.h) ++ _CHECK(NRI_INCLUDE_DIR "NRI_INCLUDE_DIR-NOTFOUND" "nri_plugin.h") ++ ++ find_library(LIBISULA_NRI_LIBRARY isula_nri) ++ _CHECK(LIBISULA_NRI_LIBRARY "LIBISULA_NRI_LIBRARY-NOTFOUND" "libisula_nri.so") ++endif() ++ + if (OPENSSL_VERIFY) + find_path(OPENSSL_INCLUDE_DIR openssl/x509.h) + _CHECK(OPENSSL_INCLUDE_DIR "OPENSSL_INCLUDE_DIR-NOTFOUND" "openssl/x509.h") +diff --git a/cmake/options.cmake b/cmake/options.cmake +index 5b17f631..41177fe0 100644 +--- a/cmake/options.cmake ++++ b/cmake/options.cmake +@@ -59,12 +59,23 @@ if (ENABLE_SANDBOXER STREQUAL "ON") + endif() + + option(ENABLE_OOM_MONITOR "Enable oom monitor" ON) +-IF (ENABLE_OOM_MONITOR STREQUAL "ON") ++if (ENABLE_OOM_MONITOR STREQUAL "ON") + add_definitions(-DENABLE_OOM_MONITOR) + set(ENABLE_OOM_MONITOR 1) + message("${Green}-- Enable oom monitor${ColourReset}") + endif() + ++option(ENABLE_NRI "Enable NRI API" OFF) ++if (ENABLE_NRI STREQUAL "ON") ++ if (ENABLE_CRI_API_V1) ++ add_definitions(-DENABLE_NRI) ++ set(ENABLE_NRI 1) ++ message("${Green}-- Enable NRI API${ColourReset}") ++ else() ++ message("${Yellow}-- Can not enable NRI, NRI need enable CRI API V1 first ${ColourReset}") ++ endif() ++endif() ++ + option(ENABLE_SYSTEMD_NOTIFY "Enable systemd notify" ON) + if (ENABLE_SYSTEMD_NOTIFY STREQUAL "ON") + add_definitions(-DSYSTEMD_NOTIFY) +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 48c1bad0..70a8ac91 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -15,6 +15,12 @@ if (ENABLE_SHIM_V2) + ) + endif() + ++if (ENABLE_NRI) ++ list(APPEND CHECKED_INCLUDE_DIRS ++ ${NRI_INCLUDE_DIR} ++ ) ++endif() ++ + if (GRPC_CONNECTOR) + list(APPEND CHECKED_INCLUDE_DIRS + ${GRPC_INCLUDE_DIR} +@@ -168,6 +174,10 @@ if (ENABLE_SHIM_V2) + target_link_libraries(isulad ${LIBSHIM_V2_LIBRARY}) + endif() + ++if (ENABLE_NRI) ++ target_link_libraries(isulad ${LIBISULA_NRI_LIBRARY}) ++endif() ++ + if (ENABLE_EMBEDDED_IMAGE) + target_link_libraries(isulad ${SQLITE3_LIBRARY}) + endif() +diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt +index 29af3dca..801f5797 100644 +--- a/src/daemon/CMakeLists.txt ++++ b/src/daemon/CMakeLists.txt +@@ -36,6 +36,15 @@ if (ENABLE_CRI_API_V1) + list (APPEND local_daemon_incs + ${SANDBOX_INCS} + ) ++ if (ENABLE_NRI) ++ add_subdirectory(nri) ++ list (APPEND local_daemon_srcs ++ ${NRI_SRCS} ++ ) ++ list (APPEND local_daemon_incs ++ ${NRI_INCS} ++ ) ++ endif() + endif() + + set(DAEMON_SRCS +diff --git a/src/daemon/common/CMakeLists.txt b/src/daemon/common/CMakeLists.txt +index e88578dd..ffeed4b3 100644 +--- a/src/daemon/common/CMakeLists.txt ++++ b/src/daemon/common/CMakeLists.txt +@@ -10,12 +10,16 @@ if (GRPC_CONNECTOR) + endif() + + add_subdirectory(cgroup) ++if (ENABLE_NRI) ++ add_subdirectory(nri) ++endif() + + set(local_daemon_common_srcs ${daemon_common_top_srcs}) + + set(DAEMON_COMMON_SRCS + ${COMMON_CRI_SRCS} + ${COMMON_CGROUP_SRCS} ++ ${COMMON_NRI_SRCS} + ${local_daemon_common_srcs} + PARENT_SCOPE + ) +@@ -23,6 +27,7 @@ set(DAEMON_COMMON_SRCS + set(DAEMON_COMMON_INCS + ${COMMON_CRI_INCS} + ${COMMON_CGROUP_INCS} ++ ${COMMON_NRI_INCS} + ${CMAKE_CURRENT_SOURCE_DIR} + PARENT_SCOPE + ) +diff --git a/src/daemon/common/nri/CMakeLists.txt b/src/daemon/common/nri/CMakeLists.txt +new file mode 100644 +index 00000000..512ba694 +--- /dev/null ++++ b/src/daemon/common/nri/CMakeLists.txt +@@ -0,0 +1,13 @@ ++# get current directory sources files ++aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} local_common_nri_srcs) ++set(local_common_nri_incs ${CMAKE_CURRENT_SOURCE_DIR}) ++ ++set(COMMON_NRI_SRCS ++ ${local_common_nri_srcs} ++ PARENT_SCOPE ++) ++ ++set(COMMON_NRI_INCS ++ ${local_common_nri_incs} ++ PARENT_SCOPE ++) +diff --git a/src/daemon/common/nri/nri_convert.h b/src/daemon/common/nri/nri_convert.h +new file mode 100644 +index 00000000..883f7c41 +--- /dev/null ++++ b/src/daemon/common/nri/nri_convert.h +@@ -0,0 +1,36 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: zhongtao ++ * Create: 2024-03-16 ++ * Description: provide nri convert functions ++ *********************************************************************************/ ++#ifndef DAEMON_COMMON_NRI_NRI_CONVERT_H ++#define DAEMON_COMMON_NRI_NRI_CONVERT_H ++#include <map> ++#include <memory> ++#include <string> ++#include <vector> ++ ++#include "isula_libutils/nri_pod_sandbox.h" ++#include "isula_libutils/nri_container.h" ++#include "isula_libutils/nri_mount.h" ++#include "isula_libutils/nri_linux_resources.h" ++ ++#include "sandbox.h" ++#include "api_v1.pb.h" ++ ++auto PodSandboxToNRI(const std::shared_ptr<const sandbox::Sandbox> &sandbox, nri_pod_sandbox *pod) -> bool; ++auto ContainerToNRIByConConfig(const runtime::v1::ContainerConfig &containerConfig, nri_container *con) -> bool; ++auto ContainerToNRIByID(const std::string &id, nri_container *con) -> bool; ++auto PodSandboxesToNRI(const std::vector<std::unique_ptr<sandbox::Sandbox>> &arrs, nri_pod_sandbox **pod, int pod_len) -> bool; ++ ++auto LinuxResourcesFromNRI(const nri_linux_resources *src, runtime::v1::LinuxContainerResources &resources) -> bool; ++#endif // DAEMON_COMMON_NRI_NRI_CONVERT_H +diff --git a/src/daemon/common/nri/nri_spec.h b/src/daemon/common/nri/nri_spec.h +new file mode 100644 +index 00000000..e7c5035d +--- /dev/null ++++ b/src/daemon/common/nri/nri_spec.h +@@ -0,0 +1,24 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: zhongtao ++ * Create: 2024-07-17 ++ * Description: provide nri oci functions ++ *********************************************************************************/ ++ ++#ifndef DAEMON_COMMON_NRI_NRI_SPEC_H ++#define DAEMON_COMMON_NRI_NRI_SPEC_H ++ ++#include <isula_libutils/oci_runtime_spec.h> ++#include <isula_libutils/nri_container_adjustment.h> ++ ++int nri_adjust_oci_spec(const nri_container_adjustment *adjust, oci_runtime_spec *oci_spec); ++ ++#endif // DAEMON_COMMON_NRI_NRI_SPEC_H +\ No newline at end of file +diff --git a/src/daemon/common/nri/nri_utils.h b/src/daemon/common/nri/nri_utils.h +new file mode 100644 +index 00000000..3aa50ae4 +--- /dev/null ++++ b/src/daemon/common/nri/nri_utils.h +@@ -0,0 +1,71 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: zhongtao ++ * Create: 2024-07-17 ++ * Description: provide nri utils functions ++ *********************************************************************************/ ++#ifndef DAEMON_COMMON_NRI_NRI_UTILS_H ++#define DAEMON_COMMON_NRI_NRI_UTILS_H ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <stddef.h> ++ ++#include <isula_libutils/nri_create_container_request.h> ++#include <isula_libutils/nri_create_container_response.h> ++#include <isula_libutils/nri_update_container_request.h> ++#include <isula_libutils/nri_update_container_response.h> ++#include <isula_libutils/nri_container_update.h> ++#include <isula_libutils/nri_mount.h> ++ ++#include <isula_libutils/container_config.h> ++#include <isula_libutils/host_config.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef enum { ++ UNKNOWN = 0, ++ RUN_POD_SANDBOX = 1, ++ STOP_POD_SANDBOX = 2, ++ REMOVE_POD_SANDBOX = 3, ++ CREATE_CONTAINER = 4, ++ POST_CREATE_CONTAINER = 5, ++ START_CONTAINER = 6, ++ POST_START_CONTAINER = 7, ++ UPDATE_CONTAINER = 8, ++ POST_UPDATE_CONTAINER = 9, ++ STOP_CONTAINER = 10, ++ REMOVE_CONTAINER = 11, ++ LAST = 12, ++} NRI_Event; ++ ++bool copy_nri_mount(const nri_mount *src, nri_mount **dest); ++bool copy_nri_key_value(const nri_key_value *src, nri_key_value **dest); ++bool copy_nri_hook(const nri_hook *src, nri_hook **dest); ++bool copy_nri_posix_rlimit(const nri_posix_rlimit *src, nri_posix_rlimit **dest); ++bool copy_nri_linux_resources(const nri_linux_resources *src, nri_linux_resources **dest); ++bool copy_nri_linux_cpu(const nri_linux_cpu *src, nri_linux_cpu **dest); ++ ++bool is_marked_for_removal(const char* key, char **out); ++ ++bool realloc_and_copy_nri_hooks(nri_hook **targetHooks, size_t targetSize, const nri_hook **sourceHooks, size_t sourceLen); ++ ++bool init_nri_container_adjust(nri_container_adjustment **adjust); ++bool init_nri_container_update(nri_container_update **update, const char *id, uint8_t ignore_failure); ++bool init_nri_linux_resources(nri_linux_resources **resources); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // DAEMON_COMMON_NRI_NRI_UTILS_H +\ No newline at end of file +diff --git a/src/daemon/config/isulad_config.h b/src/daemon/config/isulad_config.h +index f29cd564..c57ca8d6 100644 +--- a/src/daemon/config/isulad_config.h ++++ b/src/daemon/config/isulad_config.h +@@ -40,6 +40,22 @@ struct isulad_conf { + #define DEFAULT_SANDBOXER_NAME "shim" + char *conf_get_sandbox_rootpath(void); + char *conf_get_sandbox_statepath(void); ++ ++#ifdef ENABLE_NRI ++#define DEFAULT_SOCKET_PATH "/var/run/nri/nri.sock" ++#define DEFAULT_MUX_SOCKET_PATH "/var/run/nri/nri_mux.sock" ++#define DEFAULT_PLUGIN_PATH "/opt/nri/plugins" ++#define DEFAULT_PLUGIN_CONFIG_PATH "/etc/nri/conf.d" ++#define DEFAULT_PLUGIN_REGISTRY_TIMEOUT 5 ++#define DEFAULT_PLUGIN_REQUST_TIMEOUT 2 ++bool conf_get_nri_support(void); ++bool conf_get_nri_external_support(void); ++char *conf_get_nri_plugin_config_path(void); ++char *conf_get_nri_plugin_path(void); ++char *conf_get_socket_path(void); ++uint64_t conf_get_nri_plugin_registration_timeout(void); ++uint64_t conf_get_nri_plugin_requst_timeout(void); ++#endif + #endif + + char *conf_get_isulad_pidfile(void); +diff --git a/src/daemon/modules/api/specs_api.h b/src/daemon/modules/api/specs_api.h +index 0999836b..6a1cd776 100644 +--- a/src/daemon/modules/api/specs_api.h ++++ b/src/daemon/modules/api/specs_api.h +@@ -58,6 +58,9 @@ int spec_module_init(void); + #ifdef ENABLE_CDI + int defs_process_add_multiple_env(defs_process *dp, const char **envs, size_t env_len); + int spec_add_multiple_process_env(oci_runtime_spec *oci_spec, const char **envs, size_t env_len); ++#endif/* ENABLE_CDI */ ++ ++#if defined (ENABLE_CDI) || defined(ENABLE_NRI) + int spec_add_device(oci_runtime_spec *oci_spec, defs_device *device); + int spec_add_linux_resources_device(oci_runtime_spec *oci_spec, bool allow, const char *dev_type, + int64_t major, int64_t minor, const char *access); +@@ -66,7 +69,12 @@ int spec_add_mount(oci_runtime_spec *oci_spec, defs_mount *mnt); + int spec_add_prestart_hook(oci_runtime_spec *oci_spec, defs_hook *prestart_hook); + int spec_add_poststart_hook(oci_runtime_spec *oci_spec, defs_hook *poststart_hook); + int spec_add_poststop_hook(oci_runtime_spec *oci_spec, defs_hook *poststop_hook); +-#endif /* ENABLE_CDI */ ++#endif /* ENABLE_CDI || ENABLE_NRI */ ++ ++#ifdef ENABLE_NRI ++int spec_add_linux_resources_hugepage_limit(oci_runtime_spec *oci_spec, const char *page_size, uint64_t limit); ++int spec_add_linux_resources_rlimit(oci_runtime_spec *oci_spec, const char *type, uint64_t hard, uint64_t soft); ++#endif /* ENABLE_NRI */ + + #ifdef __cplusplus + } +diff --git a/src/daemon/modules/spec/specs.c b/src/daemon/modules/spec/specs.c +index f0538e26..1fd9e5a8 100644 +--- a/src/daemon/modules/spec/specs.c ++++ b/src/daemon/modules/spec/specs.c +@@ -2608,7 +2608,7 @@ int spec_module_init(void) + static int add_env(defs_process *dp, const char *env, const char *key) + { + size_t i; +- ++ + for (i = 0; i < dp->env_len; i++) { + __isula_auto_free char *oci_key = NULL; + if (util_valid_split_env(dp->env[i], &oci_key, NULL) < 0) { +@@ -2684,7 +2684,9 @@ int spec_add_multiple_process_env(oci_runtime_spec *oci_spec, const char **envs, + + return ret; + } ++#endif /* ENABLE_CDI */ + ++#if defined (ENABLE_CDI) || defined(ENABLE_NRI) + int spec_add_device(oci_runtime_spec *oci_spec, defs_device *device) + { + int ret = 0; +@@ -2817,4 +2819,65 @@ SPEC_ADD_HOOKS_ITEM_DEF(prestart) + SPEC_ADD_HOOKS_ITEM_DEF(poststart) + SPEC_ADD_HOOKS_ITEM_DEF(poststop) + +-#endif /* ENABLE_CDI */ +\ No newline at end of file ++#endif /* ENABLE_CDI || ENABLE_NRI */ ++ ++#ifdef ENABLE_NRI ++int spec_add_linux_resources_hugepage_limit(oci_runtime_spec *oci_spec, const char *page_size, uint64_t limit) ++{ ++ int ret = 0; ++ defs_resources_hugepage_limits_element *hugepage_limit = NULL; ++ ++ ret = make_sure_oci_spec_linux_resources(oci_spec); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ hugepage_limit = util_common_calloc_s(sizeof(*hugepage_limit)); ++ if (hugepage_limit == NULL) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ hugepage_limit->page_size = util_strdup_s(page_size); ++ hugepage_limit->limit = limit; ++ ++ if (util_mem_realloc((void **)&oci_spec->linux->resources->hugepage_limits, ++ (oci_spec->linux->resources->hugepage_limits_len + 1) * sizeof(defs_resources_hugepage_limits_element *), ++ (void *)oci_spec->linux->resources->hugepage_limits, ++ oci_spec->linux->resources->hugepage_limits_len * sizeof(defs_resources_hugepage_limits_element *)) != 0) { ++ ERROR("Out of memory"); ++ free_defs_resources_hugepage_limits_element(hugepage_limit); ++ return -1; ++ } ++ oci_spec->linux->resources->hugepage_limits[oci_spec->linux->resources->hugepage_limits_len] = hugepage_limit; ++ oci_spec->linux->resources->hugepage_limits_len++; ++ ++ return 0; ++} ++ ++int spec_add_linux_resources_rlimit(oci_runtime_spec *oci_spec, const char *type, uint64_t hard, uint64_t soft) ++{ ++ int ret = 0; ++ defs_process_rlimits_element *rlimit = NULL; ++ ++ ret = make_sure_oci_spec_linux_resources(oci_spec); ++ if (ret < 0) { ++ return -1; ++ } ++ ++ rlimit = util_common_calloc_s(sizeof(*rlimit)); ++ if (rlimit == NULL) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ rlimit->type = util_strdup_s(type); ++ rlimit->hard = hard; ++ rlimit->soft = soft; ++ ++ if (do_merge_one_ulimit_override(oci_spec, rlimit) != 0) { ++ ERROR("Failed to merge one nri ulimit to oci spec"); ++ return -1; ++ } ++ ++ return 0; ++} ++#endif /* ENABLE_NRI */ +\ No newline at end of file +diff --git a/src/daemon/nri/CMakeLists.txt b/src/daemon/nri/CMakeLists.txt +new file mode 100644 +index 00000000..361d79f8 +--- /dev/null ++++ b/src/daemon/nri/CMakeLists.txt +@@ -0,0 +1,6 @@ ++# get current directory sources files ++aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} nri_top_srcs) ++ ++set(NRI_INCS ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE) ++ ++set(NRI_SRCS ${nri_top_srcs} PARENT_SCOPE) +diff --git a/src/daemon/nri/nri_adaption.h b/src/daemon/nri/nri_adaption.h +new file mode 100644 +index 00000000..7f0640df +--- /dev/null ++++ b/src/daemon/nri/nri_adaption.h +@@ -0,0 +1,123 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: zhongtao ++ * Create: 2024-03-15 ++ * Description: provide plugin manager(NRI adaption) class definition ++ *********************************************************************************/ ++ ++#ifndef DAEMON_NRI_PLUGIN_NRI_ADAPTION_H ++#define DAEMON_NRI_PLUGIN_NRI_ADAPTION_H ++ ++// #include "read_write_lock.h" ++#include <isula_libutils/nri_update_containers_request.h> ++#include <isula_libutils/nri_update_containers_response.h> ++ ++#include "plugin.h" ++#include "sandbox.h" ++#include "v1_cri_container_manager_service.h" ++ ++const std::string PluginNameEnv = "NRI_PLUGIN_NAME"; ++const std::string PluginIdxEnv = "NRI_PLUGIN_IDX"; ++const std::string PluginSocketEnv = "NRI_PLUGIN_SOCKET"; ++ ++struct nri_plugin_exec_args_t { ++ const char *workdir; ++ const char *cmd; ++ const char *name; ++ const char *index; ++ const uint32_t sockFd; ++}; ++ ++class NRIAdaptation { ++public: ++ // Singleton ++ static NRIAdaptation *GetInstance() noexcept; ++ ++ // initialize value ++ auto Init(Errors &error) -> bool; ++ ++ auto GetSockpath(std::vector<std::string> &paths) -> bool; ++ ++ // Stop plugins. ++ auto StopPlugins() -> bool; ++ ++ void RemoveClosedPlugins(); ++ ++ auto GetPluginByIndex(const std::string &index) -> std::shared_ptr<NRIPlugin>; ++ void AddPluginByIndex(const std::string &index, std::shared_ptr<NRIPlugin> plugin); ++ void RemovePluginByIndex(const std::string &index); ++ ++ auto RunPodSandbox(std::shared_ptr<const sandbox::Sandbox> sandbox, Errors &error) ->bool; ++ auto StopPodSandbox(std::shared_ptr<const sandbox::Sandbox> sandbox, Errors &error) ->bool; ++ auto RemovePodSandbox(std::shared_ptr<const sandbox::Sandbox> sandbox, Errors &error) ->bool; ++ auto CreateContainer(std::shared_ptr<const sandbox::Sandbox> sandbox, const std::string &conId, const runtime::v1::ContainerConfig &containerConfig, nri_container_adjustment **adjust, Errors &error) -> bool; ++ auto PostCreateContainer(const std::string &conId, Errors &error) ->bool; ++ auto UndoCreateContainer(std::shared_ptr<const sandbox::Sandbox> sandbox, const std::string &conId, Errors &error) -> bool; ++ auto StartContainer(const std::string &conId, Errors &error) ->bool; ++ auto PostStartContainer(const std::string &conId, Errors &error) ->bool; ++ auto UpdateContainer(const std::string &conId, Errors &error) ->bool; ++ auto PostUpdateContainer(const std::string &conId, Errors &error) ->bool; ++ auto StopContainer(const std::string &conId, Errors &error) ->bool; ++ auto RemoveContainer(const std::string &conId, Errors &error) ->bool; ++ auto StateChange(nri_state_change_event *evt, Errors &error) ->bool; ++ auto updateContainers(const nri_update_containers_request *req, nri_update_containers_response **resp) ->bool; ++ ++ auto NewExternalPlugin(int fd) -> bool; ++private: ++ NRIAdaptation() = default; ++ NRIAdaptation(const NRIAdaptation &other) = delete; ++ NRIAdaptation &operator=(const NRIAdaptation &) = delete; ++ virtual ~NRIAdaptation(); ++ ++ auto StartPlugin() -> bool; ++ auto NewLaunchedPlugin(const std::shared_ptr<NRIPlugin> &) -> bool; ++ auto DiscoverPlugins(std::map<std::string, std::shared_ptr<NRIPlugin>> &map) -> bool; ++ // Synchronizing NRI (plugin) with current runtime state ++ auto SyncPlugin() -> bool; ++ ++ auto SortPlugins() -> bool; ++ void GetClosedPlugins(std::vector<std::string> &closedPlugin); ++ ++ auto IsSupport() -> bool; ++ ++ auto ApplyUpdates(const std::vector<nri_container_update *> &update, std::vector<nri_container_update *> &failed, bool getFailed, ++ Errors &error) -> bool; ++ ++ auto NRIPodSandbox(const std::shared_ptr<const sandbox::Sandbox> &sandbox, Errors& error) -> std::unique_ptr<CStructWrapper<nri_pod_sandbox>>; ++ auto NRIContainerByConConfig(const std::shared_ptr<const sandbox::Sandbox> &sandbox, const runtime::v1::ContainerConfig &containerConfig, Errors& error) -> std::unique_ptr<CStructWrapper<nri_container>>; ++ auto NRIContainerByID(const std::string &id, Errors& error) -> std::unique_ptr<CStructWrapper<nri_container>>; ++ ++ auto GetNRIPluginConfigPath(void) -> std::string; ++ auto GetNRIPluginPath(void) -> std::string; ++ auto GetNRISockPath(void) -> std::string; ++private: ++ RWMutex m_mutex; ++ static std::atomic<NRIAdaptation *> m_instance; ++ bool m_support; ++ bool m_external_support; ++ std::string m_version; ++ std::string m_sock_path; ++ std::string m_pluginConfigPath; ++ std::string m_pluginPath; ++ std::vector<std::string> m_socketPathArr; ++ std::string m_disableConnections; ++ // id --> NRIPlugin map ++ std::map<std::string, std::shared_ptr<NRIPlugin>> m_storeMap; ++ // TODO:plugin monitor thread id?? ++ // shutdown() to clean resource ++ // init to create thread ++ // todo: if Singleton? ++ std::unique_ptr<CRIV1::ContainerManagerService> m_containerManager; ++ int64_t m_plugin_registration_timeout; ++ int64_t m_plugin_requst_timeout; ++}; ++ ++#endif // DAEMON_NRI_PLUGIN_NRI_ADAPTION_H +\ No newline at end of file +diff --git a/src/daemon/nri/nri_helpers.h b/src/daemon/nri/nri_helpers.h +new file mode 100644 +index 00000000..06ee8419 +--- /dev/null ++++ b/src/daemon/nri/nri_helpers.h +@@ -0,0 +1,63 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: zhongtao ++ * Create: 2024-07-13 ++ * Description: provide nri helpers functions ++ *********************************************************************************/ ++#ifndef DAEMON_NRI_PLUGIN_NRI_HELPERS_H ++#define DAEMON_NRI_PLUGIN_NRI_HELPERS_H ++ ++#include <map> ++#include <memory> ++#include <string> ++#include <vector> ++ ++#include <isula_libutils/nri_create_container_request.h> ++#include <isula_libutils/nri_create_container_response.h> ++#include <isula_libutils/nri_update_container_request.h> ++#include <isula_libutils/nri_update_container_response.h> ++#include <isula_libutils/nri_container_update.h> ++#include <isula_libutils/nri_mount.h> ++ ++#include <isula_libutils/container_config.h> ++#include <isula_libutils/host_config.h> ++ ++#include "errors.h" ++ ++namespace NRIHelpers { ++std::string MarkForRemoval(const std::string &key); ++ ++auto GetPluginConfig(std::string &idx, std::string &name, std::string &config) -> bool; ++ ++std::string GenerateRandomExternalName(void); ++ ++bool CheckPluginIndex(const std::string &idx); ++ ++template <typename T> ++void freeArray(T ** &arr, int size) ++{ ++ if (arr == NULL) { ++ return; ++ } ++ ++ for (int i = 0; i < size; i++) { ++ if (arr[i] == NULL) { ++ return; ++ } ++ free(arr[i]); ++ } ++ ++ free(arr); ++ arr = NULL; ++} ++}; // namespace NRIHelpers ++ ++#endif // DAEMON_NRI_PLUGIN_NRI_HELPERS_H +diff --git a/src/daemon/nri/nri_plugin_ops.h b/src/daemon/nri/nri_plugin_ops.h +new file mode 100644 +index 00000000..37d437d2 +--- /dev/null ++++ b/src/daemon/nri/nri_plugin_ops.h +@@ -0,0 +1,38 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: zhongtaoo ++ * Create: 2024-03-26 ++ * Description: provide nri plugin api definition ++ ******************************************************************************/ ++ ++#ifndef DAEMON_NRI_PLUGIN_OPS_H ++#define DAEMON_NRI_PLUGIN_OPS_H ++ ++#include <isula_libutils/nri_update_containers_request.h> ++#include <isula_libutils/nri_update_containers_response.h> ++#include <isula_libutils/nri_register_plugin_request.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++bool nri_adaption_init(void); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++int nri_update_containers(const nri_update_containers_request *request, nri_update_containers_response **response); ++int nri_registry_containers(const nri_register_plugin_request *request); ++ ++int nri_external_plugin_connect(int fd); ++ ++#endif // DAEMON_NRI_PLUGIN_OPS_H +diff --git a/src/daemon/nri/nri_result.h b/src/daemon/nri/nri_result.h +new file mode 100644 +index 00000000..f2896ea0 +--- /dev/null ++++ b/src/daemon/nri/nri_result.h +@@ -0,0 +1,114 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: zhongtao ++ * Create: 2024-06-29 ++ * Description: provide nri result definition ++ *********************************************************************************/ ++ ++#ifndef DAEMON_NRI_PLUGIN_NRI_RESULT_H ++#define DAEMON_NRI_PLUGIN_NRI_RESULT_H ++ ++#include <map> ++ ++#include <isula_libutils/nri_create_container_request.h> ++#include <isula_libutils/nri_create_container_response.h> ++#include <isula_libutils/nri_update_container_request.h> ++#include <isula_libutils/nri_update_container_response.h> ++#include <isula_libutils/nri_container_update.h> ++#include <isula_libutils/nri_mount.h> ++ ++#include "api_v1.pb.h" ++#include "nri_helpers.h" ++#include "nri_utils.h" ++ ++using EventMask = std::int32_t; ++ ++const EventMask ValidEvents = (1 << (LAST - 1)) - 1; ++ ++struct owners { ++ std::map<std::string, std::string> annotations; ++ std::map<std::string, std::string> mounts; ++ std::map<std::string, std::string> devices; ++ std::map<std::string, std::string> env; ++ std::string memLimit; ++ std::string memReservation; ++ std::string memSwapLimit; ++ std::string memKernelLimit; ++ std::string memTCPLimit; ++ std::string memSwappiness; ++ std::string memDisableOomKiller; ++ std::string memUseHierarchy; ++ std::string cpuShares; ++ std::string cpuQuota; ++ std::string cpuPeriod; ++ std::string cpuRealtimeRuntime; ++ std::string cpuRealtimePeriod; ++ std::string cpusetCpus; ++ std::string cpusetMems; ++ std::map<std::string, std::string> hugepageLimits; ++ std::string blockioClass; ++ std::string rdtClass; ++ std::map<std::string, std::string> unified; ++ std::string cgroupsPath; ++ std::map<std::string, std::string> rlimits; ++}; ++ ++struct resultReply { ++ nri_container_adjustment* adjust; ++ std::vector<nri_container_update*> update; ++}; ++ ++using resultOwners = std::map<std::string, owners>; ++ ++class pluginResult { ++public: ++ pluginResult() = default; ++ ++ ~pluginResult() = default; ++ ++ auto InitByConId(std::string conId) -> bool; ++ auto InitByUpdateReq(nri_update_container_request *req) -> bool; ++ ++ auto GetReplyUpdate() -> std::vector<nri_container_update *>; ++ auto GetReplyAdjust() -> nri_container_adjustment *; ++ ++ auto Apply(int32_t event, nri_container_adjustment *adjust, nri_container_update **update, size_t update_len, ++ const std::string &plugin) -> bool; ++ auto Update(nri_container_update **updates, size_t update_len, const std::string &plugin) -> bool; ++ ++private: ++ auto GetContainerUpdate(nri_container_update *update, const std::string &plugin, nri_container_update **out) -> bool; ++ auto UpdateResources(nri_container_update *reply, nri_container_update *u, const std::string &plugin) -> bool; ++ ++ auto InitReply(void) -> bool; ++ ++ auto Adjust(nri_container_adjustment *adjust, const std::string &plugin) -> bool; ++ ++ auto AdjustAnnotations(json_map_string_string *annos, const std::string &plugin) -> bool; ++ auto AdjustMounts(nri_mount **mounts, size_t mounts_size, const std::string &plugin) -> bool; ++ auto AdjustEnv(nri_key_value **envs, size_t envs_size, const std::string &plugin) -> bool; ++ auto AdjustHooks(nri_hooks *hooks, const std::string &plugin) -> bool; ++ auto AdjustDevices(nri_linux_device **devices, size_t devices_size, const std::string &plugin) -> bool; ++ auto AdjustResources(nri_linux_resources *resources, const std::string &plugin) -> bool; ++ bool ClaimAndCopyResources(nri_linux_resources *src, std::string &id, const std::string &plugin, ++ nri_linux_resources *dest); ++ auto AdjustCgroupsPath(char *path, const std::string &plugin) -> bool; ++ auto AdjustRlimits(nri_posix_rlimit **rlimits, size_t rlimits_len, const std::string &plugin) -> bool; ++ ++private: ++ std::string m_conId; ++ nri_linux_resources *m_update_req; ++ resultReply m_reply; ++ std::map<std::string, nri_container_update *> m_updates; ++ resultOwners m_owners; ++}; ++ ++#endif +\ No newline at end of file +diff --git a/src/daemon/nri/plugin.h b/src/daemon/nri/plugin.h +new file mode 100644 +index 00000000..f60a9b3d +--- /dev/null ++++ b/src/daemon/nri/plugin.h +@@ -0,0 +1,95 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: zhongtao ++ * Create: 2024-03-15 ++ * Description: provide plugin class definition ++ *********************************************************************************/ ++ ++#ifndef DAEMON_NRI_PLUGIN_PLUGIN_H ++#define DAEMON_NRI_PLUGIN_PLUGIN_H ++ ++#include <condition_variable> ++ ++#include <isula_libutils/nri_stop_container_request.h> ++#include <isula_libutils/nri_stop_container_response.h> ++#include <isula_libutils/nri_state_change_event.h> ++ ++#include "errors.h" ++#include "read_write_lock.h" ++#include "nri_result.h" ++ ++const std::string NRIRruntime = "v2"; ++const std::string NRIVersion = "2.0.0-beta.2+unknown"; ++ ++class NRIPlugin { ++public: ++ // init client conn ++ NRIPlugin(std::string &idx, std::string &name, std::string &config); ++ NRIPlugin(int fd, std::string &name); ++ // todo: close client conn ?? or single close func? ++ virtual ~NRIPlugin() = default; ++ // wait for plugin to register, then configure it. ++ auto Start(int64_t registry_timeout, int64_t request_timeout) -> bool; ++ // close a plugin shutting down its multiplexed ttrpc connections. ++ auto Close(void) -> bool; ++ // stop a plugin (if it was launched by us) ++ auto Stop(void) -> bool; ++ ++ // Name returns a string indentication for the plugin. ++ auto GetName(void) -> const std::string &; ++ auto GetIndex(void) -> const std::string &; ++ auto GetPeerSockFd(void) -> uint32_t; ++ auto GetQualifiedName(void) -> std::string; ++ ++ void SetReady(void); ++ void SetPid(int pid); ++ ++ auto IsClose(void) -> bool; ++ ++ auto CreateSocketPair(void) -> bool; ++ ++ auto Configure(Errors &error) -> bool; ++ // Only called in external plugin scenario ++ auto Synchronize(std::vector<std::unique_ptr<nri_pod_sandbox>> pods, ++ std::vector<std::unique_ptr<nri_container>> &containers, nri_container_update ***update, size_t update_len, ++ Errors &error) -> bool; ++ auto CreateContainer(nri_create_container_request *req, nri_create_container_response **resp, Errors &error) -> bool; ++ auto UpdateContainer(nri_update_container_request *req, nri_update_container_response **resp, Errors &error) -> bool; ++ auto StopContainer(nri_stop_container_request *req, nri_stop_container_response **resp, Errors &error) -> bool; ++ auto StateChange(nri_state_change_event *evt, Errors &error) -> bool; ++ ++private: ++ auto Connect(int64_t timeout) -> bool; ++ ++ auto WaitForReady(int64_t timeout) -> bool; ++ auto IsSetEvent(EventMask e) -> bool; ++ ++private: ++ RWMutex m_mutex; ++ bool m_external; ++ std::string m_idx; ++ std::string m_name; ++ std::string m_config; ++ int m_pid; ++ std::string m_cmd; ++ std::vector<uint32_t> m_sockFds; ++ std::string m_localFileName; ++ std::string m_peerFileName; ++ // TODO:zhontao monitor? ++ bool m_closed; ++ std::mutex m_readyMutex; ++ bool m_ready; ++ std::condition_variable m_condition; ++ EventMask m_events; ++}; ++ ++ ++#endif // DAEMON_NRI_PLUGIN_PLUGIN_H +\ No newline at end of file +diff --git a/src/utils/cpputils/transform.cc b/src/utils/cpputils/transform.cc +index 74c178a9..51c154fb 100644 +--- a/src/utils/cpputils/transform.cc ++++ b/src/utils/cpputils/transform.cc +@@ -89,4 +89,20 @@ void CharArrayToStringVector(const char **src, size_t len, std::vector<std::stri + } + } + ++ ++auto RepeatedPtrFieldToCharArray(const google::protobuf::RepeatedPtrField<std::string> &ptrs) -> char ** ++{ ++ size_t len = ptrs.size(); ++ char **result = (char **)util_smart_calloc_s(sizeof(char *), (len + 1)); ++ if (result == nullptr) { ++ return nullptr; ++ } ++ size_t i {}; ++ for (const auto &it : ptrs) { ++ result[i++] = util_strdup_s(it.c_str()); ++ } ++ ++ return result; ++} ++ + } // namespace Transform +diff --git a/src/utils/cpputils/transform.h b/src/utils/cpputils/transform.h +index 476f39a6..57c58d9e 100644 +--- a/src/utils/cpputils/transform.h ++++ b/src/utils/cpputils/transform.h +@@ -35,6 +35,8 @@ auto StringVectorToCharArray(std::vector<std::string> &strVec) -> char **; + + void CharArrayToStringVector(const char **src, size_t len, std::vector<std::string> &dest); + ++auto RepeatedPtrFieldToCharArray(const google::protobuf::RepeatedPtrField<std::string> &ptrs) -> char **; ++ + }; // namespace Transform + + #endif // UTILS_CPPUTILS_TRANSFORM_H +\ No newline at end of file +diff --git a/src/utils/cutils/utils.c b/src/utils/cutils/utils.c +index 9a33f935..f81a9141 100644 +--- a/src/utils/cutils/utils.c ++++ b/src/utils/cutils/utils.c +@@ -1699,3 +1699,10 @@ int util_chown_for_shm(const char *shm_path, const char *user_remap) + + return 0; + } ++ ++void set_child_process_pdeathsig(void) ++{ ++ if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0) { ++ SYSERROR("Failed to set child process pdeathsig"); ++ } ++} +\ No newline at end of file +diff --git a/src/utils/cutils/utils.h b/src/utils/cutils/utils.h +index ce0ca703..76684ed3 100644 +--- a/src/utils/cutils/utils.h ++++ b/src/utils/cutils/utils.h +@@ -409,6 +409,8 @@ int util_create_shm_path(const char *spath, const int64_t shm_size); + + int util_chown_for_shm(const char *shm_path, const char *user_remap); + ++void set_child_process_pdeathsig(void); ++ + /** + * retry_cnt: max count of call cb; + * interval_us: how many us to sleep, after call cb; +diff --git a/src/utils/tar/util_archive.c b/src/utils/tar/util_archive.c +index 204dab83..985e0f16 100644 +--- a/src/utils/tar/util_archive.c ++++ b/src/utils/tar/util_archive.c +@@ -812,13 +812,6 @@ static void close_archive_pipes_fd(int *pipes, size_t pipe_size) + } + } + +-static void set_child_process_pdeathsig(void) +-{ +- if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0) { +- SYSERROR("Failed to set child process pdeathsig"); +- } +-} +- + int archive_unpack(const struct io_read_wrapper *content, const char *dstdir, const struct archive_options *options, + const char *root_dir, char **errmsg) + { +-- +2.25.1 + |