From 99b51fed8c3062aa3f5c39eaf21ef511e3aff326 Mon Sep 17 00:00:00 2001 From: Zhangxiaoyu Date: Wed, 8 Jul 2020 15:06:45 +0800 Subject: [PATCH] transform form source code to tar + patch Signed-off-by: Zhangxiaoyu --- 0001-fix-wrong-license.patch | 80 + 0002-support-import-rootfs-to-be-image.patch | 55 + 0003-support-calico.patch | 30 + 0004-improve-check-driver-of-log.patch | 373 +++ 0005-improve-llt-framework.patch | 246 ++ 0006-fix-log-test-error.patch | 26 + 0007-improve-html-show-result.patch | 26 + 0008-change-tests-name.patch | 189 ++ ...-Request-49-change-name-of-testcases.patch | 188 ++ 0010-change-tests-name.patch | 227 ++ 0011-support-fuzz-test.patch | 241 ++ CMakeLists.txt | 89 - License/LICENSE | 127 - README.md | 15 - cmake/checker.cmake | 35 - cmake/set_build_flags.cmake | 17 - config.h.in | 1 - contrib/oci.config.json | 1672 ----------- lcr-2.0.2.tar.gz | Bin 0 -> 112181 bytes lcr.pc.in | 12 - lcr.spec | 53 +- lcr.yaml | 41 + src/CMakeLists.txt | 54 - src/buffer.c | 228 -- src/buffer.h | 32 - src/conf.c | 2590 ----------------- src/conf.h | 113 - src/constants.h | 52 - src/error.c | 117 - src/error.h | 68 - src/json/CMakeLists.txt | 2 - src/json/oci_runtime_hooks.c | 77 - src/json/oci_runtime_hooks.h | 24 - src/json/schema/CMakeLists.txt | 16 - src/json/schema/schema/defs.json | 233 -- .../schema/oci/runtime/config-linux.json | 271 -- .../schema/schema/oci/runtime/defs-linux.json | 270 -- src/json/schema/schema/oci/runtime/spec.json | 216 -- src/json/schema/schema/oci/runtime/state.json | 45 - .../schema/schema/start-generate-config.json | 18 - src/json/schema/src/CMakeLists.txt | 3 - src/json/schema/src/common_c.py | 1185 -------- src/json/schema/src/common_h.py | 213 -- src/json/schema/src/generate.py | 841 ------ src/json/schema/src/headers.py | 220 -- src/json/schema/src/helpers.py | 333 --- src/json/schema/src/read_file.c | 142 - src/json/schema/src/read_file.h | 25 - src/json/schema/src/sources.py | 1008 ------- src/lcr_list.h | 138 - src/lcrcontainer.c | 1237 -------- src/lcrcontainer.h | 298 -- src/lcrcontainer_execute.c | 750 ----- src/lcrcontainer_execute.h | 36 - src/lcrcontainer_extend.c | 1081 ------- src/lcrcontainer_extend.h | 87 - src/log.c | 386 --- src/log.h | 124 - src/utils.c | 1252 -------- src/utils.h | 196 -- tools/static_check | 554 ---- update-version.bash | 33 +- 62 files changed, 1787 insertions(+), 16524 deletions(-) create mode 100644 0001-fix-wrong-license.patch create mode 100644 0002-support-import-rootfs-to-be-image.patch create mode 100644 0003-support-calico.patch create mode 100644 0004-improve-check-driver-of-log.patch create mode 100644 0005-improve-llt-framework.patch create mode 100644 0006-fix-log-test-error.patch create mode 100644 0007-improve-html-show-result.patch create mode 100644 0008-change-tests-name.patch create mode 100644 0009-Pull-Request-49-change-name-of-testcases.patch create mode 100644 0010-change-tests-name.patch create mode 100644 0011-support-fuzz-test.patch delete mode 100644 CMakeLists.txt delete mode 100644 License/LICENSE delete mode 100644 README.md delete mode 100644 cmake/checker.cmake delete mode 100644 cmake/set_build_flags.cmake delete mode 100644 config.h.in delete mode 100644 contrib/oci.config.json create mode 100644 lcr-2.0.2.tar.gz delete mode 100644 lcr.pc.in create mode 100644 lcr.yaml delete mode 100644 src/CMakeLists.txt delete mode 100644 src/buffer.c delete mode 100644 src/buffer.h delete mode 100644 src/conf.c delete mode 100644 src/conf.h delete mode 100644 src/constants.h delete mode 100644 src/error.c delete mode 100644 src/error.h delete mode 100644 src/json/CMakeLists.txt delete mode 100644 src/json/oci_runtime_hooks.c delete mode 100644 src/json/oci_runtime_hooks.h delete mode 100644 src/json/schema/CMakeLists.txt delete mode 100644 src/json/schema/schema/defs.json delete mode 100644 src/json/schema/schema/oci/runtime/config-linux.json delete mode 100644 src/json/schema/schema/oci/runtime/defs-linux.json delete mode 100644 src/json/schema/schema/oci/runtime/spec.json delete mode 100644 src/json/schema/schema/oci/runtime/state.json delete mode 100644 src/json/schema/schema/start-generate-config.json delete mode 100644 src/json/schema/src/CMakeLists.txt delete mode 100644 src/json/schema/src/common_c.py delete mode 100644 src/json/schema/src/common_h.py delete mode 100644 src/json/schema/src/generate.py delete mode 100644 src/json/schema/src/headers.py delete mode 100644 src/json/schema/src/helpers.py delete mode 100644 src/json/schema/src/read_file.c delete mode 100644 src/json/schema/src/read_file.h delete mode 100644 src/json/schema/src/sources.py delete mode 100644 src/lcr_list.h delete mode 100644 src/lcrcontainer.c delete mode 100644 src/lcrcontainer.h delete mode 100644 src/lcrcontainer_execute.c delete mode 100644 src/lcrcontainer_execute.h delete mode 100644 src/lcrcontainer_extend.c delete mode 100644 src/lcrcontainer_extend.h delete mode 100644 src/log.c delete mode 100644 src/log.h delete mode 100644 src/utils.c delete mode 100644 src/utils.h delete mode 100755 tools/static_check diff --git a/0001-fix-wrong-license.patch b/0001-fix-wrong-license.patch new file mode 100644 index 0000000..ab7a97c --- /dev/null +++ b/0001-fix-wrong-license.patch @@ -0,0 +1,80 @@ +From 74c5abe35a931aca850d5619faecbd62e75d9fb2 Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Tue, 26 May 2020 20:04:13 +0800 +Subject: [PATCH 01/11] fix wrong license + +Signed-off-by: haozi007 +--- + README.md | 2 +- + lcr.spec | 2 +- + update-version.bash | 33 +++++++++++++++++++++------------ + 3 files changed, 23 insertions(+), 14 deletions(-) + +diff --git a/README.md b/README.md +index 1984855..a1289c5 100644 +--- a/README.md ++++ b/README.md +@@ -12,4 +12,4 @@ iSulad follows the kernel coding conventions. You can find a detailed introducti + + ## Licensing + +-lcr is licensed under the Mulan PSL v2. ++lcr is licensed under the LGPLv2.1+. +diff --git a/lcr.spec b/lcr.spec +index a706537..5644fdf 100644 +--- a/lcr.spec ++++ b/lcr.spec +@@ -9,7 +9,7 @@ URL: lcr + Source: lcr-2.0.tar.gz + Summary: Lightweight Container Runtime + Group: Applications/System +-License: Mulan PSL v2 ++License: LGPLv2.1+ + BuildRoot: %{_tmppath}/lcr-%{version} + + BuildRequires: cmake +diff --git a/update-version.bash b/update-version.bash +index 77a6434..76697b8 100755 +--- a/update-version.bash ++++ b/update-version.bash +@@ -1,16 +1,25 @@ + ####################################################################### +-##- @Copyright (C) Huawei Technologies., Ltd. 2019. All rights reserved. +-# - lcr 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. +-##- @Description: generate cetification +-##- @Author: wujing +-##- @Create: 2019-04-25 ++# lcr: utils library for iSula ++# ++# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++# ++# Authors: ++# Haozi007 ++# ++# 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.1 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, write to the Free Software ++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++# + ####################################################################### + #!/bin/bash + # +-- +2.25.1 + diff --git a/0002-support-import-rootfs-to-be-image.patch b/0002-support-import-rootfs-to-be-image.patch new file mode 100644 index 0000000..2271cde --- /dev/null +++ b/0002-support-import-rootfs-to-be-image.patch @@ -0,0 +1,55 @@ +From 15b7cc66a03f26c35dfc551a960edc24e5c52440 Mon Sep 17 00:00:00 2001 +From: WangFengTu +Date: Wed, 27 May 2020 11:25:56 +0800 +Subject: [PATCH 02/11] support import rootfs to be image + +Signed-off-by: WangFengTu +--- + src/json/schema/image/import-request.json | 12 ++++++++++++ + src/json/schema/image/import-response.json | 15 +++++++++++++++ + 2 files changed, 27 insertions(+) + create mode 100644 src/json/schema/image/import-request.json + create mode 100644 src/json/schema/image/import-response.json + +diff --git a/src/json/schema/image/import-request.json b/src/json/schema/image/import-request.json +new file mode 100644 +index 0000000..e2fe7bc +--- /dev/null ++++ b/src/json/schema/image/import-request.json +@@ -0,0 +1,12 @@ ++{ ++ "$schema": "http://json-schema.org/draft-04/schema#", ++ "type": "object", ++ "properties": { ++ "file": { ++ "type": "string" ++ }, ++ "tag": { ++ "type": "string" ++ } ++ } ++} +diff --git a/src/json/schema/image/import-response.json b/src/json/schema/image/import-response.json +new file mode 100644 +index 0000000..048f43d +--- /dev/null ++++ b/src/json/schema/image/import-response.json +@@ -0,0 +1,15 @@ ++{ ++ "$schema": "http://json-schema.org/draft-04/schema#", ++ "type": "object", ++ "properties": { ++ "id": { ++ "type": "string" ++ }, ++ "cc": { ++ "type": "uint32" ++ }, ++ "errmsg": { ++ "type": "string" ++ } ++ } ++} +-- +2.25.1 + diff --git a/0003-support-calico.patch b/0003-support-calico.patch new file mode 100644 index 0000000..32877e4 --- /dev/null +++ b/0003-support-calico.patch @@ -0,0 +1,30 @@ +From 855d567b2bd92aada6c7d61a75aae2d5441a1efe Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Tue, 2 Jun 2020 10:15:58 +0800 +Subject: [PATCH 03/11] support calico + +Signed-off-by: haozi007 +--- + src/json/schema/cni/net_conf.json | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/json/schema/cni/net_conf.json b/src/json/schema/cni/net_conf.json +index 3b40017..89427ae 100644 +--- a/src/json/schema/cni/net_conf.json ++++ b/src/json/schema/cni/net_conf.json +@@ -100,6 +100,12 @@ + "type": "string" + }, + "mtu": { ++ "type": "int32" ++ }, ++ "datastore_type": { ++ "type": "string" ++ }, ++ "nodename": { + "type": "string" + }, + "policy": { +-- +2.25.1 + diff --git a/0004-improve-check-driver-of-log.patch b/0004-improve-check-driver-of-log.patch new file mode 100644 index 0000000..aa8219e --- /dev/null +++ b/0004-improve-check-driver-of-log.patch @@ -0,0 +1,373 @@ +From 72c179403743bd9bd82f0e4d80c558d883b973ac Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Tue, 9 Jun 2020 14:44:51 +0800 +Subject: [PATCH 04/11] improve check driver of log + +1. add llt for log +2. improve init driver of log + +Signed-off-by: haozi007 +--- + lcr.spec | 2 +- + tests/json_llt.cpp | 17 ++++++++-- + tests/log_llt.cpp | 53 +++++++++++++++++++++++++++++-- + third_party/log.c | 78 +++++++++++++++++++++++++--------------------- + third_party/log.h | 1 + + tools/static_check | 10 +++--- + 6 files changed, 113 insertions(+), 48 deletions(-) + +diff --git a/lcr.spec b/lcr.spec +index 5644fdf..0963e53 100644 +--- a/lcr.spec ++++ b/lcr.spec +@@ -1,5 +1,5 @@ + %global _version 2.0.2 +-%global _release 20200526.162423.gitf1095eab ++%global _release 20200609.145938.gita2be0373 + %global _inner_name isula_libutils + + Name: lcr +diff --git a/tests/json_llt.cpp b/tests/json_llt.cpp +index 4a66305..9622ed4 100644 +--- a/tests/json_llt.cpp ++++ b/tests/json_llt.cpp +@@ -33,11 +33,11 @@ + TEST(json_testcase, test_oci_runtime_spec_hooks) + { + const char *fname = "./ocihook.json"; +- oci_runtime_spec_hooks *hooks = NULL; ++ oci_runtime_spec_hooks *hooks = nullptr; + parser_error jerr = nullptr; + char *jstr = nullptr; + +- hooks = oci_runtime_spec_hooks_parse_file(fname, NULL, &jerr); ++ hooks = oci_runtime_spec_hooks_parse_file(fname, nullptr, &jerr); + ASSERT_EQ(jerr, nullptr) << "parse hook failed: " << jerr; + ASSERT_NE(hooks, nullptr); + +@@ -82,11 +82,22 @@ TEST(json_testcase, test_oci_runtime_spec_hooks) + TEST(json_testcase, test_json_readfile) + { + const char *fname = "./ocihook.json"; +- char *jstr = NULL; ++ const char *not_exist = "/tmp/not_exist.json"; ++ char *jstr = nullptr; + size_t len = 0; + + jstr = read_file(fname, &len); + ASSERT_NE(jstr, nullptr); + ASSERT_EQ(len, 527); ++ free(jstr); ++ len = 0; ++ ++ jstr = read_file(not_exist, &len); ++ ASSERT_EQ(jstr, nullptr); ++ ASSERT_EQ(len, 0); ++ len = 0; ++ ++ jstr = read_file(nullptr, nullptr); ++ ASSERT_EQ(jstr, nullptr); + } + +diff --git a/tests/log_llt.cpp b/tests/log_llt.cpp +index 7d4a3d4..dbdebad 100644 +--- a/tests/log_llt.cpp ++++ b/tests/log_llt.cpp +@@ -42,7 +42,7 @@ TEST(log_testcases, test_isula_libutils_default_log_config) + ASSERT_EQ(tconf.file, nullptr); + ASSERT_EQ(tconf.driver, nullptr); + EXPECT_STREQ(name, tconf.name); +- EXPECT_STREQ("FATAL", tconf.priority); ++ EXPECT_STREQ("NOTSET", tconf.priority); + + // not quiet configs check + tconf.quiet = false; +@@ -79,28 +79,65 @@ TEST(log_testcases, test_isula_libutils_log_enable) + struct isula_libutils_log_config tconf = {0}; + const char *prefix = "fake"; + const char *prio = "INFO"; ++ const char *invalid_prio = "INVALID"; + const char *fname = "/tmp/fake.fifo"; + int fd = -1; ++ int ret = 0; ++ ++ ret = isula_libutils_log_enable(nullptr); ++ ASSERT_NE(ret, 0); ++ fd = isula_libutils_get_log_fd(); ++ ASSERT_EQ(fd, -1); + + tconf.driver = ISULA_LOG_DRIVER_FIFO; + tconf.prefix = prefix; + tconf.priority = prio; ++ tconf.file = nullptr; ++ ret = isula_libutils_log_enable(&tconf); ++ ASSERT_NE(ret, 0); ++ fd = isula_libutils_get_log_fd(); ++ ASSERT_EQ(fd, -1); ++ ++ tconf.driver = nullptr; ++ tconf.prefix = prefix; ++ tconf.priority = prio; + tconf.file = fname; +- isula_libutils_log_enable(&tconf); ++ ret = isula_libutils_log_enable(&tconf); ++ ASSERT_EQ(ret, 0); ++ fd = isula_libutils_get_log_fd(); ++ ASSERT_EQ(fd, -1); + ++ tconf.driver = ISULA_LOG_DRIVER_FIFO; ++ tconf.prefix = prefix; ++ tconf.priority = invalid_prio; ++ tconf.file = fname; ++ ret = isula_libutils_log_enable(&tconf); ++ ASSERT_EQ(ret, 0); + fd = isula_libutils_get_log_fd(); + ASSERT_GE(fd, 0); ++ DEBUG("debug log"); ++ check_log(fd, false, false, "debug log"); ++ isula_libutils_log_disable(); + ++ tconf.driver = ISULA_LOG_DRIVER_FIFO; ++ tconf.prefix = prefix; ++ tconf.priority = prio; ++ tconf.file = fname; ++ ret = isula_libutils_log_enable(&tconf); ++ ASSERT_EQ(ret, 0); ++ fd = isula_libutils_get_log_fd(); ++ ASSERT_GE(fd, 0); + INFO("info log"); + check_log(fd, true, true, "info log"); +- + DEBUG("debug log"); + check_log(fd, false, false, "debug log"); ++ isula_libutils_log_disable(); + } + + TEST(log_testcases, test_isula_libutils_log_prefix) + { + struct isula_libutils_log_config tconf = {0}; ++ const char *default_prefix = "iSula"; + const char *prefix = "prefix"; + const char *prio = "INFO"; + const char *fname = "/tmp/fake.fifo"; +@@ -121,5 +158,15 @@ TEST(log_testcases, test_isula_libutils_log_prefix) + isula_libutils_free_log_prefix(); + INFO("fake log"); + check_log(fd, true, false, prefix); ++ INFO("fake log"); ++ check_log(fd, true, true, default_prefix); ++ ++ isula_libutils_set_log_prefix(nullptr); ++ INFO("fake log"); ++ check_log(fd, true, true, default_prefix); ++ ++ isula_libutils_set_log_prefix(""); ++ INFO("fake log"); ++ check_log(fd, true, true, default_prefix); + } + +diff --git a/third_party/log.c b/third_party/log.c +index d0fa541..e8ee9b5 100644 +--- a/third_party/log.c ++++ b/third_party/log.c +@@ -79,7 +79,8 @@ void isula_libutils_default_log_config(const char *name, struct isula_libutils_l + { + log->name = name; + log->file = NULL; +- log->priority = "FATAL"; ++ // use to disable log ++ log->priority = "NOTSET"; + if (!log->quiet) { + log->driver = ISULA_LOG_DRIVER_STDOUT; + } +@@ -87,7 +88,7 @@ void isula_libutils_default_log_config(const char *name, struct isula_libutils_l + + void isula_libutils_set_log_prefix(const char *prefix) + { +- if (prefix == NULL) { ++ if (prefix == NULL || strlen(prefix) == 0) { + return; + } + +@@ -336,12 +337,45 @@ static int open_fifo(const char *fifo_path) + return fifo_fd; + } + +-static bool check_log_driver(const struct isula_libutils_log_config *log) ++static void clean_pre_init() ++{ ++ g_lxc_log_category_lxc.appender = &log_appender_stderr; ++ g_lxc_log_category_lxc.priority = LXC_LOG_LEVEL_ERROR; ++} ++ ++static bool init_log_file(const char *fname) ++{ ++ if (fname == NULL) { ++ return false; ++ } ++ if (strcmp(fname, "none") == 0) { ++ return true; ++ } ++ if (lcr_util_build_dir(fname) != 0) { ++ CMD_SYSERROR("build log path \"%s\" failed", fname); ++ goto clean_out; ++ } ++ g_lxc_log_fd = open_fifo(fname); ++ if (g_lxc_log_fd == -1) { ++ CMD_SYSERROR("Open log fifo \"%s\" failed", fname); ++ goto clean_out; ++ } ++ ++ free(log_fname); ++ log_fname = lcr_util_strdup_s(fname); ++ return true; ++clean_out: ++ clean_pre_init(); ++ return false; ++} ++ ++static bool choice_log_driver(const struct isula_libutils_log_config *log) + { + bool is_fifo = false; + + // if driver is null, mean disable log + if (log->driver == NULL) { ++ g_lxc_log_category_lxc.priority = LXC_LOG_LEVEL_NOTSET; + return true; + } + g_lxc_log_category_lxc.appender = &log_appender_logfile; +@@ -350,10 +384,11 @@ static bool check_log_driver(const struct isula_libutils_log_config *log) + + // if set file, only use log_append_logfile + // we only support fifo driver with file +- if (log->file != NULL) { +- return is_fifo; +- } + if (is_fifo) { ++ return init_log_file(log->file); ++ } ++ if (log->file != NULL) { ++ clean_pre_init(); + return false; + } + +@@ -363,16 +398,8 @@ static bool check_log_driver(const struct isula_libutils_log_config *log) + return true; + } + +-static void clean_pre_init() +-{ +- g_lxc_log_category_lxc.appender = &log_appender_stderr; +- +- g_lxc_log_category_lxc.priority = LXC_LOG_LEVEL_ERROR; +-} +- + int isula_libutils_log_enable(const struct isula_libutils_log_config *log) + { +- int ret = 0; + int lxc_priority = LXC_LOG_LEVEL_ERROR; + + if (log == NULL) +@@ -383,7 +410,7 @@ int isula_libutils_log_enable(const struct isula_libutils_log_config *log) + return 0; + } + +- if (!check_log_driver(log)) { ++ if (!choice_log_driver(log)) { + COMMAND_ERROR("Invalid log config of driver"); + return -1; + } +@@ -395,29 +422,8 @@ int isula_libutils_log_enable(const struct isula_libutils_log_config *log) + + isula_libutils_set_log_prefix(log->prefix != NULL ? log->prefix : log->name); + +- if (log->file) { +- if (strcmp(log->file, "none") == 0) { +- ret = 0; +- goto clean_out; +- } +- if (lcr_util_build_dir(log->file) != 0) { +- CMD_SYSERROR("build log path \"%s\" failed", log->file); +- ret = -1; +- goto clean_out; +- } +- g_lxc_log_fd = open_fifo(log->file); +- if (g_lxc_log_fd == -1) { +- CMD_SYSERROR("Open log fifo \"%s\" failed", log->file); +- ret = -1; +- goto clean_out; +- } +- log_fname = lcr_util_strdup_s(log->file); +- } + + return 0; +-clean_out: +- clean_pre_init(); +- return ret; + } + + static inline void lxc_log_close(void) +diff --git a/third_party/log.h b/third_party/log.h +index 7f14ce0..2db0d98 100644 +--- a/third_party/log.h ++++ b/third_party/log.h +@@ -448,6 +448,7 @@ void isula_libutils_default_log_config(const char *name, struct isula_libutils_l + int isula_libutils_log_enable(const struct isula_libutils_log_config *log); + void isula_libutils_set_log_prefix(const char *prefix); + void isula_libutils_free_log_prefix(void); ++void isula_libutils_log_disable(); + + int isula_libutils_get_log_fd(void); + +diff --git a/tools/static_check b/tools/static_check +index 3a21d65..fd5c8ed 100755 +--- a/tools/static_check ++++ b/tools/static_check +@@ -91,7 +91,7 @@ function pclint_check() { + local start_time=$(date +%s) + local files + if [[ ${1} == "all" ]]; then +- files=$(find ./src ./test -regextype posix-extended -regex ".*\.(c|cc)") ++ files=$(find ./src ./tests -regextype posix-extended -regex ".*\.(c|cc)") + else + files=$(git diff --name-only HEAD | grep -E "*.c$") + fi +@@ -157,7 +157,7 @@ function codestyle_check() { + local start_time=$(date +%s) + local files + if [[ ${1} == "all" ]]; then +- files=$(find ./src ./test -regextype posix-extended -regex ".*\.(h|c|cc)") ++ files=$(find ./src ./tests -regextype posix-extended -regex ".*\.(h|c|cc)") + else + files=$(git diff --name-only HEAD | grep -E "*.h$|*.c$|*.cc$") + fi +@@ -313,7 +313,7 @@ function astyle_format() { + /_/ |_|/____/ /_/ /_//_____//_____/ /_/ \____//_/ |_|/_/ /_//_/ |_|/_/ \033[0m] + =================================================================================================" + local start_time=$(date +%s) +- local files=$(find ./src ./test -regextype posix-extended -regex ".*\.(h|c|cc)") ++ local files=$(find ./src ./tests -regextype posix-extended -regex ".*\.(h|c|cc)") + files=(${files// / }) + local total=${#files[@]} + local failure_num=0 +@@ -368,7 +368,7 @@ echo -e "\ + local start_time=$(date +%s) + local files + if [[ ${1} == "all" ]]; then +- files=$(find ./src ./test -regextype posix-extended -regex ".*\.(h|c|cc)") ++ files=$(find ./src ./tests -regextype posix-extended -regex ".*\.(h|c|cc)") + else + files=$(git diff --name-only HEAD | grep -E "*.h$|*.c$|*.cc$") + fi +@@ -428,7 +428,7 @@ function cmetrics_check() { + local start_time=$(date +%s) + local files + if [[ ${1} == "all" ]]; then +- files=$(find ./src ./test -regextype posix-extended -regex ".*\.(h|c|cc)") ++ files=$(find ./src ./tests -regextype posix-extended -regex ".*\.(h|c|cc)") + else + files=$(git diff --name-only HEAD | grep -E "*.h$|*.c$|*.cc$") + fi +-- +2.25.1 + diff --git a/0005-improve-llt-framework.patch b/0005-improve-llt-framework.patch new file mode 100644 index 0000000..8b0edab --- /dev/null +++ b/0005-improve-llt-framework.patch @@ -0,0 +1,246 @@ +From d97eb223fea08b12b63aa84f1c67a9a38fd1fee9 Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Thu, 11 Jun 2020 14:41:55 +0800 +Subject: [PATCH 05/11] improve llt framework + +1. add hook to run genhtml for llt +2. improve llt + +Signed-off-by: haozi007 +--- + CMakeLists.txt | 27 +++++---------------------- + cmake/checker.cmake | 31 +++++++++++++++++++++++++------ + cmake/set_build_flags.cmake | 10 ++++++---- + tests/CMakeLists.txt | 30 ++++++++++++++++++++++++++++++ + tests/log_llt.cpp | 25 +++++++++++++++++++++++++ + third_party/log.c | 4 ++-- + 6 files changed, 93 insertions(+), 34 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index c4acf43..dcb4232 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -23,8 +23,6 @@ + cmake_minimum_required (VERSION 2.8) + project (lcr) + +-include(cmake/set_build_flags.cmake) +- + option(VERSION "set lcr version" ON) + if (VERSION STREQUAL "ON") + set(LCR_VERSION "2.0.2") +@@ -35,10 +33,8 @@ if (DEBUG STREQUAL "ON") + add_definitions("-g -o2") + endif() + +-option(GCOV "set lcr gcov option" OFF) +-if (GCOV STREQUAL "ON") +- set(LCR_GCOV "ON") +-endif() ++include(cmake/set_build_flags.cmake) ++ + + if (LIB_INSTALL_DIR) + set(LIB_INSTALL_DIR_DEFAULT ${LIB_INSTALL_DIR}) +@@ -61,9 +57,6 @@ execute_process( + ) + message("-- commit id: " ${GIT_COMMIT_HASH}) + +-set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-E -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines -fPIE -pie -shared -pthread") +-set(CMAKE_EXE_LINKER_FLAGS "-Wl,-E -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines -fPIE -pie") +- + add_definitions(-DLCRPATH="${CMAKE_INSTALL_PREFIX}/var/lib/lcr") + add_definitions(-DLOGPATH="${CMAKE_INSTALL_PREFIX}/var/log/lcr") + add_definitions(-DLCR_GIT_COMMIT="${GIT_COMMIT_HASH}") +@@ -88,24 +81,14 @@ else () + message("-- Build static library") + endif() + +-# llt and coverage +-SET(CMAKE_VERBOSE_MAKEFILE OFF) +-OPTION(ENABLE_COVERAGE "coverage switch" OFF) +-IF(ENABLE_COVERAGE) +- MESSAGE(STATUS "Enable coverage compile option") +- SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -fprofile-arcs -ftest-coverage") +- SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -fprofile-arcs -ftest-coverage") +- SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -g -fprofile-arcs -ftest-coverage -lgcov") +-ENDIF(ENABLE_COVERAGE) +- + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/third_party) + + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src) + +-OPTION(ENABLE_LLT "llt switch" OFF) +-IF(ENABLE_LLT) ++# llt and gcoverage ++if (LCR_GCOV) + add_subdirectory(tests) +-ENDIF(ENABLE_LLT) ++endif() + + # install all files + install(FILES ${CMAKE_BINARY_DIR}/conf/lcr.pc +diff --git a/cmake/checker.cmake b/cmake/checker.cmake +index c527442..20ad917 100644 +--- a/cmake/checker.cmake ++++ b/cmake/checker.cmake +@@ -69,11 +69,30 @@ find_library(LIBYAJL_LIBRARY yajl + HINTS ${PC_LIBYAJL_LIBDIR} ${PC_LIBYAJL_LIBRARY_DIRS}) + _CHECK(LIBYAJL_LIBRARY "LIBYAJL_LIBRARY-NOTFOUND" "libyajl.so") + +-if (ENABLE_TESTS STREQUAL "ON") +- pkg_check_modules(PC_CHECK REQUIRED "check>=0.9.12") +- if (NOT PC_CHECK_FOUND) +- message("error: can not find check>=0.9.12") +- set(CHECKER_RESULT 1) +- endif() ++if (LCR_GCOV) ++ pkg_check_modules(PC_GTEST "gtest") ++ find_path(GTEST_INCLUDE_DIR gtest/gtest.h ++ HINTS ${PC_GTEST_INCLUDEDIR} ${PC_GTEST_INCLUDE_DIRS}) ++ _CHECK(GTEST_INCLUDE_DIR "GTEST_INCLUDE_DIR-NOTFOUND" "gtest.h") ++ find_library(GTEST_LIBRARY gtest ++ HINTS ${PC_GTEST_LIBDIR} ${PC_GTEST_LIBRARY_DIRS}) ++ _CHECK(GTEST_LIBRARY "GTEST_LIBRARY-NOTFOUND" "libgtest.so") ++ ++ pkg_check_modules(PC_GMOCK "gmock") ++ find_path(GMOCK_INCLUDE_DIR gmock/gmock.h ++ HINTS ${PC_GMOCK_INCLUDEDIR} ${PC_GMOCK_INCLUDE_DIRS}) ++ _CHECK(GMOCK_INCLUDE_DIR "GMOCK_INCLUDE_DIR-NOTFOUND" "gmock.h") ++ find_library(GMOCK_LIBRARY z ++ HINTS ${PC_GMOCK_LIBDIR} ${PC_GMOCK_LIBRARY_DIRS}) ++ _CHECK(GMOCK_LIBRARY "GMOCK_LIBRARY-NOTFOUND" "libgmock.so") ++ ++ find_program(CMD_GCOV gcov) ++ _CHECK(CMD_GCOV "CMD_GCOV-NOTFOUND" "gcov") ++ ++ find_program(CMD_LCOV lcov) ++ _CHECK(CMD_LCOV "CMD_LCOV-NOTFOUND" "lcov") ++ ++ find_program(CMD_GENHTML genhtml) ++ _CHECK(CMD_GENHTML "CMD_GENHTML-NOTFOUND" "genhtml") + endif() + +diff --git a/cmake/set_build_flags.cmake b/cmake/set_build_flags.cmake +index 46ba3c9..9aab5e1 100644 +--- a/cmake/set_build_flags.cmake ++++ b/cmake/set_build_flags.cmake +@@ -29,11 +29,13 @@ set(CMAKE_EXE_LINKER_FLAGS "-Wl,-E -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -W + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__FILENAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__FILENAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'") + ++option(LCR_GCOV "set lcr gcov option" OFF) + if (LCR_GCOV) +- set(CMAKE_C_FLAGS_DEBUG "-Wall -fprofile-arcs -ftest-coverage") +- set(CMAKE_CXX_FLAGS_DEBUG "-Wall -fprofile-arcs -ftest-coverage") +- message("-----CXXFLAGS: " ${CMAKE_CXX_FLAGS_DEBUG}) ++ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fprofile-arcs -ftest-coverage") ++ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fprofile-arcs -ftest-coverage") ++ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov") ++ message("-----CXXFLAGS: " ${CMAKE_CXX_FLAGS}) + message("------compile with gcov-------------") +- message("-----CFLAGS: " ${CMAKE_C_FLAGS_DEBUG}) ++ message("-----CFLAGS: " ${CMAKE_C_FLAGS}) + message("------------------------------------") + endif() +diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt +index 2d414ca..15708dd 100644 +--- a/tests/CMakeLists.txt ++++ b/tests/CMakeLists.txt +@@ -64,5 +64,35 @@ endmacro() + _DEFINE_NEW_TEST(log_llt log_testcase) + _DEFINE_NEW_TEST(json_llt json_testcase) + ++# mock test for run lcov to generate html ++add_executable(mock_llt main.cpp) ++target_include_directories(mock_llt PUBLIC ++ ${GTEST_INCLUDE_DIR} ++ PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ++ ) ++target_link_libraries(mock_llt ++ gtest ++ pthread ++ ) ++add_dependencies(mock_llt log_llt json_llt) ++ ++set(result isula_libutils.info) ++set(result_dir lcr_gcovs) ++set(target_dir src/CMakeFiles/isula_libutils.dir) ++ ++# generate gcov ++ ++add_custom_command(TARGET mock_llt ++ POST_BUILD ++ COMMAND ${CMAKE_COMMAND} -E remove -f ${result} ++ COMMAND ${CMAKE_COMMAND} -E make_directory ${result_dir} ++ COMMAND "ctest" ++ COMMAND ${CMD_LCOV} --gcov-tool ${CMD_GCOV} --exclude "*/src/utils.c" --exclude "*/json/*" -d ${CMAKE_BINARY_DIR}/${target_dir} -c -o ${result} ++ COMMAND ${CMD_GENHTML} --ignore-errors source -o ${result_dir} ${result} ++ COMMAND ${CMAKE_COMMAND} -E echo LLT finish ++ VERBATIM ++ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tests ++ ) ++ + # --------------- testcase add finish ----------------- + +diff --git a/tests/log_llt.cpp b/tests/log_llt.cpp +index dbdebad..a047f57 100644 +--- a/tests/log_llt.cpp ++++ b/tests/log_llt.cpp +@@ -107,6 +107,31 @@ TEST(log_testcases, test_isula_libutils_log_enable) + fd = isula_libutils_get_log_fd(); + ASSERT_EQ(fd, -1); + ++ tconf.driver = ISULA_LOG_DRIVER_STDOUT; ++ tconf.prefix = prefix; ++ tconf.priority = prio; ++ tconf.file = fname; ++ ret = isula_libutils_log_enable(&tconf); ++ ASSERT_NE(ret, 0); ++ isula_libutils_log_disable(); ++ ++ tconf.driver = ISULA_LOG_DRIVER_STDOUT; ++ tconf.prefix = prefix; ++ tconf.priority = prio; ++ tconf.file = nullptr; ++ ret = isula_libutils_log_enable(&tconf); ++ ASSERT_EQ(ret, 0); ++ TRACE("trace log"); ++ DEBUG("debug log"); ++ INFO("info log"); ++ NOTICE("notice log"); ++ WARN("warn log"); ++ ERROR("error log"); ++ EVENT("event log"); ++ CRIT("crit log"); ++ FATAL("fatal log"); ++ isula_libutils_log_disable(); ++ + tconf.driver = ISULA_LOG_DRIVER_FIFO; + tconf.prefix = prefix; + tconf.priority = invalid_prio; +diff --git a/third_party/log.c b/third_party/log.c +index e8ee9b5..83de005 100644 +--- a/third_party/log.c ++++ b/third_party/log.c +@@ -80,7 +80,7 @@ void isula_libutils_default_log_config(const char *name, struct isula_libutils_l + log->name = name; + log->file = NULL; + // use to disable log +- log->priority = "NOTSET"; ++ log->priority = "FATAL"; + if (!log->quiet) { + log->driver = ISULA_LOG_DRIVER_STDOUT; + } +@@ -375,7 +375,7 @@ static bool choice_log_driver(const struct isula_libutils_log_config *log) + + // if driver is null, mean disable log + if (log->driver == NULL) { +- g_lxc_log_category_lxc.priority = LXC_LOG_LEVEL_NOTSET; ++ g_lxc_log_category_lxc.priority = LXC_LOG_LEVEL_FATAL; + return true; + } + g_lxc_log_category_lxc.appender = &log_appender_logfile; +-- +2.25.1 + diff --git a/0006-fix-log-test-error.patch b/0006-fix-log-test-error.patch new file mode 100644 index 0000000..173772c --- /dev/null +++ b/0006-fix-log-test-error.patch @@ -0,0 +1,26 @@ +From 02054466c71822e197499b0271cfed57c96598b2 Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Thu, 11 Jun 2020 15:14:48 +0800 +Subject: [PATCH 06/11] fix log test error + +Signed-off-by: haozi007 +--- + tests/log_llt.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/log_llt.cpp b/tests/log_llt.cpp +index a047f57..8944b38 100644 +--- a/tests/log_llt.cpp ++++ b/tests/log_llt.cpp +@@ -42,7 +42,7 @@ TEST(log_testcases, test_isula_libutils_default_log_config) + ASSERT_EQ(tconf.file, nullptr); + ASSERT_EQ(tconf.driver, nullptr); + EXPECT_STREQ(name, tconf.name); +- EXPECT_STREQ("NOTSET", tconf.priority); ++ EXPECT_STREQ("FATAL", tconf.priority); + + // not quiet configs check + tconf.quiet = false; +-- +2.25.1 + diff --git a/0007-improve-html-show-result.patch b/0007-improve-html-show-result.patch new file mode 100644 index 0000000..b37dd94 --- /dev/null +++ b/0007-improve-html-show-result.patch @@ -0,0 +1,26 @@ +From abc0b5907d4b50729aa83a4c41d4a7e02d857aea Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Thu, 11 Jun 2020 15:48:32 +0800 +Subject: [PATCH 07/11] improve html show result + +Signed-off-by: haozi007 +--- + tests/CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt +index 15708dd..ca6d164 100644 +--- a/tests/CMakeLists.txt ++++ b/tests/CMakeLists.txt +@@ -87,7 +87,7 @@ add_custom_command(TARGET mock_llt + COMMAND ${CMAKE_COMMAND} -E remove -f ${result} + COMMAND ${CMAKE_COMMAND} -E make_directory ${result_dir} + COMMAND "ctest" +- COMMAND ${CMD_LCOV} --gcov-tool ${CMD_GCOV} --exclude "*/src/utils.c" --exclude "*/json/*" -d ${CMAKE_BINARY_DIR}/${target_dir} -c -o ${result} ++ COMMAND ${CMD_LCOV} --gcov-tool ${CMD_GCOV} --exclude "/usr/*" --exclude "*/src/utils.c" --exclude "*/json/*" -d ${CMAKE_BINARY_DIR}/${target_dir} -c -o ${result} + COMMAND ${CMD_GENHTML} --ignore-errors source -o ${result_dir} ${result} + COMMAND ${CMAKE_COMMAND} -E echo LLT finish + VERBATIM +-- +2.25.1 + diff --git a/0008-change-tests-name.patch b/0008-change-tests-name.patch new file mode 100644 index 0000000..953eca4 --- /dev/null +++ b/0008-change-tests-name.patch @@ -0,0 +1,189 @@ +From cb27a1612fdba43b94e9af1232da4378205c4c8a Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Sat, 13 Jun 2020 10:32:28 +0800 +Subject: [PATCH 08/11] change tests name + +1. change name of tests +2. default to run tests after build +3. use option to manage gcov + +Signed-off-by: haozi007 +--- + CMakeLists.txt | 6 +-- + cmake/checker.cmake | 2 +- + cmake/set_build_flags.cmake | 4 +- + src/CMakeLists.txt | 4 -- + tests/CMakeLists.txt | 54 ++++++++++++++--------- + tests/{json_llt.cpp => libocispec_ut.cpp} | 4 +- + tests/{log_llt.cpp => log_ut.cpp} | 0 + 7 files changed, 39 insertions(+), 35 deletions(-) + rename tests/{json_llt.cpp => libocispec_ut.cpp} (97%) + rename tests/{log_llt.cpp => log_ut.cpp} (100%) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index dcb4232..53e985f 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -85,10 +85,8 @@ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/third_party) + + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src) + +-# llt and gcoverage +-if (LCR_GCOV) +- add_subdirectory(tests) +-endif() ++# ut and gcoverage ++add_subdirectory(tests) + + # install all files + install(FILES ${CMAKE_BINARY_DIR}/conf/lcr.pc +diff --git a/cmake/checker.cmake b/cmake/checker.cmake +index 20ad917..7f8e9cc 100644 +--- a/cmake/checker.cmake ++++ b/cmake/checker.cmake +@@ -69,7 +69,7 @@ find_library(LIBYAJL_LIBRARY yajl + HINTS ${PC_LIBYAJL_LIBDIR} ${PC_LIBYAJL_LIBRARY_DIRS}) + _CHECK(LIBYAJL_LIBRARY "LIBYAJL_LIBRARY-NOTFOUND" "libyajl.so") + +-if (LCR_GCOV) ++if (ENABLE_GCOV) + pkg_check_modules(PC_GTEST "gtest") + find_path(GTEST_INCLUDE_DIR gtest/gtest.h + HINTS ${PC_GTEST_INCLUDEDIR} ${PC_GTEST_INCLUDE_DIRS}) +diff --git a/cmake/set_build_flags.cmake b/cmake/set_build_flags.cmake +index 9aab5e1..87cab3e 100644 +--- a/cmake/set_build_flags.cmake ++++ b/cmake/set_build_flags.cmake +@@ -29,8 +29,8 @@ set(CMAKE_EXE_LINKER_FLAGS "-Wl,-E -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -W + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__FILENAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__FILENAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'") + +-option(LCR_GCOV "set lcr gcov option" OFF) +-if (LCR_GCOV) ++option(ENABLE_GCOV "set lcr gcov option" OFF) ++if (ENABLE_GCOV) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fprofile-arcs -ftest-coverage") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fprofile-arcs -ftest-coverage") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov") +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 5e09c93..6ed2d95 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -103,10 +103,6 @@ if (CMAKE_TOOLCHAIN_FILE) + target_link_libraries(liblcr ${EXTRAL_LINK_LIBS}) + endif() + +-if (LCR_GCOV) +- target_link_libraries(liblcr -lgcov) +-endif() +- + # install all files + install(TARGETS liblcr + LIBRARY DESTINATION ${LIB_INSTALL_DIR_DEFAULT} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE) +diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt +index ca6d164..58a6fad 100644 +--- a/tests/CMakeLists.txt ++++ b/tests/CMakeLists.txt +@@ -61,38 +61,48 @@ endmacro() + + # --------------- testcase add here ----------------- + # api testcase +-_DEFINE_NEW_TEST(log_llt log_testcase) +-_DEFINE_NEW_TEST(json_llt json_testcase) ++_DEFINE_NEW_TEST(log_ut log_testcase) ++_DEFINE_NEW_TEST(libocispec_ut json_testcase) ++ + + # mock test for run lcov to generate html +-add_executable(mock_llt main.cpp) +-target_include_directories(mock_llt PUBLIC ++add_executable(mock_ut main.cpp) ++target_include_directories(mock_ut PUBLIC + ${GTEST_INCLUDE_DIR} + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} + ) +-target_link_libraries(mock_llt ++target_link_libraries(mock_ut + gtest + pthread + ) +-add_dependencies(mock_llt log_llt json_llt) +- +-set(result isula_libutils.info) +-set(result_dir lcr_gcovs) +-set(target_dir src/CMakeFiles/isula_libutils.dir) ++add_dependencies(mock_ut log_ut libocispec_ut) + +-# generate gcov ++# run ut and gcov ++if (ENABLE_GCOV) ++ set(result isula_libutils.info) ++ set(result_dir lcr_gcovs) ++ set(target_dir src/CMakeFiles/isula_libutils.dir) + +-add_custom_command(TARGET mock_llt +- POST_BUILD +- COMMAND ${CMAKE_COMMAND} -E remove -f ${result} +- COMMAND ${CMAKE_COMMAND} -E make_directory ${result_dir} +- COMMAND "ctest" +- COMMAND ${CMD_LCOV} --gcov-tool ${CMD_GCOV} --exclude "/usr/*" --exclude "*/src/utils.c" --exclude "*/json/*" -d ${CMAKE_BINARY_DIR}/${target_dir} -c -o ${result} +- COMMAND ${CMD_GENHTML} --ignore-errors source -o ${result_dir} ${result} +- COMMAND ${CMAKE_COMMAND} -E echo LLT finish +- VERBATIM +- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tests +- ) ++ add_custom_command(TARGET mock_ut ++ POST_BUILD ++ COMMAND ${CMAKE_COMMAND} -E remove -f ${result} ++ COMMAND ${CMAKE_COMMAND} -E make_directory ${result_dir} ++ COMMAND "ctest" ++ COMMAND ${CMD_LCOV} --gcov-tool ${CMD_GCOV} --exclude "/usr/*" --exclude "*/src/utils.c" --exclude "*/json/*" -d ${CMAKE_BINARY_DIR}/${target_dir} -c -o ${result} ++ COMMAND ${CMD_GENHTML} --ignore-errors source -o ${result_dir} ${result} ++ COMMAND ${CMAKE_COMMAND} -E echo run gcov finish ++ VERBATIM ++ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tests ++ ) ++else() ++ add_custom_command(TARGET mock_ut ++ PRE_BUILD ++ COMMAND "ctest" ++ COMMAND ${CMAKE_COMMAND} -E echo UT finish ++ VERBATIM ++ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tests ++ ) ++endif() + + # --------------- testcase add finish ----------------- + +diff --git a/tests/json_llt.cpp b/tests/libocispec_ut.cpp +similarity index 97% +rename from tests/json_llt.cpp +rename to tests/libocispec_ut.cpp +index 9622ed4..58a1f52 100644 +--- a/tests/json_llt.cpp ++++ b/tests/libocispec_ut.cpp +@@ -30,7 +30,7 @@ + #include "read_file.h" + #include "oci_runtime_hooks.h" + +-TEST(json_testcase, test_oci_runtime_spec_hooks) ++TEST(libocispec_testcase, test_oci_runtime_spec_hooks) + { + const char *fname = "./ocihook.json"; + oci_runtime_spec_hooks *hooks = nullptr; +@@ -79,7 +79,7 @@ TEST(json_testcase, test_oci_runtime_spec_hooks) + free(jstr); + } + +-TEST(json_testcase, test_json_readfile) ++TEST(libocispec_testcase, test_json_readfile) + { + const char *fname = "./ocihook.json"; + const char *not_exist = "/tmp/not_exist.json"; +diff --git a/tests/log_llt.cpp b/tests/log_ut.cpp +similarity index 100% +rename from tests/log_llt.cpp +rename to tests/log_ut.cpp +-- +2.25.1 + diff --git a/0009-Pull-Request-49-change-name-of-testcases.patch b/0009-Pull-Request-49-change-name-of-testcases.patch new file mode 100644 index 0000000..bfe918c --- /dev/null +++ b/0009-Pull-Request-49-change-name-of-testcases.patch @@ -0,0 +1,188 @@ +From c1cd034cf73b483c4c120c789c188ee64d19f7d3 Mon Sep 17 00:00:00 2001 +From: lifeng_isula +Date: Mon, 15 Jun 2020 10:39:15 +0800 +Subject: [PATCH 09/11] =?UTF-8?q?=E5=9B=9E=E9=80=80=20'Pull=20Request=20!4?= + =?UTF-8?q?9=20:=20change=20name=20of=20testcases'?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + CMakeLists.txt | 6 ++- + cmake/checker.cmake | 2 +- + cmake/set_build_flags.cmake | 4 +- + src/CMakeLists.txt | 4 ++ + tests/CMakeLists.txt | 54 +++++++++-------------- + tests/{libocispec_ut.cpp => json_llt.cpp} | 4 +- + tests/{log_ut.cpp => log_llt.cpp} | 0 + 7 files changed, 35 insertions(+), 39 deletions(-) + rename tests/{libocispec_ut.cpp => json_llt.cpp} (97%) + rename tests/{log_ut.cpp => log_llt.cpp} (100%) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 53e985f..dcb4232 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -85,8 +85,10 @@ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/third_party) + + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src) + +-# ut and gcoverage +-add_subdirectory(tests) ++# llt and gcoverage ++if (LCR_GCOV) ++ add_subdirectory(tests) ++endif() + + # install all files + install(FILES ${CMAKE_BINARY_DIR}/conf/lcr.pc +diff --git a/cmake/checker.cmake b/cmake/checker.cmake +index 7f8e9cc..20ad917 100644 +--- a/cmake/checker.cmake ++++ b/cmake/checker.cmake +@@ -69,7 +69,7 @@ find_library(LIBYAJL_LIBRARY yajl + HINTS ${PC_LIBYAJL_LIBDIR} ${PC_LIBYAJL_LIBRARY_DIRS}) + _CHECK(LIBYAJL_LIBRARY "LIBYAJL_LIBRARY-NOTFOUND" "libyajl.so") + +-if (ENABLE_GCOV) ++if (LCR_GCOV) + pkg_check_modules(PC_GTEST "gtest") + find_path(GTEST_INCLUDE_DIR gtest/gtest.h + HINTS ${PC_GTEST_INCLUDEDIR} ${PC_GTEST_INCLUDE_DIRS}) +diff --git a/cmake/set_build_flags.cmake b/cmake/set_build_flags.cmake +index 87cab3e..9aab5e1 100644 +--- a/cmake/set_build_flags.cmake ++++ b/cmake/set_build_flags.cmake +@@ -29,8 +29,8 @@ set(CMAKE_EXE_LINKER_FLAGS "-Wl,-E -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -W + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__FILENAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__FILENAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'") + +-option(ENABLE_GCOV "set lcr gcov option" OFF) +-if (ENABLE_GCOV) ++option(LCR_GCOV "set lcr gcov option" OFF) ++if (LCR_GCOV) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fprofile-arcs -ftest-coverage") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fprofile-arcs -ftest-coverage") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov") +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 6ed2d95..5e09c93 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -103,6 +103,10 @@ if (CMAKE_TOOLCHAIN_FILE) + target_link_libraries(liblcr ${EXTRAL_LINK_LIBS}) + endif() + ++if (LCR_GCOV) ++ target_link_libraries(liblcr -lgcov) ++endif() ++ + # install all files + install(TARGETS liblcr + LIBRARY DESTINATION ${LIB_INSTALL_DIR_DEFAULT} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE) +diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt +index 58a6fad..ca6d164 100644 +--- a/tests/CMakeLists.txt ++++ b/tests/CMakeLists.txt +@@ -61,48 +61,38 @@ endmacro() + + # --------------- testcase add here ----------------- + # api testcase +-_DEFINE_NEW_TEST(log_ut log_testcase) +-_DEFINE_NEW_TEST(libocispec_ut json_testcase) +- ++_DEFINE_NEW_TEST(log_llt log_testcase) ++_DEFINE_NEW_TEST(json_llt json_testcase) + + # mock test for run lcov to generate html +-add_executable(mock_ut main.cpp) +-target_include_directories(mock_ut PUBLIC ++add_executable(mock_llt main.cpp) ++target_include_directories(mock_llt PUBLIC + ${GTEST_INCLUDE_DIR} + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} + ) +-target_link_libraries(mock_ut ++target_link_libraries(mock_llt + gtest + pthread + ) +-add_dependencies(mock_ut log_ut libocispec_ut) ++add_dependencies(mock_llt log_llt json_llt) + +-# run ut and gcov +-if (ENABLE_GCOV) +- set(result isula_libutils.info) +- set(result_dir lcr_gcovs) +- set(target_dir src/CMakeFiles/isula_libutils.dir) ++set(result isula_libutils.info) ++set(result_dir lcr_gcovs) ++set(target_dir src/CMakeFiles/isula_libutils.dir) + +- add_custom_command(TARGET mock_ut +- POST_BUILD +- COMMAND ${CMAKE_COMMAND} -E remove -f ${result} +- COMMAND ${CMAKE_COMMAND} -E make_directory ${result_dir} +- COMMAND "ctest" +- COMMAND ${CMD_LCOV} --gcov-tool ${CMD_GCOV} --exclude "/usr/*" --exclude "*/src/utils.c" --exclude "*/json/*" -d ${CMAKE_BINARY_DIR}/${target_dir} -c -o ${result} +- COMMAND ${CMD_GENHTML} --ignore-errors source -o ${result_dir} ${result} +- COMMAND ${CMAKE_COMMAND} -E echo run gcov finish +- VERBATIM +- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tests +- ) +-else() +- add_custom_command(TARGET mock_ut +- PRE_BUILD +- COMMAND "ctest" +- COMMAND ${CMAKE_COMMAND} -E echo UT finish +- VERBATIM +- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tests +- ) +-endif() ++# generate gcov ++ ++add_custom_command(TARGET mock_llt ++ POST_BUILD ++ COMMAND ${CMAKE_COMMAND} -E remove -f ${result} ++ COMMAND ${CMAKE_COMMAND} -E make_directory ${result_dir} ++ COMMAND "ctest" ++ COMMAND ${CMD_LCOV} --gcov-tool ${CMD_GCOV} --exclude "/usr/*" --exclude "*/src/utils.c" --exclude "*/json/*" -d ${CMAKE_BINARY_DIR}/${target_dir} -c -o ${result} ++ COMMAND ${CMD_GENHTML} --ignore-errors source -o ${result_dir} ${result} ++ COMMAND ${CMAKE_COMMAND} -E echo LLT finish ++ VERBATIM ++ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tests ++ ) + + # --------------- testcase add finish ----------------- + +diff --git a/tests/libocispec_ut.cpp b/tests/json_llt.cpp +similarity index 97% +rename from tests/libocispec_ut.cpp +rename to tests/json_llt.cpp +index 58a1f52..9622ed4 100644 +--- a/tests/libocispec_ut.cpp ++++ b/tests/json_llt.cpp +@@ -30,7 +30,7 @@ + #include "read_file.h" + #include "oci_runtime_hooks.h" + +-TEST(libocispec_testcase, test_oci_runtime_spec_hooks) ++TEST(json_testcase, test_oci_runtime_spec_hooks) + { + const char *fname = "./ocihook.json"; + oci_runtime_spec_hooks *hooks = nullptr; +@@ -79,7 +79,7 @@ TEST(libocispec_testcase, test_oci_runtime_spec_hooks) + free(jstr); + } + +-TEST(libocispec_testcase, test_json_readfile) ++TEST(json_testcase, test_json_readfile) + { + const char *fname = "./ocihook.json"; + const char *not_exist = "/tmp/not_exist.json"; +diff --git a/tests/log_ut.cpp b/tests/log_llt.cpp +similarity index 100% +rename from tests/log_ut.cpp +rename to tests/log_llt.cpp +-- +2.25.1 + diff --git a/0010-change-tests-name.patch b/0010-change-tests-name.patch new file mode 100644 index 0000000..3c6d80b --- /dev/null +++ b/0010-change-tests-name.patch @@ -0,0 +1,227 @@ +From 71eb58f5a5002faf6ad4bc1a77cbf483d06f27c9 Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Tue, 16 Jun 2020 14:40:10 +0800 +Subject: [PATCH 10/11] change tests name + +Signed-off-by: haozi007 +--- + CMakeLists.txt | 6 +-- + cmake/checker.cmake | 30 ++++++------ + cmake/set_build_flags.cmake | 4 +- + src/CMakeLists.txt | 4 -- + tests/CMakeLists.txt | 60 +++++++++++++---------- + tests/{json_llt.cpp => libocispec_ut.cpp} | 4 +- + tests/{log_llt.cpp => log_ut.cpp} | 0 + 7 files changed, 56 insertions(+), 52 deletions(-) + rename tests/{json_llt.cpp => libocispec_ut.cpp} (97%) + rename tests/{log_llt.cpp => log_ut.cpp} (100%) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index dcb4232..53e985f 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -85,10 +85,8 @@ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/third_party) + + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src) + +-# llt and gcoverage +-if (LCR_GCOV) +- add_subdirectory(tests) +-endif() ++# ut and gcoverage ++add_subdirectory(tests) + + # install all files + install(FILES ${CMAKE_BINARY_DIR}/conf/lcr.pc +diff --git a/cmake/checker.cmake b/cmake/checker.cmake +index 20ad917..dde41a6 100644 +--- a/cmake/checker.cmake ++++ b/cmake/checker.cmake +@@ -69,23 +69,23 @@ find_library(LIBYAJL_LIBRARY yajl + HINTS ${PC_LIBYAJL_LIBDIR} ${PC_LIBYAJL_LIBRARY_DIRS}) + _CHECK(LIBYAJL_LIBRARY "LIBYAJL_LIBRARY-NOTFOUND" "libyajl.so") + +-if (LCR_GCOV) +- pkg_check_modules(PC_GTEST "gtest") +- find_path(GTEST_INCLUDE_DIR gtest/gtest.h +- HINTS ${PC_GTEST_INCLUDEDIR} ${PC_GTEST_INCLUDE_DIRS}) +- _CHECK(GTEST_INCLUDE_DIR "GTEST_INCLUDE_DIR-NOTFOUND" "gtest.h") +- find_library(GTEST_LIBRARY gtest +- HINTS ${PC_GTEST_LIBDIR} ${PC_GTEST_LIBRARY_DIRS}) +- _CHECK(GTEST_LIBRARY "GTEST_LIBRARY-NOTFOUND" "libgtest.so") ++pkg_check_modules(PC_GTEST "gtest") ++find_path(GTEST_INCLUDE_DIR gtest/gtest.h ++ HINTS ${PC_GTEST_INCLUDEDIR} ${PC_GTEST_INCLUDE_DIRS}) ++_CHECK(GTEST_INCLUDE_DIR "GTEST_INCLUDE_DIR-NOTFOUND" "gtest.h") ++find_library(GTEST_LIBRARY gtest ++ HINTS ${PC_GTEST_LIBDIR} ${PC_GTEST_LIBRARY_DIRS}) ++_CHECK(GTEST_LIBRARY "GTEST_LIBRARY-NOTFOUND" "libgtest.so") + +- pkg_check_modules(PC_GMOCK "gmock") +- find_path(GMOCK_INCLUDE_DIR gmock/gmock.h +- HINTS ${PC_GMOCK_INCLUDEDIR} ${PC_GMOCK_INCLUDE_DIRS}) +- _CHECK(GMOCK_INCLUDE_DIR "GMOCK_INCLUDE_DIR-NOTFOUND" "gmock.h") +- find_library(GMOCK_LIBRARY z +- HINTS ${PC_GMOCK_LIBDIR} ${PC_GMOCK_LIBRARY_DIRS}) +- _CHECK(GMOCK_LIBRARY "GMOCK_LIBRARY-NOTFOUND" "libgmock.so") ++pkg_check_modules(PC_GMOCK "gmock") ++find_path(GMOCK_INCLUDE_DIR gmock/gmock.h ++ HINTS ${PC_GMOCK_INCLUDEDIR} ${PC_GMOCK_INCLUDE_DIRS}) ++_CHECK(GMOCK_INCLUDE_DIR "GMOCK_INCLUDE_DIR-NOTFOUND" "gmock.h") ++find_library(GMOCK_LIBRARY z ++ HINTS ${PC_GMOCK_LIBDIR} ${PC_GMOCK_LIBRARY_DIRS}) ++_CHECK(GMOCK_LIBRARY "GMOCK_LIBRARY-NOTFOUND" "libgmock.so") + ++if (ENABLE_GCOV) + find_program(CMD_GCOV gcov) + _CHECK(CMD_GCOV "CMD_GCOV-NOTFOUND" "gcov") + +diff --git a/cmake/set_build_flags.cmake b/cmake/set_build_flags.cmake +index 9aab5e1..87cab3e 100644 +--- a/cmake/set_build_flags.cmake ++++ b/cmake/set_build_flags.cmake +@@ -29,8 +29,8 @@ set(CMAKE_EXE_LINKER_FLAGS "-Wl,-E -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -W + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__FILENAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__FILENAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'") + +-option(LCR_GCOV "set lcr gcov option" OFF) +-if (LCR_GCOV) ++option(ENABLE_GCOV "set lcr gcov option" OFF) ++if (ENABLE_GCOV) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fprofile-arcs -ftest-coverage") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fprofile-arcs -ftest-coverage") + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov") +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 5e09c93..6ed2d95 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -103,10 +103,6 @@ if (CMAKE_TOOLCHAIN_FILE) + target_link_libraries(liblcr ${EXTRAL_LINK_LIBS}) + endif() + +-if (LCR_GCOV) +- target_link_libraries(liblcr -lgcov) +-endif() +- + # install all files + install(TARGETS liblcr + LIBRARY DESTINATION ${LIB_INSTALL_DIR_DEFAULT} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE) +diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt +index ca6d164..89eb6cf 100644 +--- a/tests/CMakeLists.txt ++++ b/tests/CMakeLists.txt +@@ -37,8 +37,8 @@ macro(_DEFINE_NEW_TEST) + + target_link_libraries(${ARGV0} + isula_libutils +- gtest +- -lyajl ++ ${GTEST_LIBRARY} ++ ${LIBYAJL_LIBRARY} + pthread + ) + +@@ -61,38 +61,48 @@ endmacro() + + # --------------- testcase add here ----------------- + # api testcase +-_DEFINE_NEW_TEST(log_llt log_testcase) +-_DEFINE_NEW_TEST(json_llt json_testcase) ++_DEFINE_NEW_TEST(log_ut log_testcase) ++_DEFINE_NEW_TEST(libocispec_ut libocispec_testcase) ++ + + # mock test for run lcov to generate html +-add_executable(mock_llt main.cpp) +-target_include_directories(mock_llt PUBLIC ++add_executable(mock_ut main.cpp) ++target_include_directories(mock_ut PUBLIC + ${GTEST_INCLUDE_DIR} + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} + ) +-target_link_libraries(mock_llt +- gtest ++target_link_libraries(mock_ut ++ ${GTEST_LIBRARY} + pthread + ) +-add_dependencies(mock_llt log_llt json_llt) +- +-set(result isula_libutils.info) +-set(result_dir lcr_gcovs) +-set(target_dir src/CMakeFiles/isula_libutils.dir) ++add_dependencies(mock_ut log_ut libocispec_ut) + +-# generate gcov ++# run ut and gcov ++if (ENABLE_GCOV) ++ set(result isula_libutils.info) ++ set(result_dir lcr_gcovs) ++ set(target_dir src/CMakeFiles/isula_libutils.dir) + +-add_custom_command(TARGET mock_llt +- POST_BUILD +- COMMAND ${CMAKE_COMMAND} -E remove -f ${result} +- COMMAND ${CMAKE_COMMAND} -E make_directory ${result_dir} +- COMMAND "ctest" +- COMMAND ${CMD_LCOV} --gcov-tool ${CMD_GCOV} --exclude "/usr/*" --exclude "*/src/utils.c" --exclude "*/json/*" -d ${CMAKE_BINARY_DIR}/${target_dir} -c -o ${result} +- COMMAND ${CMD_GENHTML} --ignore-errors source -o ${result_dir} ${result} +- COMMAND ${CMAKE_COMMAND} -E echo LLT finish +- VERBATIM +- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tests +- ) ++ add_custom_command(TARGET mock_ut ++ POST_BUILD ++ COMMAND ${CMAKE_COMMAND} -E remove -f ${result} ++ COMMAND ${CMAKE_COMMAND} -E make_directory ${result_dir} ++ COMMAND ctest -VV ++ COMMAND ${CMD_LCOV} --gcov-tool ${CMD_GCOV} --exclude "/usr/*" --exclude "*/src/utils.c" --exclude "*/json/*" -d ${CMAKE_BINARY_DIR}/${target_dir} -c -o ${result} ++ COMMAND ${CMD_GENHTML} --ignore-errors source -o ${result_dir} ${result} ++ COMMAND ${CMAKE_COMMAND} -E echo run gcov finish ++ VERBATIM ++ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tests ++ ) ++else() ++ add_custom_command(TARGET mock_ut ++ PRE_BUILD ++ COMMAND ${CMAKE_CTEST_COMMAND} -VV ++ COMMAND ${CMAKE_COMMAND} -E echo UT finish ++ VERBATIM ++ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tests ++ ) ++endif() + + # --------------- testcase add finish ----------------- + +diff --git a/tests/json_llt.cpp b/tests/libocispec_ut.cpp +similarity index 97% +rename from tests/json_llt.cpp +rename to tests/libocispec_ut.cpp +index 9622ed4..58a1f52 100644 +--- a/tests/json_llt.cpp ++++ b/tests/libocispec_ut.cpp +@@ -30,7 +30,7 @@ + #include "read_file.h" + #include "oci_runtime_hooks.h" + +-TEST(json_testcase, test_oci_runtime_spec_hooks) ++TEST(libocispec_testcase, test_oci_runtime_spec_hooks) + { + const char *fname = "./ocihook.json"; + oci_runtime_spec_hooks *hooks = nullptr; +@@ -79,7 +79,7 @@ TEST(json_testcase, test_oci_runtime_spec_hooks) + free(jstr); + } + +-TEST(json_testcase, test_json_readfile) ++TEST(libocispec_testcase, test_json_readfile) + { + const char *fname = "./ocihook.json"; + const char *not_exist = "/tmp/not_exist.json"; +diff --git a/tests/log_llt.cpp b/tests/log_ut.cpp +similarity index 100% +rename from tests/log_llt.cpp +rename to tests/log_ut.cpp +-- +2.25.1 + diff --git a/0011-support-fuzz-test.patch b/0011-support-fuzz-test.patch new file mode 100644 index 0000000..5b4b220 --- /dev/null +++ b/0011-support-fuzz-test.patch @@ -0,0 +1,241 @@ +From 10ee1a5e5eca638f0cc5190ae49c34e9841d8c8b Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Sun, 28 Jun 2020 16:16:04 +0800 +Subject: [PATCH 11/11] support fuzz test + +Signed-off-by: haozi007 +--- + tests/CMakeLists.txt | 7 ++++ + tests/fuzz/CMakeLists.txt | 40 ++++++++++++++++++ + tests/fuzz/dict/log_fuzz.dict | 14 +++++++ + tests/fuzz/fuzz.sh | 48 ++++++++++++++++++++++ + tests/fuzz/log_fuzz.cc | 76 +++++++++++++++++++++++++++++++++++ + 5 files changed, 185 insertions(+) + create mode 100644 tests/fuzz/CMakeLists.txt + create mode 100644 tests/fuzz/dict/log_fuzz.dict + create mode 100755 tests/fuzz/fuzz.sh + create mode 100644 tests/fuzz/log_fuzz.cc + +diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt +index 89eb6cf..e2ad103 100644 +--- a/tests/CMakeLists.txt ++++ b/tests/CMakeLists.txt +@@ -60,6 +60,13 @@ macro(_DEFINE_NEW_TEST) + endmacro() + + # --------------- testcase add here ----------------- ++ ++# fuzz test ++option(ENABLE_FUZZ "set lcr fuzz option" OFF) ++if (ENABLE_FUZZ) ++ add_subdirectory(fuzz) ++endif() ++ + # api testcase + _DEFINE_NEW_TEST(log_ut log_testcase) + _DEFINE_NEW_TEST(libocispec_ut libocispec_testcase) +diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt +new file mode 100644 +index 0000000..660b8be +--- /dev/null ++++ b/tests/fuzz/CMakeLists.txt +@@ -0,0 +1,40 @@ ++# lcr: fuzz tests ++# ++# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++# ++# Authors: ++# Haozi007 ++# ++# 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.1 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, write to the Free Software ++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++# ++ ++set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-coverage=trace-pc") ++set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize-coverage=trace-pc") ++set(EXE log_fuzz) ++ ++configure_file("dict/log_fuzz.dict" ${CMAKE_BINARY_DIR}/tests/fuzz/dict/log_fuzz.dict COPYONLY) ++configure_file("fuzz.sh" ${CMAKE_BINARY_DIR}/tests/fuzz/fuzz.sh COPYONLY) ++ ++add_executable(${EXE} log_fuzz.cc) ++ ++target_include_directories(${EXE} PUBLIC ++ ${GTEST_INCLUDE_DIR} ++ PUBLIC ${CMAKE_SOURCE_DIR}/third_party ++ PUBLIC ${CMAKE_SOURCE_DIR}/third_party/libocispec ++ ) ++ ++set_target_properties(${EXE} PROPERTIES LINKER_LANGUAGE CXX) ++set_target_properties(${EXE} PROPERTIES LINK_FLAGS "-fsanitize-coverage=trace-pc") ++target_link_libraries(${EXE} ${CMAKE_THREAD_LIBS_INIT} isula_libutils Fuzzer pthread) +diff --git a/tests/fuzz/dict/log_fuzz.dict b/tests/fuzz/dict/log_fuzz.dict +new file mode 100644 +index 0000000..d6a438d +--- /dev/null ++++ b/tests/fuzz/dict/log_fuzz.dict +@@ -0,0 +1,14 @@ ++"x,,debug,prefix,stdout" ++",/tmp/fake.fifo,info,prefix,stdout" ++"x,,ERROR,prefix,stdout" ++"x,/tmp/fake.fifo,,prefix,stdout" ++"x,/tmp/fake.fifo,info,,stdout" ++"x,/tmp/fake.fifo,crit,prefix," ++"x,/tmp/fake.fifo,fatal,prefix,fifo" ++",/tmp/fake.fifo,info,prefix,fifo" ++"x,,ERROR,prefix,fifo" ++"x,/tmp/fake.fifo,,prefix,fifo" ++"x,/tmp/fake.fifo,debug,,fifo" ++"x,,invalid,prefix,stdout" ++"x,/tmp/fake.fifo,invalid,prefix,fifo" ++"invalid" +diff --git a/tests/fuzz/fuzz.sh b/tests/fuzz/fuzz.sh +new file mode 100755 +index 0000000..6f80cab +--- /dev/null ++++ b/tests/fuzz/fuzz.sh +@@ -0,0 +1,48 @@ ++# lcr: fuzz tests ++# ++# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++# ++# Authors: ++# Haozi007 ++# ++# 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.1 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, write to the Free Software ++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++# ++ ++#!/bin/bash ++ ++LIB_FUZZING_ENGINE="/lib64/libFuzzer.a" ++FUZZ_OPTION="corpus -dict=./dict/log_fuzz.dict -runs=100000 -max_total_time=3600" ++ ++if [ ! -f "$LIB_FUZZING_ENGINE" ];then ++ echo "$LIB_FUZZING_ENGINE not exist, pls check" ++ exit 1 ++fi ++ ++# compile fuzz testcase ++make -j ++ ++# run fuzz testcases ++./log_fuzz ${FUZZ_OPTION} -artifact_prefix=log_fuzz- ++ ++echo "########### Fuzz Result ##############" ++crash=`find -name "*-crash-*"` ++if [ x"${crash}" != x"" ];then ++ echo "find bugs while fuzzing, pls check <*-crash-*> file" ++ find -name "*-crash-*" ++ exit 1 ++else ++ echo "all fuzz success." ++fi ++ +diff --git a/tests/fuzz/log_fuzz.cc b/tests/fuzz/log_fuzz.cc +new file mode 100644 +index 0000000..9dc02bb +--- /dev/null ++++ b/tests/fuzz/log_fuzz.cc +@@ -0,0 +1,76 @@ ++/****************************************************************************** ++ * log_fuzz: testcase for log ++ * ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * ++ * Authors: ++ * Haozi007 ++ * ++ * 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.1 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, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ ********************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include "log.h" ++ ++ ++extern "C" void testLog(struct isula_libutils_log_config *conf) ++{ ++ (void)isula_libutils_log_enable(conf); ++ INFO("info log"); ++ isula_libutils_set_log_prefix(conf->prefix); ++ INFO("test prefix info"); ++ isula_libutils_log_disable(); ++} ++ ++ ++extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) ++{ ++ const char *default_name = "iSula"; ++ struct isula_libutils_log_config tconf = {0}; ++ std::string testData(reinterpret_cast(data), size); ++ std::vector ret_vec; ++ std::string tmpstr; ++ std::istringstream istr(testData); ++ while(std::getline(istr, tmpstr, ',')) { ++ ret_vec.push_back(tmpstr); ++ } ++ ++ if (ret_vec.size() == 5) { ++ if (ret_vec[0] != "") { ++ tconf.name = ret_vec[0].c_str(); ++ } ++ if (ret_vec[1] != "") { ++ tconf.file = ret_vec[1].c_str(); ++ } ++ if (ret_vec[2] != "") { ++ tconf.priority = ret_vec[2].c_str(); ++ } ++ if (ret_vec[3] != "") { ++ tconf.prefix = ret_vec[3].c_str(); ++ } ++ if (ret_vec[4] != "") { ++ tconf.driver = ret_vec[4].c_str(); ++ } ++ } else { ++ isula_libutils_default_log_config(default_name, &tconf); ++ } ++ ++ testLog(&tconf); ++ return 0; ++} ++ +-- +2.25.1 + diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index e79e3bf..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,89 +0,0 @@ -cmake_minimum_required (VERSION 2.8) -project (lcr) - -include(cmake/set_build_flags.cmake) - -option(VERSION "set lcr version" ON) -if (VERSION STREQUAL "ON") - set(LCR_VERSION "2.0.0") -endif() - -option(DEBUG "set lcr gcc option" ON) -if (DEBUG STREQUAL "ON") - add_definitions("-g -o2") -endif() - -option(GCOV "set lcr gcov option" OFF) -if (GCOV STREQUAL "ON") - set(LCR_GCOV "ON") -endif() - -if (LIB_INSTALL_DIR) - set(LIB_INSTALL_DIR_DEFAULT ${LIB_INSTALL_DIR}) -else() - set(LIB_INSTALL_DIR_DEFAULT "lib") -endif() - -# check depends libs and headers -include(cmake/checker.cmake) -if (CHECKER_RESULT) - return() -endif() - -# Get the latest abbreviated commit hash of the working branch -execute_process( - COMMAND git rev-parse HEAD - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - OUTPUT_VARIABLE GIT_COMMIT_HASH - OUTPUT_STRIP_TRAILING_WHITESPACE -) -message("-- commit id: " ${GIT_COMMIT_HASH}) - -set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-E -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines -fPIE -pie -shared -pthread") -set(CMAKE_EXE_LINKER_FLAGS "-Wl,-E -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines -fPIE -pie") - -add_definitions(-DLCRPATH="${CMAKE_INSTALL_PREFIX}/var/lib/lcr") -add_definitions(-DLOGPATH="${CMAKE_INSTALL_PREFIX}/var/log/lcr") -add_definitions(-DLCR_GIT_COMMIT="${GIT_COMMIT_HASH}") - -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/config.h.in" - "${CMAKE_BINARY_DIR}/conf/config.h" -) - -configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/lcr.pc.in" - "${CMAKE_BINARY_DIR}/conf/lcr.pc" -) - -# build which type of lcr library -option(USESHARED "set type of liblcr, default is shared" ON) -if (USESHARED STREQUAL "ON") - set(LIBTYPE "SHARED") - message("-- Build shared library") -else () - set(LIBTYPE "STATIC") - message("-- Build static library") -endif() - -# llt and coverage -SET(CMAKE_VERBOSE_MAKEFILE OFF) -OPTION(ENABLE_COVERAGE "coverage switch" OFF) -IF(ENABLE_COVERAGE) - MESSAGE(STATUS "Enable coverage compile option") - SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -fprofile-arcs -ftest-coverage") - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -fprofile-arcs -ftest-coverage") - SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -g -fprofile-arcs -ftest-coverage -lgcov") -ENDIF(ENABLE_COVERAGE) - -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src) -OPTION(ENABLE_LLT "llt switch" OFF) -IF(ENABLE_LLT) - enable_testing() -ENDIF(ENABLE_LLT) - -# install all files -install(FILES ${CMAKE_BINARY_DIR}/conf/lcr.pc - DESTINATION ${LIB_INSTALL_DIR_DEFAULT}/pkgconfig PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ GROUP_WRITE) -install(FILES src/lcrcontainer.h - DESTINATION include/lcr) diff --git a/License/LICENSE b/License/LICENSE deleted file mode 100644 index f74a5d4..0000000 --- a/License/LICENSE +++ /dev/null @@ -1,127 +0,0 @@ - 木兰宽松许可证, 第2版 - - 木兰宽松许可证, 第2版 - 2020年1月 http://license.coscl.org.cn/MulanPSL22 - - - 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: - - 0. 定义 - - “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 - - “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 - - “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 - - “法人实体”是指提交贡献的机构及其“关联实体”。 - - “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 - - 1. 授予版权许可 - - 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 - - 2. 授予专利许可 - - 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 - - 3. 无商标许可 - - “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 - - 4. 分发限制 - - 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 - - 5. 免责声明与责任限制 - - “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 - - 6. 语言 - “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 - - 条款结束 - - 如何将木兰宽松许可证,第2版,应用到您的软件 - - 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: - - 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; - - 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; - - 3, 请将如下声明文本放入每个源文件的头部注释中。 - - Copyright (c) [Year] [name of copyright holder] - [Software Name] is licensed under 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/MulanPSL22 - 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. - - - Mulan Permissive Software License,Version 2 - - Mulan Permissive Software License,Version 2 (Mulan PSL v2) - January 2020 http://license.coscl.org.cn/MulanPSL22 - - Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: - - 0. Definition - - Software means the program and related documents which are licensed under this License and comprise all Contribution(s). - - Contribution means the copyrightable work licensed by a particular Contributor under this License. - - Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. - - Legal Entity means the entity making a Contribution and all its Affiliates. - - Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. - - 1. Grant of Copyright License - - Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. - - 2. Grant of Patent License - - Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. - - 3. No Trademark License - - No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4. - - 4. Distribution Restriction - - You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. - - 5. Disclaimer of Warranty and Limitation of Liability - - THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - - 6. Language - - THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. - - END OF THE TERMS AND CONDITIONS - - How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software - - To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: - - i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; - - ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; - - iii Attach the statement to the appropriate annotated syntax at the beginning of each source file. - - - Copyright (c) [Year] [name of copyright holder] - [Software Name] is licensed under 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/MulanPSL22 - 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. diff --git a/README.md b/README.md deleted file mode 100644 index 1984855..0000000 --- a/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# lcr - -`lcr`(Lightweight Container Runtime) is CLI tool for spawning and running containers according to OCI specification. -It is based on `liblxc` and written by `C`. - -## How to Contribute - -We always welcome new contributors. And we are happy to provide guidance for the new contributors. -iSulad follows the kernel coding conventions. You can find a detailed introduction at: - -- https://www.kernel.org/doc/html/v4.10/process/coding-style.html - -## Licensing - -lcr is licensed under the Mulan PSL v2. diff --git a/cmake/checker.cmake b/cmake/checker.cmake deleted file mode 100644 index be78919..0000000 --- a/cmake/checker.cmake +++ /dev/null @@ -1,35 +0,0 @@ -# check depends library and headers -find_package(PkgConfig REQUIRED) - -macro(_CHECK) -if (${ARGV0} STREQUAL "${ARGV1}") - message("error: can not find " ${ARGV2} " program") - set(CHECKER_RESULT 1) -else() - message("-- found " ${ARGV2} " --- works") -endif() -endmacro() - -#check python3 -find_program(CMD_PYTHON python3) -_CHECK(CMD_PYTHON "CMD_PYTHON-NOTFOUND" "python3") - -# check liblxc -pkg_check_modules(PC_LIBLXC REQUIRED "lxc>=3") -find_path(LIBLXC_INCLUDE_DIR lxc/lxccontainer.h - HINTS ${PC_LIBLXC_INCLUDEDIR} ${PC_LIBLXC_INCLUDE_DIRS}) -_CHECK(LIBLXC_INCLUDE_DIR "LIBLXC_INCLUDE_DIR-NOTFOUND" "lxc/lxccontainer.h") - -find_library(LIBLXC_LIBRARY lxc - HINTS ${PC_LIBLXC_LIBDIR} ${PC_LIBLXC_LIBRARY_DIRS}) -_CHECK(LIBLXC_LIBRARY "LIBLXC_LIBRARY-NOTFOUND" "liblxc.so") - -# check libyajl -pkg_check_modules(PC_LIBYAJL REQUIRED "yajl>=2") -find_path(LIBYAJL_INCLUDE_DIR yajl/yajl_tree.h - HINTS ${PC_LIBYAJL_INCLUDEDIR} ${PC_LIBYAJL_INCLUDE_DIRS}) -_CHECK(LIBYAJL_INCLUDE_DIR "LIBYAJL_INCLUDE_DIR-NOTFOUND" "yajl/yajl_tree.h") - -find_library(LIBYAJL_LIBRARY yajl - HINTS ${PC_LIBYAJL_LIBDIR} ${PC_LIBYAJL_LIBRARY_DIRS}) -_CHECK(LIBYAJL_LIBRARY "LIBYAJL_LIBRARY-NOTFOUND" "libyajl.so") diff --git a/cmake/set_build_flags.cmake b/cmake/set_build_flags.cmake deleted file mode 100644 index 0469ba8..0000000 --- a/cmake/set_build_flags.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# set common FLAGS -set(CMAKE_C_FLAGS "-fPIC -fstack-protector-all -D_FORTIFY_SOURCE=2 -O2 -Wall -Werror -rdynamic") -set(CMAKE_CXX_FLAGS "-fPIC -std=c++11 -fstack-protector-all -D_FORTIFY_SOURCE=2 -O2 -Wall -Werror") -set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-E -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines -fPIE -pie -shared -pthread") -set(CMAKE_EXE_LINKER_FLAGS "-Wl,-E -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines -fPIE -pie") - -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D__FILENAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__FILENAME__='\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"'") - -if (LCR_GCOV) - set(CMAKE_C_FLAGS_DEBUG "-Wall -fprofile-arcs -ftest-coverage") - set(CMAKE_CXX_FLAGS_DEBUG "-Wall -fprofile-arcs -ftest-coverage") - message("-----CXXFLAGS: " ${CMAKE_CXX_FLAGS_DEBUG}) - message("------compile with gcov-------------") - message("-----CFLAGS: " ${CMAKE_C_FLAGS_DEBUG}) - message("------------------------------------") -endif() diff --git a/config.h.in b/config.h.in deleted file mode 100644 index 3f3c523..0000000 --- a/config.h.in +++ /dev/null @@ -1 +0,0 @@ -#cmakedefine VERSION "@LCR_VERSION@" diff --git a/contrib/oci.config.json b/contrib/oci.config.json deleted file mode 100644 index 16f5c26..0000000 --- a/contrib/oci.config.json +++ /dev/null @@ -1,1672 +0,0 @@ -{ - "ociVersion": "1.0.0-rc5-dev", - "platform": { - "os": "linux", - "arch": "amd64" - }, - "process": { - "terminal": true, - "consoleSize": { - "height": 0, - "width": 0 - }, - "user": { - "uid": 5, - "gid": 3 - }, - "args": [ - "/bin/bash", - "-x", - "sleep", - "5" - ], - "env": [ - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - "HOSTNAME=7facfe3313cd", - "TERM=xterm" - ], - "cwd": "/", - "capabilities": [ - "CAP_CHOWN", - "CAP_DAC_OVERRIDE", - "CAP_FSETID", - "CAP_FOWNER", - "CAP_MKNOD", - "CAP_NET_RAW", - "CAP_SETGID", - "CAP_SETUID", - "CAP_SETFCAP", - "CAP_SETPCAP", - "CAP_NET_BIND_SERVICE", - "CAP_SYS_CHROOT", - "CAP_KILL", - "CAP_AUDIT_WRITE" - ], - "rlimits": [ - { - "type": "RLIMIT_NOFILE", - "hard": 1024, - "soft": 1024 - }, - { - "type": "RLIMIT_CPU", - "hard": 124, - "soft": 109994 - } - ], - "apparmorProfile": "docker-default", - "selinuxLabel": "docker-default-selinux" - }, - "root": { - "path": "/var/lib/docker/aufs/mnt/30c8ae0af789e1c313726584699c1ce351e0a4e056885096423235bcbfc6c61a" - }, - "hostname": "7facfe3313cd", - "mounts": [ - { - "destination": "/proc", - "type": "proc", - "source": "proc", - "options": [ - "nosuid", - "noexec", - "nodev" - ] - }, - { - "destination": "/dev", - "type": "tmpfs", - "source": "tmpfs", - "options": [ - "nosuid", - "strictatime", - "mode=755" - ] - }, - { - "destination": "/dev/pts", - "type": "devpts", - "source": "devpts", - "options": [ - "nosuid", - "noexec", - "newinstance", - "ptmxmode=0666", - "mode=0620", - "gid=5" - ] - }, - { - "destination": "/sys", - "type": "sysfs", - "source": "sysfs", - "options": [ - "nosuid", - "noexec", - "nodev", - "ro" - ] - }, - { - "destination": "/sys/fs/cgroup", - "type": "cgroup", - "source": "cgroup", - "options": [ - "ro", - "nosuid", - "noexec", - "nodev" - ] - }, - { - "destination": "/dev/mqueue", - "type": "mqueue", - "source": "mqueue", - "options": [ - "nosuid", - "noexec", - "nodev" - ] - }, - { - "destination": "/etc/resolv.conf", - "type": "bind", - "source": "/var/lib/docker/containers/7facfe3313cdca596b13ab6aab063e577f8540f875943e074c08603ee8efb52c/resolv.conf", - "options": [ - "rbind", - "rprivate" - ] - }, - { - "destination": "/etc/hostname", - "type": "bind", - "source": "/var/lib/docker/containers/7facfe3313cdca596b13ab6aab063e577f8540f875943e074c08603ee8efb52c/hostname", - "options": [ - "rbind", - "rprivate" - ] - }, - { - "destination": "/etc/hosts", - "type": "bind", - "source": "/var/lib/docker/containers/7facfe3313cdca596b13ab6aab063e577f8540f875943e074c08603ee8efb52c/hosts", - "options": [ - "rbind", - "rprivate" - ] - }, - { - "destination": "/dev/shm", - "type": "bind", - "source": "/var/lib/docker/containers/7facfe3313cdca596b13ab6aab063e577f8540f875943e074c08603ee8efb52c/shm", - "options": [ - "rbind", - "rprivate" - ] - } - ], - "hooks": { - "prestart": [ - { - "path": "/usr/bin/dockerd", - "args": [ - "libnetwork-setkey", - "7facfe3313cdca596b13ab6aab063e577f8540f875943e074c08603ee8efb52c", - "007ddd4074870397cf56b5fc958fdcea04314b7bfeaaf8104e13b9c980ed6ac4" - ] - } - ] - }, - "linux": { - "uidMappings": [ - { - "hostID": 1002, - "containerID": 0, - "size": 32002 - } - ], - "gidMappings": [ - { - "hostID": 1001, - "containerID": 0, - "size": 32001 - } - ], - "resources": { - "devices": [ - { - "allow": false, - "access": "rwm" - }, - { - "allow": true, - "type": "c", - "major": 1, - "minor": 5, - "access": "rwm" - }, - { - "allow": true, - "type": "c", - "major": 1, - "minor": 3, - "access": "rwm" - }, - { - "allow": true, - "type": "c", - "major": 1, - "minor": 9, - "access": "rwm" - }, - { - "allow": true, - "type": "c", - "major": 1, - "minor": 8, - "access": "rwm" - }, - { - "allow": true, - "type": "c", - "major": 5, - "minor": 0, - "access": "rwm" - }, - { - "allow": true, - "type": "c", - "major": 5, - "minor": 1, - "access": "rwm" - }, - { - "allow": false, - "type": "c", - "major": 10, - "minor": 229, - "access": "rwm" - } - ], - "disableOOMKiller": false, - "memory": { - "limit": 536870912, - "reservation": 536870912, - "swap": 536870912, - "kernel": 0, - "kernelTCP": 0, - "swappiness": 20 - }, - "cpu": { - "shares": 1024, - "quota": 1000000, - "period": 500000, - "realtimeRuntime": 950000, - "realtimePeriod": 1000000, - "cpus": "2-3", - "mems": "0-7" - }, - "pids": { - "limit": 32771 - }, - "hugepageLimits": [ - { - "pageSize": "2MB", - "limit": 209715200 - }, - { - "pageSize": "2GB", - "limit": 10971201 - } - ], - "network": { - "classID": 1048577, - "priorities": [ - { - "name": "eth0", - "priority": 500 - }, - { - "name": "eth1", - "priority": 1000 - } - ] - }, - "blockIO": { - "weight": 10, - "leafWeight": 11, - "weightDevice": [ - { - "major": 8, - "minor": 0, - "weight": 500, - "leafWeight": 300 - }, - { - "major": 8, - "minor": 16, - "weight": 500 - } - ], - "throttleReadBpsDevice": [ - { - "major": 8, - "minor": 0, - "rate": 600 - } - ], - "throttleWriteBpsDevice": [ - { - "major": 8, - "minor": 1, - "rate": 601 - } - ], - "throttleReadIOPSDevice": [ - { - "major": 8, - "minor": 0, - "rate": 700 - } - ], - "throttleWriteIOPSDevice": [ - { - "major": 8, - "minor": 1, - "rate": 701 - } - ] - } - }, - "cgroupsPath": "/docker/7facfe3313cdca596b13ab6aab063e577f8540f875943e074c08603ee8efb52c", - "namespaces": [ - { - "type": "mount" - }, - { - "type": "network" - }, - { - "type": "uts" - }, - { - "type": "pid" - }, - { - "type": "ipc" - } - ], - "intelRdt": { - "l3CacheSchema": "L3:0=ffff0;1=3ff" - }, - "sysctl": { - "net.ipv4.ip_forward": "1", - "net.core.somaxconn": "256" - }, - "seccomp": { - "defaultAction": "SCMP_ACT_ERRNO", - "architectures": [ - "SCMP_ARCH_X86_64", - "SCMP_ARCH_X86", - "SCMP_ARCH_X32" - ], - "syscalls": [ - { - "name": "accept", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "accept4", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "access", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "alarm", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "alarm", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "bind", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "brk", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "capget", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "capset", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "chdir", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "chmod", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "chown", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "chown32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "clock_getres", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "clock_gettime", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "clock_nanosleep", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "close", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "connect", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "copy_file_range", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "creat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "dup", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "dup2", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "dup3", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "epoll_create", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "epoll_create1", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "epoll_ctl", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "epoll_ctl_old", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "epoll_pwait", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "epoll_wait", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "epoll_wait_old", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "eventfd", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "eventfd2", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "execve", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "execveat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "exit", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "exit_group", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "faccessat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fadvise64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fadvise64_64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fallocate", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fanotify_mark", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fchdir", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fchmod", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fchmodat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fchown", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fchown32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fchownat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fcntl", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fcntl64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fdatasync", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fgetxattr", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "flistxattr", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "flock", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fork", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fremovexattr", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fsetxattr", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fstat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fstat64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fstatat64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fstatfs", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fstatfs64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "fsync", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "ftruncate", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "ftruncate64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "futex", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "futimesat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getcpu", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getcwd", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getdents", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getdents64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getegid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getegid32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "geteuid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "geteuid32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getgid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getgid32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getgroups", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getgroups32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getitimer", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getpeername", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getpgid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getpgrp", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getpid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getppid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getpriority", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getrandom", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getresgid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getresgid32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getresuid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getresuid32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getrlimit", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "get_robust_list", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getrusage", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getsid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getsockname", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getsockopt", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "get_thread_area", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "gettid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "gettimeofday", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getuid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getuid32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "getxattr", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "inotify_add_watch", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "inotify_init", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "inotify_init1", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "inotify_rm_watch", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "io_cancel", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "ioctl", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "io_destroy", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "io_getevents", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "ioprio_get", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "ioprio_set", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "io_setup", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "io_submit", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "ipc", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "kill", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "lchown", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "lchown32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "lgetxattr", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "link", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "linkat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "listen", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "listxattr", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "llistxattr", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "_llseek", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "lremovexattr", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "lseek", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "lsetxattr", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "lstat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "lstat64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "madvise", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "memfd_create", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mincore", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mkdir", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mkdirat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mknod", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mknodat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mlock", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mlock2", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mlockall", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mmap", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mmap2", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mprotect", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mq_getsetattr", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mq_notify", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mq_open", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mq_timedreceive", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mq_timedsend", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mq_unlink", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "mremap", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "msgctl", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "msgget", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "msgrcv", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "msgsnd", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "msync", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "munlock", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "munlockall", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "munmap", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "nanosleep", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "newfstatat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "_newselect", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "open", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "openat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "pause", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "pipe", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "pipe2", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "poll", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "ppoll", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "prctl", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "pread64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "preadv", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "prlimit64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "pselect6", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "pwrite64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "pwritev", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "read", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "readahead", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "readlink", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "readlinkat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "readv", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "recv", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "recvfrom", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "recvmmsg", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "recvmsg", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "remap_file_pages", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "removexattr", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "rename", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "renameat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "renameat2", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "restart_syscall", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "rmdir", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "rt_sigaction", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "rt_sigpending", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "rt_sigprocmask", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "rt_sigqueueinfo", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "rt_sigreturn", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "rt_sigsuspend", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "rt_sigtimedwait", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "rt_tgsigqueueinfo", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sched_getaffinity", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sched_getattr", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sched_getparam", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sched_get_priority_max", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sched_get_priority_min", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sched_getscheduler", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sched_rr_get_interval", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sched_setaffinity", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sched_setattr", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sched_setparam", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sched_setscheduler", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sched_yield", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "seccomp", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "select", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "semctl", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "semget", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "semop", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "semtimedop", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "send", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sendfile", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sendfile64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sendmmsg", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sendmsg", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sendto", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setfsgid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setfsgid32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setfsuid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setfsuid32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setgid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setgid32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setgroups", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setgroups32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setitimer", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setpgid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setpriority", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setregid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setregid32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setresgid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setresgid32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setresuid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setresuid32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setreuid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setreuid32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setrlimit", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "set_robust_list", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setsid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setsockopt", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "set_thread_area", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "set_tid_address", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setuid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setuid32", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "setxattr", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "shmat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "shmctl", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "shmdt", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "shmget", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "shutdown", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sigaltstack", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "signalfd", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "signalfd4", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sigreturn", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "socket", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "socketcall", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "socketpair", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "splice", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "stat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "stat64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "statfs", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "statfs64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "symlink", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "symlinkat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sync", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sync_file_range", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "syncfs", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "sysinfo", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "syslog", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "tee", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "tgkill", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "time", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "timer_create", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "timer_delete", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "timerfd_create", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "timerfd_gettime", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "timerfd_settime", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "timer_getoverrun", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "timer_gettime", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "timer_settime", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "times", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "tkill", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "truncate", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "truncate64", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "ugetrlimit", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "umask", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "uname", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "unlink", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "unlinkat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "utime", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "utimensat", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "utimes", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "vfork", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "vmsplice", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "wait4", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "waitid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "waitpid", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "write", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "writev", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "personality", - "action": "SCMP_ACT_ALLOW", - "args": [ - { - "index": 0, - "value": 0, - "valueTwo": 0, - "op": "SCMP_CMP_EQ" - } - ] - }, - { - "name": "personality", - "action": "SCMP_ACT_ALLOW", - "args": [ - { - "index": 0, - "value": 8, - "valueTwo": 0, - "op": "SCMP_CMP_EQ" - } - ] - }, - { - "name": "personality", - "action": "SCMP_ACT_ALLOW", - "args": [ - { - "index": 0, - "value": 4294967295, - "valueTwo": 0, - "op": "SCMP_CMP_EQ" - } - ] - }, - { - "name": "arch_prctl", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "modify_ldt", - "action": "SCMP_ACT_ALLOW" - }, - { - "name": "clone", - "action": "SCMP_ACT_ALLOW", - "args": [ - { - "index": 0, - "value": 2080505856, - "valueTwo": 0, - "op": "SCMP_CMP_MASKED_EQ" - } - ] - }, - { - "name": "chroot", - "action": "SCMP_ACT_ALLOW" - } - ] - }, - "maskedPaths": [ - "/proc/kcore", - "/proc/latency_stats", - "/proc/timer_list", - "/proc/timer_stats", - "/proc/sched_debug", - "/sys/firmware" - ], - "readonlyPaths": [ - "/proc/asound", - "/proc/bus", - "/proc/fs", - "/proc/irq", - "/proc/sys", - "/proc/sysrq-trigger" - ] - } -} diff --git a/lcr-2.0.2.tar.gz b/lcr-2.0.2.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..e82ea04f2844641aa63b304448248f06d1a073b4 GIT binary patch literal 112181 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 - 0.0.1 diff --git a/lcr.yaml b/lcr.yaml new file mode 100644 index 0000000..099932e --- /dev/null +++ b/lcr.yaml @@ -0,0 +1,41 @@ +--- +version_control: gitee +src_repo: openEuler/lcr +tag_prefix: "^v" +seperator: "." +last_query: + time_stamp: 2020-07-01 16:03:11.677912422 +08:00 + raw_data: + { + "assets": [ + { + "browser_download_url": "https://gitee.com/openeuler/lcr/repository/archive/v2.0.2" + } + ], + "author": { + "avatar_url": "https://gitee.com/assets/no_portrait.png", + "events_url": "https://gitee.com/api/v5/users/duguhaotian/events{/privacy}", + "followers_url": "https://gitee.com/api/v5/users/duguhaotian/followers", + "following_url": "https://gitee.com/api/v5/users/duguhaotian/following_url{/other_user}", + "gists_url": "https://gitee.com/api/v5/users/duguhaotian/gists{/gist_id}", + "html_url": "https://gitee.com/duguhaotian", + "id": 5595769, + "login": "duguhaotian", + "name": "haozi007", + "organizations_url": "https://gitee.com/api/v5/users/duguhaotian/orgs", + "received_events_url": "https://gitee.com/api/v5/users/duguhaotian/received_events", + "repos_url": "https://gitee.com/api/v5/users/duguhaotian/repos", + "site_admin": false, + "starred_url": "https://gitee.com/api/v5/users/duguhaotian/starred{/owner}{/repo}", + "subscriptions_url": "https://gitee.com/api/v5/users/duguhaotian/subscriptions", + "type": "User", + "url": "https://gitee.com/api/v5/users/duguhaotian" + }, + "body": "- merge iSula-libutils into lcr", + "created_at": "2020-05-26T17:23:17+08:00", + "id": 70689, + "name": "v2.0.2", + "prerelease": false, + "tag_name": "v2.0.2", + "target_commitish": "9c98c586048841369739c66ee1fdf72548fc1ed6" + } \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index 1be0966..0000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,54 +0,0 @@ -# generate .c and .h files for json -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/json) - -# get liblcr source files -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} topsrcs) -message("-- Get top srcs: " ${topsrcs}) -aux_source_directory(${CMAKE_BINARY_DIR}/json generatesrcs) -message("-- Get generate srcs: " ${generatesrcs}) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/json/schema/src commonjsonsrcs) -message("-- Get common json srcs: " ${commonjsonsrcs}) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/json topjsonsrcs) -message("-- Get top json srcs: " ${topjsonsrcs}) - -# set liblcr library -add_library(liblcr ${LIBTYPE} ${topsrcs} ${topjsonsrcs} ${commonjsonsrcs} ${generatesrcs}) - -set(check_incs - ${LIBLXC_INCLUDE_DIR} - ${LIBYAJL_INCLUDE_DIR} - ) -set(check_libs - ${LIBLXC_LIBRARY} - ${LIBYAJL_LIBRARY} - ) -list(REMOVE_DUPLICATES check_incs) -list(REMOVE_DUPLICATES check_libs) - -# set liblcr include dirs -target_include_directories(liblcr - PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} - PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/json - PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/json/schema/src - PUBLIC ${CMAKE_BINARY_DIR}/json - PUBLIC ${CMAKE_BINARY_DIR}/conf - PUBLIC ${check_incs} - ) - -# set liblcr compile flags -set_target_properties(liblcr PROPERTIES PREFIX "") - -target_link_libraries(liblcr ${check_libs}) - -if (CMAKE_TOOLCHAIN_FILE) - target_link_directories(liblcr PUBLIC ${CMAKE_LIBRARY_PATH}) - target_link_libraries(liblcr ${EXTRAL_LINK_LIBS}) -endif() - -if (LCR_GCOV) - target_link_libraries(liblcr -lgcov) -endif() - -# install all files -install(TARGETS liblcr - LIBRARY DESTINATION ${LIB_INSTALL_DIR_DEFAULT} PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE) diff --git a/src/buffer.c b/src/buffer.c deleted file mode 100644 index 41ba266..0000000 --- a/src/buffer.c +++ /dev/null @@ -1,228 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide container buffer definition - ******************************************************************************/ -#define _GNU_SOURCE - -#include -#include - -#include "buffer.h" -#include "log.h" -#include "utils.h" - -/* buffer allocate */ -Buffer *buffer_alloc(size_t initial_size) -{ - Buffer *buf = NULL; - char *tmp = NULL; - - if (initial_size == 0) { - return NULL; - } - - buf = lcr_util_common_calloc_s(sizeof(Buffer)); - if (buf == NULL) { - return NULL; - } - - tmp = calloc(1, initial_size); - if (tmp == NULL) { - free(buf); - return NULL; - } - - buf->contents = tmp; - buf->bytes_used = 0; - buf->total_size = initial_size; - - return buf; -} - -/* buffer strlen */ -static size_t buffer_strlen(const Buffer *buf) -{ - return buf == NULL ? 0 : buf->bytes_used; -} - -/* buffer free */ -void buffer_free(Buffer *buf) -{ - if (buf == NULL) { - return; - } - free(buf->contents); - buf->contents = NULL; - free(buf); -} - -/* buffer has space */ -static bool buffer_has_space(const Buffer *buf, size_t desired_length) -{ - size_t bytes_remaining = 0; - - if (buf == NULL) { - return false; - } - bytes_remaining = buf->total_size - buf->bytes_used; - - return desired_length <= bytes_remaining; -} - -/* buffer grow */ -static int buffer_grow(Buffer *buf, size_t minimum_size) -{ - size_t factor = 0; - size_t new_size = 0; - char *tmp = NULL; - - if (buf == NULL) { - return -1; - } - - factor = buf->total_size; - if (factor < minimum_size) { - factor = minimum_size; - } - - if (factor > SIZE_MAX / 2) { - return -1; - } - - new_size = factor * 2; - if (new_size == 0) { - return -1; - } - - tmp = lcr_util_common_calloc_s(new_size); - if (tmp == NULL) { - ERROR("Out of memory"); - return -1; - } - - (void)memcpy(tmp, buf->contents, buf->total_size); - - free(buf->contents); - buf->contents = tmp; - buf->total_size = new_size; - - return 0; -} - -/* buffer cat */ -static void buffer_cat(Buffer *buf, const char *append, size_t length) -{ - size_t i = 0; - - if (buf == NULL) { - return; - } - - for (i = 0; i < length; i++) { - if (append[i] == '\0') { - break; - } - - *(buf->contents + buf->bytes_used + i) = append[i]; - } - - buf->bytes_used += i; - *(buf->contents + buf->bytes_used) = '\0'; -} - -/* buffer append */ -static int buffer_append(Buffer *buf, const char *append, size_t length) -{ - size_t desired_length = 0; - - if (buf == NULL) { - return -1; - } - - desired_length = length + 1; - if (!buffer_has_space(buf, desired_length)) { - if (buffer_grow(buf, desired_length) != 0) { - goto error; - } - } - - buffer_cat(buf, append, length); - - return 0; -error: - return -1; -} - -/* buffer nappendf */ -int buffer_nappendf(Buffer *buf, size_t length, const char *format, ...) -{ - int status = 0; - size_t printf_length = 0; - char *tmp = NULL; - va_list argp; - - if (buf == NULL) { - return -1; - } - - if (length > SIZE_MAX / sizeof(char) - 1) { - return -1; - } - printf_length = length + 1; - tmp = calloc(1, printf_length * sizeof(char)); - if (tmp == NULL) { - return -1; - } - - va_start(argp, format); - status = vsprintf(tmp, format, argp); - va_end(argp); - if (status < 0) { - goto error; - } - - status = buffer_append(buf, tmp, length); - if (status != 0) { - goto error; - } - - free(tmp); - return 0; -error: - free(tmp); - return -1; -} - -/* buffer to string */ -char *buffer_to_s(const Buffer *buf) -{ - size_t len; - char *result = NULL; - - if (buf == NULL) { - return NULL; - } - - len = buffer_strlen(buf); - if (len == SIZE_MAX) { - return NULL; - } - - result = calloc(1, len + 1); - if (result == NULL) { - return NULL; - } - (void)strncpy(result, buf->contents, len); - - return result; -} diff --git a/src/buffer.h b/src/buffer.h deleted file mode 100644 index 5bf79a6..0000000 --- a/src/buffer.h +++ /dev/null @@ -1,32 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide container buffer definition - ******************************************************************************/ -#ifndef LCR_BUFFER_H -#define LCR_BUFFER_H - -#include -#include -#include - -typedef struct Buffer { - char *contents; - size_t bytes_used; - size_t total_size; -} Buffer; - -Buffer *buffer_alloc(size_t initial_size); -void buffer_free(Buffer *buf); -int buffer_nappendf(Buffer *buf, size_t length, const char *format, ...); -char *buffer_to_s(const Buffer *buf); -#endif diff --git a/src/conf.c b/src/conf.c deleted file mode 100644 index 70bc66e..0000000 --- a/src/conf.c +++ /dev/null @@ -1,2590 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide container conf function - ******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "conf.h" -#include "lcrcontainer.h" -#include "lcrcontainer_extend.h" -#include "error.h" -#include "utils.h" -#include "log.h" -#include "buffer.h" - -#define SUB_UID_PATH "/etc/subuid" -#define SUB_GID_PATH "/etc/subgid" -#define ID_MAP_LEN 100 - -/* files limit checker */ -static int files_limit_checker(const char *value) -{ - long long limit = 0; - int ret = 0; - - ret = lcr_util_safe_llong(value, &limit); - if (ret) { - ret = -1; - } - - return ret; -} - -/* check console log file */ -static int check_console_log_file(const char *value) -{ - int ret = 0; - - if (value == NULL) { - return -1; - } - - if (strcmp(value, "none") == 0) { - ret = 1; - } - - return ret; -} - -/* check console log filesize */ -static int check_console_log_filesize(const char *value) -{ - int ret = -1; - int64_t tmp = 0; - int64_t min = 4 * SIZE_KB; - - if (value == NULL) { - return ret; - } - - if (lcr_parse_byte_size_string(value, &tmp) == 0 && tmp >= min) { - ret = 0; - } - - return ret; -} - -/* check oom score adj */ -static int check_oom_score_adj(const char *value) -{ - int ret = -1; - int tmp = 0; - int min = OOM_SCORE_ADJ_MIN; - int max = OOM_SCORE_ADJ_MAX; - - if (value == NULL) { - return ret; - } - - if (lcr_util_safe_int(value, &tmp) == 0 && tmp >= min && tmp <= max) { - ret = 0; - } - lcr_set_error_message(LCR_ERR_RUNTIME, "Invalid value %s, range for oom score adj is [%d, %d]", value, min, max); - return ret; -} -/* check console log filerotate */ -static int check_console_log_filerotate(const char *value) -{ - int ret = -1; - unsigned int tmp = 0; - - if (value == NULL) { - return ret; - } - - if (lcr_util_safe_uint(value, &tmp) == 0) { - ret = 0; - } - - return ret; -} - -/* check rootfs mount */ -static int check_rootfs_mount(const char *value) -{ - if (value == NULL) { - return -1; - } - - if (!lcr_util_dir_exists(value)) { - lcr_set_error_message(LCR_ERR_RUNTIME, "Container rootfs mount path '%s' is not exist", value); - return -1; - } - - return 0; -} - -static inline bool is_native_umask_normal(const char *value) -{ - return strcmp(value, "normal") == 0; -} - -static inline bool is_native_umask_secure(const char *value) -{ - return strcmp(value, "secure") == 0; -} - - -/* check umask */ -static int check_native_umask(const char *value) -{ - if (value == NULL) { - return -1; - } - - if (!is_native_umask_normal(value) && !is_native_umask_secure(value)) { - ERROR("Invalid native umask: %s", value); - return -1; - } - - return 0; -} - -/* check system container */ -static int check_system_container(const char *value) -{ - if (value == NULL) { - return -1; - } - - if (strcmp(value, "true") != 0) { - ERROR("Invalid system container: %s", value); - return -1; - } - - return 0; -} - -/* check cgroup dir */ -static int check_cgroup_dir(const char *value) -{ - if (value == NULL) { - return -1; - } - return 0; -} - -static const lcr_annotation_item_t g_require_annotations[] = { - { - "files.limit", - "lxc.cgroup.files.limit", - files_limit_checker, - }, - { - "log.console.file", - "lxc.console.logfile", - check_console_log_file, - }, - { - "log.console.filesize", - "lxc.console.size", - check_console_log_filesize, - }, - { - "log.console.filerotate", - "lxc.console.rotate", - check_console_log_filerotate, - }, - { - "rootfs.mount", - "lxc.rootfs.mount", - check_rootfs_mount, - }, - { - "cgroup.dir", - "lxc.cgroup.dir", - check_cgroup_dir, - }, - { - "native.umask", - "lxc.isulad.umask", - check_native_umask, - }, - { - "system.container", - "lxc.isulad.systemd", - check_system_container, - }, - { - "proc.oom_score_adj", - "lxc.proc.oom_score_adj", - check_oom_score_adj, - }, -}; - -/* create lcr list node */ -struct lcr_list *create_lcr_list_node(const char *key, const char *value) -{ - struct lcr_list *node = NULL; - lcr_config_item_t *entry = NULL; - - node = lcr_util_common_calloc_s(sizeof(*node)); - if (node == NULL) { - return NULL; - } - entry = lcr_util_common_calloc_s(sizeof(*entry)); - if (entry == NULL) { - free(node); - return NULL; - } - entry->name = lcr_util_strdup_s(key); - - entry->value = lcr_util_strdup_s(value); - - node->elem = entry; - return node; -} - -/* free lcr list node */ -void free_lcr_list_node(struct lcr_list *node) -{ - lcr_config_item_t *entry = NULL; - - if (node == NULL) { - return; - } - - entry = node->elem; - if (entry != NULL) { - free(entry->name); - free(entry->value); - } - free(node->elem); - node->elem = NULL; - free(node); -} - -/* trans oci hostname */ -struct lcr_list *trans_oci_hostname(const char *hostname) -{ - if (hostname == NULL) { - return NULL; - } - - return create_lcr_list_node("lxc.uts.name", hostname); -} - -static bool valid_sep_len(size_t sep_len, size_t len) -{ - if (sep_len && (sep_len != 1) && (len > SIZE_MAX / sep_len + 1)) { - return false; - } - - return true; -} - -/* capabilities join */ -static char *capabilities_join(const char *sep, const char **parts, size_t len) -{ - char *result = NULL; - size_t sep_len; - size_t result_len; - size_t iter; - - sep_len = strlen(sep); - if (valid_sep_len(sep_len, len) == false) { - return NULL; - } - result_len = (len - 1) * sep_len; - /* calculate new string length - * dont calculate `CAP_` - */ - for (iter = 0; iter < len; iter++) { - if (result_len > 4 && (result_len - 4 >= SIZE_MAX - strlen(parts[iter]))) { - return NULL; - } - result_len += strlen(parts[iter]) - 4; - } - - result = calloc(result_len + 1, 1); - if (result == NULL) { - return NULL; - } - - for (iter = 0; iter < len - 1; iter++) { - (void)strcat(result, &(parts[iter][4])); - (void)strcat(result, sep); - } - (void)strcat(result, &(parts[len - 1][4])); - - // Lower case - for (iter = 0; iter < result_len; iter++) { - if (result[iter] >= 'A' && result[iter] <= 'Z') { - result[iter] = (char)(result[iter] + 32); - } - } - - return result; -} - -#define UID_MAX_SIZE 21 -/* UID to use within a private user namespace for init */ -static int trans_oci_process_init_uid(const oci_runtime_spec_process *proc, struct lcr_list *conf) -{ - struct lcr_list *node = NULL; - char buf[UID_MAX_SIZE] = { 0 }; - int nret; - int ret = -1; - if (proc->user != NULL && proc->user->uid != INVALID_INT) { - nret = snprintf(buf, sizeof(buf), "%u", (unsigned int)proc->user->uid); - if (nret < 0 || (size_t)nret >= sizeof(buf)) { - goto out; - } - - node = create_lcr_list_node("lxc.init.uid", buf); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - ret = 0; -out: - return ret; -} - -/* GID to use within a private user namespace for init */ -static int trans_oci_process_init_gid(const oci_runtime_spec_process *proc, struct lcr_list *conf) -{ - struct lcr_list *node = NULL; - char buf[UID_MAX_SIZE] = { 0 }; - int nret; - int ret = -1; - if (proc->user != NULL && proc->user->gid != INVALID_INT) { - nret = snprintf(buf, sizeof(buf), "%u", (unsigned int)proc->user->gid); - if (nret < 0 || (size_t)nret >= sizeof(buf)) { - goto out; - } - - node = create_lcr_list_node("lxc.init.gid", buf); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - ret = 0; -out: - return ret; -} - -/* additional groups for init command */ -static int trans_oci_process_init_groups(const oci_runtime_spec_process *proc, struct lcr_list *conf) -{ - struct lcr_list *node = NULL; - int nret; - size_t i = 0; - int ret = -1; - if (proc->user != NULL && proc->user->additional_gids != NULL && proc->user->additional_gids_len > 0) { - if (proc->user->additional_gids_len > (SIZE_MAX / (LCR_NUMSTRLEN64 + 1))) { - goto out; - } - - size_t total_len = (LCR_NUMSTRLEN64 + 1) * proc->user->additional_gids_len; - char *gids = lcr_util_common_calloc_s(total_len); - if (gids == NULL) { - goto out; - } - - nret = snprintf(gids, total_len, "%u", (unsigned int)(proc->user->additional_gids[0])); - if (nret < 0 || (size_t)nret >= total_len) { - free(gids); - goto out; - } - for (i = 1; i < proc->user->additional_gids_len; i++) { - size_t old_len = strlen(gids); - nret = snprintf(gids + old_len, total_len - old_len, " %u", - (unsigned int)(proc->user->additional_gids[i])); - if (nret < 0 || (size_t)nret >= (total_len - old_len)) { - free(gids); - goto out; - } - } - - node = create_lcr_list_node("lxc.isulad.init.groups", gids); - free(gids); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - ret = 0; -out: - return ret; -} - -/* Sets the command to use as the init system for the containers */ -static int trans_oci_process_init_args(const oci_runtime_spec_process *proc, struct lcr_list *conf) -{ - struct lcr_list *node = NULL; - size_t i = 0; - int ret = -1; - for (i = 0; i < proc->args_len; i++) { - node = create_lcr_list_node("lxc.isulad.init.args", proc->args[i]); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - ret = 0; -out: - return ret; -} - -/* working directory to use within container */ -static int trans_oci_process_init_cwd(const oci_runtime_spec_process *proc, struct lcr_list *conf) -{ - struct lcr_list *node = NULL; - int ret = -1; - if (proc->cwd != NULL) { - node = create_lcr_list_node("lxc.init.cwd", proc->cwd); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - ret = 0; -out: - return ret; -} - -/* trans oci process init */ -static int trans_oci_process_init(const oci_runtime_spec_process *proc, struct lcr_list *conf) -{ - int ret = -1; - if (trans_oci_process_init_uid(proc, conf)) { - goto out; - } - - if (trans_oci_process_init_gid(proc, conf)) { - goto out; - } - - if (trans_oci_process_init_groups(proc, conf)) { - goto out; - } - - if (trans_oci_process_init_args(proc, conf)) { - goto out; - } - - if (trans_oci_process_init_cwd(proc, conf)) { - goto out; - } - - ret = 0; -out: - return ret; -} - -/* trans oci process env and cap */ -static int trans_oci_process_env_and_cap(const oci_runtime_spec_process *proc, struct lcr_list *conf) -{ - struct lcr_list *node = NULL; - char *boundings = NULL; - int ret = -1; - size_t i; - - for (i = 0; i < proc->env_len; i++) { - char *replaced = lcr_util_string_replace(" ", SPACE_MAGIC_STR, proc->env[i]); - if (replaced == NULL) { - ERROR("memory allocation error"); - goto out; - } - node = create_lcr_list_node("lxc.environment", replaced); - free(replaced); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - - if (proc->capabilities != NULL && proc->capabilities->bounding_len > 0) { - boundings = - capabilities_join(" ", (const char **)(proc->capabilities->bounding), proc->capabilities->bounding_len); - if (boundings == NULL) { - ERROR("Failed to join bounding capabilities"); - goto out; - } - node = create_lcr_list_node("lxc.cap.keep", boundings); - free(boundings); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } else { - node = create_lcr_list_node("lxc.cap.keep", "ISULAD_KEEP_NONE"); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - ret = 0; -out: - return ret; -} - -/* trans oci process prlimit */ -static int trans_oci_process_prlimit(const oci_runtime_spec_process *proc, struct lcr_list *conf) -{ - struct lcr_list *node = NULL; - int ret = -1; - int nret; - size_t i; - - for (i = 0; i < proc->rlimits_len; i++) { - oci_runtime_spec_process_rlimits_element *lr = proc->rlimits[i]; - char buf_key[30] = { 0 }; - char buf_value[60] = { 0 }; - size_t j; - char *type = lcr_util_strdup_s(lr->type); - - // Lower case type,eg. RLIMIT_NOFILE -> RLIMIT_nofile - for (j = strlen("RLIMIT_"); j < strlen(type); j++) { - type[j] = (char)tolower(type[j]); - } - - // Skip `RLIMIT_` - nret = snprintf(buf_key, sizeof(buf_key), "lxc.prlimit.%s", &(type[7])); - free(type); - if (nret < 0 || (size_t)nret >= sizeof(buf_key)) { - goto out; - } - - // We always use format `soft_limit:hard_limit` - nret = snprintf(buf_value, sizeof(buf_value), "%llu:%llu", (unsigned long long)lr->soft, - (unsigned long long)lr->hard); - if (nret < 0 || (size_t)nret >= sizeof(buf_value)) { - goto out; - } - - node = create_lcr_list_node(buf_key, buf_value); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - ret = 0; -out: - return ret; -} - -/* trans oci process no new privs */ -static int trans_oci_process_no_new_privs(const oci_runtime_spec_process *proc, struct lcr_list *conf) -{ - struct lcr_list *node = NULL; - int ret = -1; - - if (proc->no_new_privileges) { - node = create_lcr_list_node("lxc.no_new_privs", "1"); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - ret = 0; -out: - return ret; -} - -static int trans_oci_process_apparmor(const oci_runtime_spec_process *proc, struct lcr_list *conf) -{ - struct lcr_list *node = NULL; - int ret = -1; - - if (proc->apparmor_profile != NULL) { - node = create_lcr_list_node("lxc.aa_profile", proc->apparmor_profile); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - - ret = 0; -out: - return ret; -} - -static int trans_oci_process_selinux(const oci_runtime_spec_process *proc, struct lcr_list *conf) -{ - struct lcr_list *node = NULL; - int ret = -1; - - if (proc->selinux_label != NULL) { - node = create_lcr_list_node("lxc.selinux.context", proc->selinux_label); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - - ret = 0; -out: - return ret; -} - -/* trans oci process apparmor and selinux */ -static int trans_oci_process_apparmor_and_selinux(const oci_runtime_spec_process *proc, struct lcr_list *conf) -{ - int ret = -1; - - if (trans_oci_process_apparmor(proc, conf) != 0) { - goto out; - } - - if (trans_oci_process_selinux(proc, conf) != 0) { - goto out; - } - - ret = 0; -out: - return ret; -} - -/* trans oci process */ -struct lcr_list *trans_oci_process(const oci_runtime_spec_process *proc) -{ - struct lcr_list *conf = NULL; - - conf = lcr_util_common_calloc_s(sizeof(struct lcr_list)); - if (conf == NULL) { - return NULL; - } - lcr_list_init(conf); - - if (trans_oci_process_init(proc, conf)) { - goto out_free; - } - - if (trans_oci_process_env_and_cap(proc, conf)) { - goto out_free; - } - - if (trans_oci_process_prlimit(proc, conf)) { - goto out_free; - } - - if (trans_oci_process_no_new_privs(proc, conf)) { - goto out_free; - } - - if (trans_oci_process_apparmor_and_selinux(proc, conf)) { - goto out_free; - } - - return conf; - -out_free: - lcr_free_config(conf); - free(conf); - return NULL; -} - -#define APPEND_COMMA_END_SIZE 2 -/* trans oci root rootfs */ -static int trans_oci_root_rootfs(const oci_runtime_spec_root *root, struct lcr_list *conf) -{ - struct lcr_list *node = NULL; - int ret = -1; - - if ((root != NULL) && root->path != NULL) { - if (strcmp(root->path, "/") != 0) { - node = create_lcr_list_node("lxc.rootfs.path", root->path); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - } - ret = 0; -out: - return ret; -} - -static inline bool is_root_readonly(const oci_runtime_spec_root *root) -{ - return root != NULL && root->readonly; -} - -/* trans oci root rootfsoptions */ -static int trans_oci_root_rootfs_options(const oci_runtime_spec_root *root, struct lcr_list *conf, - const oci_runtime_config_linux *linux) -{ - struct lcr_list *node = NULL; - char *value = NULL; - char *tmpvalue = NULL; - int ret = -1; - int nret; - - if (is_root_readonly(root)) { - value = lcr_util_strdup_s("ro"); - } - - if ((linux != NULL) && linux->rootfs_propagation != NULL) { - if (value != NULL) { - size_t newsize; - if (strlen(value) > (SIZE_MAX - strlen(linux->rootfs_propagation)) - APPEND_COMMA_END_SIZE) { - ERROR("Out of range!"); - goto out; - } - newsize = strlen(linux->rootfs_propagation) + strlen(value) + APPEND_COMMA_END_SIZE; - nret = lcr_mem_realloc((void **)&tmpvalue, newsize, value, strlen(value)); - if (nret < 0) { - ERROR("Out of memory"); - goto out; - } - value = tmpvalue; - nret = snprintf(value + strlen(value), newsize - strlen(value), ",%s", linux->rootfs_propagation); - if (nret < 0 || (size_t)nret >= (newsize - strlen(value))) { - ERROR("Failed to print string"); - goto out; - } - } else { - value = lcr_util_strdup_s(linux->rootfs_propagation); - } - } - - if (value != NULL) { - node = create_lcr_list_node("lxc.rootfs.options", value); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - ret = 0; -out: - free(value); - return ret; -} - -/* trans oci root */ -struct lcr_list *trans_oci_root(const oci_runtime_spec_root *root, const oci_runtime_config_linux *linux) -{ - struct lcr_list *conf = NULL; - - conf = lcr_util_common_calloc_s(sizeof(*conf)); - if (conf == NULL) { - return NULL; - } - lcr_list_init(conf); - - if (trans_oci_root_rootfs(root, conf)) { - goto out_free; - } - - if (trans_oci_root_rootfs_options(root, conf, linux)) { - goto out_free; - } - - return conf; -out_free: - lcr_free_config(conf); - free(conf); - - return NULL; -} - -static inline bool is_mount_options_invalid(const defs_mount *mount) -{ - return mount == NULL || mount->type == NULL; -} - -static inline bool is_mount_type_bind(const char *type) -{ - return strcmp(type, "bind") == 0; -} - -static inline bool is_mount_type_cgroup(const char *type) -{ - return strcmp(type, "cgroup") == 0; -} - -static inline bool is_mount_type_sysfs(const char *type) -{ - return strcmp(type, "sysfs") == 0; -} - -static inline bool is_mount_type_proc(const char *type) -{ - return strcmp(type, "proc") == 0; -} - -/* trans mount to lxc options */ -static char *trans_mount_to_lxc_options(const defs_mount *mount) -{ - char *result = NULL; - char *prefix = NULL; - char *lxc_options = NULL; - int rc; - bool isdir = true; - struct stat st; - - if (is_mount_options_invalid(mount)) { - return NULL; - } - - if (is_mount_type_bind(mount->type)) { - rc = stat(mount->source, &st); - if (rc != 0) { - ERROR("Failed to get stat of %s", mount->source); - goto free_out; - } - isdir = S_ISDIR(st.st_mode); - } - - lxc_options = isdir ? ",create=dir" : ",create=file"; - - prefix = lcr_util_string_join(",", (const char **)mount->options, mount->options_len); - if (prefix == NULL) { - prefix = lcr_util_strdup_s("defaults"); - } - - result = lcr_util_string_append(lxc_options, prefix); - free(prefix); - return result; - -free_out: - free(prefix); - free(result); - return NULL; -} - -static bool get_mount_option_ro(const defs_mount *mount) -{ - bool ro = false; - - if ((mount->options != NULL) && mount->options_len) { - size_t i = 0; - for (i = 0; i < mount->options_len; i++) { - if ((mount->options[i] != NULL) && !strcmp(mount->options[i], "ro")) { - ro = true; - break; - } - } - } - - return ro; -} - -static char *get_mount_readmode_options(const defs_mount *mount, const char *type) -{ - char *options = NULL; - bool readonly = get_mount_option_ro(mount); - - if (is_mount_type_cgroup(type)) { - if (readonly) { - options = lcr_util_strdup_s("ro:force"); - } else { - options = lcr_util_strdup_s("rw:force"); - } - } else { - if (readonly) { - options = lcr_util_strdup_s("ro"); - } else { - options = lcr_util_strdup_s("rw"); - } - } - - return options; -} - -/* trans mount auto to lxc */ -static struct lcr_list *trans_mount_auto_to_lxc(const defs_mount *mount) -{ - struct lcr_list *node = NULL; - size_t buf_len = 0; - char *buf = NULL; - char *options = NULL; - int ret; - char *type = NULL; - - if (is_mount_options_invalid(mount)) { - ERROR("oci container mounts element(type) is empty"); - return NULL; - } - type = mount->type; - if (is_mount_type_sysfs(type)) { - type = "sys"; - } - - options = get_mount_readmode_options(mount, type); - if (options == NULL) { - ERROR("Failed to trans to lxc options"); - goto out_free; - } - - buf_len = strlen(type) + strlen(options) + 2; - buf = calloc(buf_len, 1); - if (buf == NULL) { - DEBUG("Out of memory"); - goto out_free; - } - - ret = snprintf(buf, buf_len, "%s:%s", type, options); - if (ret < 0 || (size_t)ret >= buf_len) { - DEBUG("Failed to print string"); - goto out_free; - } - node = create_lcr_list_node("lxc.mount.auto", buf); - -out_free: - free(options); - free(buf); - return node; -} - -/* trans mount entry to lxc */ -static struct lcr_list *trans_mount_entry_to_lxc(const defs_mount *mount) -{ - struct lcr_list *node = NULL; - size_t buf_len = 0; - char *buf = NULL; - char *options = NULL; - char *replaced_dest = NULL; - int ret; - - char *replaced_source = lcr_util_string_replace(" ", SPACE_MAGIC_STR, mount->source); - if (replaced_source == NULL) { - ERROR("memory allocation error"); - goto err_out; - } - replaced_dest = lcr_util_string_replace(" ", SPACE_MAGIC_STR, mount->destination); - if (replaced_dest == NULL) { - ERROR("memory allocation error"); - free(replaced_source); - goto err_out; - } - - options = trans_mount_to_lxc_options(mount); - if (options == NULL) { - ERROR("Failed to trans to lxc options"); - goto out_free; - } - - buf_len = strlen(replaced_dest) + strlen(mount->type) + strlen(replaced_source) + strlen(options) + 8; - buf = calloc(buf_len, 1); - if (buf == NULL) { - ERROR("Out of memory"); - goto out_free; - } - - ret = snprintf(buf, buf_len, "%s %s %s %s 0 0", replaced_source, replaced_dest + 1, mount->type, options); - if (ret < 0 || (size_t)ret >= buf_len) { - ERROR("Failed to print string"); - goto out_free; - } - node = create_lcr_list_node("lxc.mount.entry", buf); - -out_free: - free(options); - free(buf); - free(replaced_source); - free(replaced_dest); -err_out: - return node; -} - -bool is_system_container(const oci_runtime_spec *container) -{ - size_t i = 0; - for (i = 0; container->annotations != NULL && i < container->annotations->len; i++) { - if (strcmp(container->annotations->keys[i], "system.container") == 0) { - return true; - } - } - return false; -} - -static bool is_external_rootfs(const oci_runtime_spec *container) -{ - size_t i = 0; - for (i = 0; container->annotations != NULL && i < container->annotations->len; i++) { - if (strcmp(container->annotations->keys[i], "external.rootfs") == 0) { - return true; - } - } - return false; -} - -static struct lcr_list *trans_oci_mounts_normal(const defs_mount *tmp) -{ - struct lcr_list *node = NULL; - if (is_mount_type_cgroup(tmp->type) || is_mount_type_proc(tmp->type) || is_mount_type_sysfs(tmp->type)) { - node = trans_mount_auto_to_lxc(tmp); - } else { - node = trans_mount_entry_to_lxc(tmp); - } - - return node; -} - -static struct lcr_list *trans_oci_mounts_system_container(const defs_mount *tmp) -{ - struct lcr_list *node = NULL; - if (is_mount_type_cgroup(tmp->type) || (is_mount_type_proc(tmp->source) && is_mount_type_proc(tmp->type)) || - is_mount_type_sysfs(tmp->type)) { - node = trans_mount_auto_to_lxc(tmp); - } else { - node = trans_mount_entry_to_lxc(tmp); - } - - return node; -} - -static struct lcr_list *trans_oci_mounts_node(const oci_runtime_spec *c, const defs_mount *tmp) -{ - struct lcr_list *node = NULL; - // system container - if (is_system_container(c)) { - node = trans_oci_mounts_system_container(tmp); - } else { - node = trans_oci_mounts_normal(tmp); - } - - return node; -} - -static inline bool is_mount_destination_dev(const char *destination) -{ - return destination != NULL && strcmp(destination, "/dev") == 0; -} - -static inline bool should_ignore_dev_mount(const defs_mount *tmp, bool system_container, bool external_rootfs) -{ - return system_container && external_rootfs && is_mount_destination_dev(tmp->destination); -} - -/* trans oci mounts */ -struct lcr_list *trans_oci_mounts(const oci_runtime_spec *c) -{ - struct lcr_list *conf = NULL; - struct lcr_list *node = NULL; - defs_mount *tmp = NULL; - size_t i; - bool system_container = is_system_container(c); - bool external_rootfs = is_external_rootfs(c); - - conf = lcr_util_common_calloc_s(sizeof(*conf)); - if (conf == NULL) { - return NULL; - } - lcr_list_init(conf); - - for (i = 0; i < c->mounts_len; i++) { - tmp = c->mounts[i]; - if (tmp->type == NULL) { - goto out_free; - } - - if (should_ignore_dev_mount(tmp, system_container, external_rootfs)) { - continue; - } - node = trans_oci_mounts_node(c, tmp); - if (node == NULL) { - goto out_free; - } - lcr_list_add_tail(conf, node); - } - - return conf; -out_free: - lcr_free_config(conf); - free(conf); - - return NULL; -} - -static int trans_one_oci_id_mapping(struct lcr_list *conf, const char *typ, const defs_id_mapping *id, const char *path) -{ - int nret; - struct lcr_list *node = NULL; - char buf_value[300] = { 0 }; - char subid[ID_MAP_LEN] = { 0 }; - - nret = snprintf(buf_value, sizeof(buf_value), "%s %u %u %u", typ, id->container_id, id->host_id, id->size); - if (nret < 0 || (size_t)nret >= sizeof(buf_value)) { - return -1; - } - - node = create_lcr_list_node("lxc.idmap", buf_value); - if (node == NULL) { - return -1; - } - lcr_list_add_tail(conf, node); - - nret = snprintf(subid, sizeof(subid), "%u:%u:%u", id->container_id, id->host_id, id->size); - if (nret < 0 || (size_t)nret >= sizeof(subid)) { - return -1; - } - nret = lcr_util_atomic_write_file(path, subid); - if (nret < 0) { - return -1; - } - return 0; -} - -static int trans_oci_uid_mapping(struct lcr_list *conf, defs_id_mapping **uid_mappings, size_t uid_mappings_len) -{ - size_t i; - - for (i = 0; uid_mappings != NULL && i < uid_mappings_len; i++) { - int nret = trans_one_oci_id_mapping(conf, "u", uid_mappings[i], SUB_UID_PATH); - if (nret < 0) { - return nret; - } - } - return 0; -} - -static int trans_oci_gid_mapping(struct lcr_list *conf, defs_id_mapping **gid_mappings, size_t gid_mappings_len) -{ - size_t i; - - for (i = 0; gid_mappings != NULL && i < gid_mappings_len; i++) { - int nret = trans_one_oci_id_mapping(conf, "g", gid_mappings[i], SUB_GID_PATH); - if (nret < 0) { - return nret; - } - } - return 0; -} - -/* trans oci id mapping */ -static struct lcr_list *trans_oci_id_mapping(const oci_runtime_config_linux *l) -{ - struct lcr_list *conf = NULL; - int nret = 0; - - conf = lcr_util_common_calloc_s(sizeof(*conf)); - if (conf == NULL) { - return NULL; - } - lcr_list_init(conf); - - nret = trans_oci_uid_mapping(conf, l->uid_mappings, l->uid_mappings_len); - if (nret < 0) { - goto out_free; - } - - nret = trans_oci_gid_mapping(conf, l->gid_mappings, l->gid_mappings_len); - if (nret < 0) { - goto out_free; - } - - return conf; - -out_free: - lcr_free_config(conf); - free(conf); - - return NULL; -} - -#define WILDCARD (-1LL) - -static int trans_conf_int(struct lcr_list *conf, const char *lxc_key, int val) -{ - struct lcr_list *node = NULL; - char buf_value[300] = { 0 }; - int nret; - - nret = snprintf(buf_value, sizeof(buf_value), "%d", val); - if (nret < 0 || (size_t)nret >= sizeof(buf_value)) { - return -1; - } - node = create_lcr_list_node(lxc_key, buf_value); - if (node == NULL) { - return -1; - } - lcr_list_add_tail(conf, node); - return 0; -} - -static int trans_conf_uint32(struct lcr_list *conf, const char *lxc_key, uint32_t val) -{ - struct lcr_list *node = NULL; - char buf_value[300] = { 0 }; - int nret; - - nret = snprintf(buf_value, sizeof(buf_value), "%u", (unsigned int)val); - if (nret < 0 || (size_t)nret >= sizeof(buf_value)) { - return -1; - } - node = create_lcr_list_node(lxc_key, buf_value); - if (node == NULL) { - return -1; - } - lcr_list_add_tail(conf, node); - return 0; -} - -static int trans_conf_int64(struct lcr_list *conf, const char *lxc_key, int64_t val) -{ - struct lcr_list *node = NULL; - char buf_value[300] = { 0 }; - int nret; - - nret = snprintf(buf_value, sizeof(buf_value), "%lld", (long long)val); - if (nret < 0 || (size_t)nret >= sizeof(buf_value)) { - return -1; - } - node = create_lcr_list_node(lxc_key, buf_value); - if (node == NULL) { - return -1; - } - lcr_list_add_tail(conf, node); - return 0; -} - -static int trans_conf_uint64(struct lcr_list *conf, const char *lxc_key, uint64_t val) -{ - struct lcr_list *node = NULL; - char buf_value[300] = { 0 }; - int nret; - - nret = snprintf(buf_value, sizeof(buf_value), "%llu", (unsigned long long)val); - if (nret < 0 || (size_t)nret >= sizeof(buf_value)) { - return -1; - } - node = create_lcr_list_node(lxc_key, buf_value); - if (node == NULL) { - return -1; - } - lcr_list_add_tail(conf, node); - return 0; -} - -/* trans resources mem swap */ -static int trans_resources_mem_swap(const oci_runtime_config_linux_resources *res, struct lcr_list *conf) -{ - int ret = -1; - int nret; - - if (res->memory->reservation != INVALID_INT) { - /* set soft limit of memory usage */ - nret = trans_conf_int64(conf, "lxc.cgroup.memory.soft_limit_in_bytes", res->memory->reservation); - if (nret < 0) { - goto out; - } - } - if (res->memory->swap != INVALID_INT) { - /* set limit of memory+swap usage */ - nret = trans_conf_int64(conf, "lxc.cgroup.memory.memsw.limit_in_bytes", res->memory->swap); - if (nret < 0) { - goto out; - } - } - - if (res->memory->swappiness != -1) { - /* set swappiness parameter of vmscan */ - nret = trans_conf_uint64(conf, "lxc.cgroup.memory.swappiness", res->memory->swappiness); - if (nret < 0) { - goto out; - } - } - ret = 0; -out: - return ret; -} - -static int trans_resources_mem_limit(const oci_runtime_config_linux_resources *res, struct lcr_list *conf) -{ - if (res->memory->limit != INVALID_INT) { - /* set limit of memory usage */ - int nret = trans_conf_int64(conf, "lxc.cgroup.memory.limit_in_bytes", res->memory->limit); - if (nret < 0) { - return -1; - } - } - return 0; -} - -/* trans resources mem kernel */ -static int trans_resources_mem_kernel(const oci_runtime_config_linux_resources *res, struct lcr_list *conf) -{ - int ret = -1; - int nret; - - if (res->memory->kernel != INVALID_INT) { - /* set hard limit for kernel memory */ - nret = trans_conf_int64(conf, "lxc.cgroup.memory.kmem.limit_in_bytes", res->memory->kernel); - if (nret < 0) { - goto out; - } - } - if (res->memory->kernel_tcp != INVALID_INT) { - /* set hard limit for tcp buf memory */ - nret = trans_conf_int64(conf, "lxc.cgroup.memory.kmem.tcp.limit_in_bytes", res->memory->kernel_tcp); - if (nret < 0) { - goto out; - } - } - ret = 0; -out: - return ret; -} - -static int trans_resources_mem_disable_oom(const oci_runtime_config_linux_resources *res, struct lcr_list *conf) -{ - struct lcr_list *node = NULL; - if (res->memory->disable_oom_killer) { - node = create_lcr_list_node("lxc.cgroup.memory.oom_control", "1"); - if (node == NULL) { - return -1; - } - lcr_list_add_tail(conf, node); - } - return 0; -} - -/* trans resources memory */ -static int trans_resources_memory(const oci_runtime_config_linux_resources *res, struct lcr_list *conf) -{ - int ret = -1; - - if (res->memory == NULL) { - return 0; - } - - if (trans_resources_mem_limit(res, conf) != 0) { - goto out; - } - - if (trans_resources_mem_swap(res, conf) != 0) { - goto out; - } - - if (trans_resources_mem_kernel(res, conf) != 0) { - goto out; - } - - if (trans_resources_mem_disable_oom(res, conf) != 0) { - goto out; - } - ret = 0; -out: - return ret; -} - -static int trans_resources_devices_node(const oci_runtime_defs_linux_device_cgroup *lrd, struct lcr_list *conf, - const char *buf_value) -{ - struct lcr_list *node = NULL; - int ret = -1; - - if (lrd->allow == true) { - node = create_lcr_list_node("lxc.cgroup.devices.allow", buf_value); - } else { - node = create_lcr_list_node("lxc.cgroup.devices.deny", buf_value); - } - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - - ret = 0; -out: - return ret; -} - -static int trans_resources_devices_no_match(const oci_runtime_defs_linux_device_cgroup *lrd, char *buf_value, - size_t size) -{ - int ret = 0; - if (lrd->minor != WILDCARD) { - ret = snprintf(buf_value, size, "%s %lld:%lld %s", lrd->type ? lrd->type : "a", (long long)(lrd->major), - (long long)lrd->minor, lrd->access ? lrd->access : "rwm"); - } else { - ret = snprintf(buf_value, size, "%s %lld:* %s", lrd->type ? lrd->type : "a", (long long)(lrd->major), - lrd->access ? lrd->access : "rwm"); - } - - return ret; -} - -static int trans_resources_devices_match(const oci_runtime_defs_linux_device_cgroup *lrd, char *buf_value, size_t size) -{ - int ret = 0; - if (lrd->minor != WILDCARD) { - ret = snprintf(buf_value, size, "%s *:%lld %s", lrd->type ? lrd->type : "a", (long long)(lrd->minor), - lrd->access ? lrd->access : "rwm"); - } else { - ret = snprintf(buf_value, size, "%s *:* %s", lrd->type ? lrd->type : "a", lrd->access ? lrd->access : "rwm"); - } - - return ret; -} - -static int trans_resources_devices_ret(const oci_runtime_defs_linux_device_cgroup *lrd, char *buf_value, size_t size) -{ - int ret = 0; - if (lrd->major != WILDCARD) { - ret = trans_resources_devices_no_match(lrd, buf_value, size); - } else { - ret = trans_resources_devices_match(lrd, buf_value, size); - } - - return ret; -} - -/* trans resources devices */ -static int trans_resources_devices(const oci_runtime_config_linux_resources *res, struct lcr_list *conf) -{ - int ret = -1; - size_t i = 0; - char buf_value[300] = { 0 }; - - for (i = 0; i < res->devices_len; i++) { - oci_runtime_defs_linux_device_cgroup *lrd = res->devices[i]; - if (trans_resources_devices_ret(lrd, buf_value, sizeof(buf_value)) < 0) { - goto out; - } - - if (trans_resources_devices_node(lrd, conf, buf_value) < 0) { - goto out; - } - } - ret = 0; -out: - return ret; -} - -/* trans resources cpu cfs */ -static int trans_resources_cpu_cfs(const oci_runtime_config_linux_resources *res, struct lcr_list *conf) -{ - int ret = -1; - - if (res->cpu->quota != INVALID_INT) { - if (trans_conf_int64(conf, "lxc.cgroup.cpu.cfs_quota_us", res->cpu->quota) < 0) { - goto out; - } - } - if (res->cpu->period != INVALID_INT) { - if (trans_conf_uint64(conf, "lxc.cgroup.cpu.cfs_period_us", res->cpu->period) < 0) { - goto out; - } - } - ret = 0; -out: - return ret; -} - -/* trans resources cpu rt */ -static int trans_resources_cpu_rt(const oci_runtime_config_linux_resources *res, struct lcr_list *conf) -{ - int ret = -1; - - if (res->cpu->realtime_runtime != INVALID_INT) { - if (trans_conf_int64(conf, "lxc.cgroup.cpu.rt_runtime_us", res->cpu->realtime_runtime) < 0) { - goto out; - } - } - if (res->cpu->realtime_period != INVALID_INT) { - if (trans_conf_uint64(conf, "lxc.cgroup.cpu.rt_period_us", res->cpu->realtime_period) < 0) { - goto out; - } - } - ret = 0; -out: - return ret; -} - -/* trans resources cpu set */ -static int trans_resources_cpu_set(const oci_runtime_config_linux_resources *res, struct lcr_list *conf) -{ - struct lcr_list *node = NULL; - int ret = -1; - - if (res->cpu->cpus != NULL) { - node = create_lcr_list_node("lxc.cgroup.cpuset.cpus", res->cpu->cpus); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - if (res->cpu->mems != NULL) { - node = create_lcr_list_node("lxc.cgroup.cpuset.mems", res->cpu->mems); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - ret = 0; -out: - return ret; -} - -/* trans resources cpu shares */ -static int trans_resources_cpu_shares(const oci_runtime_config_linux_resources *res, struct lcr_list *conf) -{ - if (res->cpu->shares != INVALID_INT) { - int nret = trans_conf_int64(conf, "lxc.cgroup.cpu.shares", (int64_t)(res->cpu->shares)); - if (nret < 0) { - return -1; - } - } - return 0; -} - -/* trans resources cpu */ -static int trans_resources_cpu(const oci_runtime_config_linux_resources *res, struct lcr_list *conf) -{ - int ret = -1; - - if (res->cpu == NULL) { - return 0; - } - - if (trans_resources_cpu_cfs(res, conf)) { - goto out; - } - - if (trans_resources_cpu_rt(res, conf)) { - goto out; - } - - if (trans_resources_cpu_set(res, conf)) { - goto out; - } - - if (trans_resources_cpu_shares(res, conf)) { - goto out; - } - - ret = 0; - -out: - return ret; -} - -/* trans resources blkio weight */ -static int trans_blkio_weight(const oci_runtime_config_linux_resources_block_io *block_io, struct lcr_list *conf) -{ - int ret = -1; - - if (block_io->weight != INVALID_INT) { - if (trans_conf_int(conf, "lxc.cgroup.blkio.weight", block_io->weight) < 0) { - goto out; - } - } - if (block_io->leaf_weight != INVALID_INT) { - if (trans_conf_int(conf, "lxc.cgroup.blkio.leaf_weight", block_io->leaf_weight) < 0) { - goto out; - } - } - ret = 0; - -out: - return ret; -} - -/* trans resources blkio wdevice */ -static int trans_blkio_wdevice(const oci_runtime_config_linux_resources_block_io *block_io, struct lcr_list *conf) -{ - struct lcr_list *node = NULL; - int ret = -1; - size_t i = 0; - char buf_value[300] = { 0 }; - - for (i = 0; i < block_io->weight_device_len; i++) { - int nret; - oci_runtime_defs_linux_block_io_device_weight *wd = block_io->weight_device[i]; - if ((wd != NULL) && wd->weight != INVALID_INT) { - nret = snprintf(buf_value, sizeof(buf_value), "%lld:%lld %d", (long long)(wd->major), (long long)wd->minor, - wd->weight); - if (nret < 0 || (size_t)nret >= sizeof(buf_value)) { - goto out; - } - - node = create_lcr_list_node("lxc.cgroup.blkio.weight_device", buf_value); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - if ((wd != NULL) && wd->leaf_weight != INVALID_INT) { - nret = snprintf(buf_value, sizeof(buf_value), "%lld:%lld %d", (long long)(wd->major), - (long long)(wd->minor), wd->leaf_weight); - if (nret < 0 || (size_t)nret >= sizeof(buf_value)) { - goto out; - } - - node = create_lcr_list_node("lxc.cgroup.blkio.leaf_weight_device", buf_value); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - } - ret = 0; -out: - return ret; -} - -/* trans resources blkio throttle */ -static int trans_blkio_throttle(oci_runtime_defs_linux_block_io_device_throttle **throttle, size_t len, - const char *lxc_key, struct lcr_list *conf) -{ - struct lcr_list *node = NULL; - int ret = -1; - size_t i; - - if ((throttle == NULL) || len == 0) { - return 0; - } - - for (i = 0; i < len; i++) { - if (throttle[i] && throttle[i]->rate != INVALID_INT) { - int nret; - char buf_value[300] = { 0x00 }; - nret = snprintf(buf_value, sizeof(buf_value), "%lld:%lld %llu", (long long)throttle[i]->major, - (long long)(throttle[i]->minor), (unsigned long long)(throttle[i]->rate)); - if (nret < 0 || (size_t)nret >= sizeof(buf_value)) { - goto out; - } - - node = create_lcr_list_node(lxc_key, buf_value); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - } - ret = 0; -out: - return ret; -} - -/* trans resources blkio */ -static int trans_resources_blkio(const oci_runtime_config_linux_resources_block_io *block_io, struct lcr_list *conf) -{ - int ret = -1; - - if (block_io == NULL) { - return 0; - } - - if (trans_blkio_weight(block_io, conf)) { - goto out; - } - - if (trans_blkio_wdevice(block_io, conf)) { - goto out; - } - - if (trans_blkio_throttle(block_io->throttle_read_bps_device, block_io->throttle_read_bps_device_len, - "lxc.cgroup.blkio.throttle.read_bps_device", conf)) { - goto out; - } - - if (trans_blkio_throttle(block_io->throttle_write_bps_device, block_io->throttle_write_bps_device_len, - "lxc.cgroup.blkio.throttle.write_bps_device", conf)) { - goto out; - } - - if (trans_blkio_throttle(block_io->throttle_read_iops_device, block_io->throttle_read_iops_device_len, - "lxc.cgroup.blkio.throttle.read_iops_device", conf)) { - goto out; - } - - if (trans_blkio_throttle(block_io->throttle_write_iops_device, block_io->throttle_write_iops_device_len, - "lxc.cgroup.blkio.throttle.write_iops_device", conf)) { - goto out; - } - - ret = 0; -out: - return ret; -} - -/* trans resources hugetlb */ -static int trans_resources_hugetlb(const oci_runtime_config_linux_resources *res, struct lcr_list *conf) -{ - int ret = -1; - size_t i = 0; - char buf_key[300] = { 0 }; - - for (i = 0; i < res->hugepage_limits_len; i++) { - oci_runtime_config_linux_resources_hugepage_limits_element *lrhl = res->hugepage_limits[i]; - if (lrhl->page_size != NULL) { - int nret = snprintf(buf_key, sizeof(buf_key), "lxc.cgroup.hugetlb.%s.limit_in_bytes", lrhl->page_size); - if (nret < 0 || (size_t)nret >= sizeof(buf_key)) { - goto out; - } - - if (trans_conf_uint64(conf, buf_key, lrhl->limit) < 0) { - return -1; - } - } - } - - ret = 0; -out: - return ret; -} - -/* trans resources network */ -static int trans_resources_network(const oci_runtime_config_linux_resources *res, struct lcr_list *conf) -{ - int ret = -1; - size_t i = 0; - char buf_value[300] = { 0 }; - - if (!res->network) { - return 0; - } - - if (res->network->class_id != INVALID_INT) { - if (trans_conf_uint32(conf, "lxc.cgroup.net_cls.classid", res->network->class_id) < 0) { - return -1; - } - } - - for (i = 0; i < res->network->priorities_len; i++) { - oci_runtime_defs_linux_network_interface_priority *lrnp = res->network->priorities[i]; - if ((lrnp != NULL) && lrnp->name != NULL && lrnp->priority != INVALID_INT) { - int nret = snprintf(buf_value, sizeof(buf_value), "%s %u", lrnp->name, lrnp->priority); - if (nret < 0 || (size_t)nret >= sizeof(buf_value)) { - goto out; - } - - struct lcr_list *node = create_lcr_list_node("lxc.cgroup.net_prio.ifpriomap", buf_value); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - } - - ret = 0; -out: - return ret; -} - -/* trans resources pids */ -static int trans_resources_pids(const oci_runtime_config_linux_resources *res, struct lcr_list *conf) -{ - int ret = -1; - char buf_value[300] = { 0 }; - - if (res->pids == NULL) { - return 0; - } - - if (res->pids->limit != INVALID_INT) { - int nret; - if (res->pids->limit == -1) { - nret = snprintf(buf_value, sizeof(buf_value), "max"); - } else { - nret = snprintf(buf_value, sizeof(buf_value), "%lld", (long long)(res->pids->limit)); - } - if (nret < 0 || (size_t)nret >= sizeof(buf_value)) { - goto out; - } - - struct lcr_list *node = create_lcr_list_node("lxc.cgroup.pids.max", buf_value); - if (node == NULL) { - goto out; - } - lcr_list_add_tail(conf, node); - } - - ret = 0; -out: - return ret; -} - -/* trans oci resources */ -static struct lcr_list *trans_oci_resources(const oci_runtime_config_linux_resources *res) -{ - struct lcr_list *conf = NULL; - - conf = lcr_util_common_calloc_s(sizeof(*conf)); - if (conf == NULL) { - return NULL; - } - lcr_list_init(conf); - - if (trans_resources_devices(res, conf)) { - goto out_free; - } - - if (trans_resources_memory(res, conf)) { - goto out_free; - } - - if (trans_resources_cpu(res, conf)) { - goto out_free; - } - - if (trans_resources_blkio(res->block_io, conf)) { - goto out_free; - } - - if (trans_resources_hugetlb(res, conf)) { - goto out_free; - } - - if (trans_resources_network(res, conf)) { - goto out_free; - } - - if (trans_resources_pids(res, conf)) { - goto out_free; - } - - return conf; - -out_free: - lcr_free_config(conf); - free(conf); - - return NULL; -} - -struct namespace_map_def { - char *ns_name; - char *lxc_name; -}; - -static char *trans_oci_namespace_to_lxc(const char *typ) -{ - struct namespace_map_def namespaces_map[] = { - { "pid", "lxc.namespace.share.pid" }, { "network", "lxc.namespace.share.net" }, - { "ipc", "lxc.namespace.share.ipc" }, { "uts", "lxc.namespace.share.uts" }, - { "mount", "lxc.namespace.share.mnt" }, { "user", "lxc.namespace.share.user" }, - { "cgroup", "lxc.namespace.share.cgroup" }, { NULL, NULL } - }; - const struct namespace_map_def *p = NULL; - - for (p = namespaces_map; p != NULL && p->ns_name != NULL; p++) { - if (strcmp(typ, p->ns_name) == 0) { - return lcr_util_strdup_s(p->lxc_name); - } - } - return NULL; -} - -/* trans oci namespaces */ -static struct lcr_list *trans_oci_namespaces(const oci_runtime_config_linux *l) -{ - struct lcr_list *conf = NULL; - struct lcr_list *node = NULL; - size_t i; - oci_runtime_defs_linux_namespace_reference *ns = NULL; - - conf = lcr_util_common_calloc_s(sizeof(*conf)); - if (conf == NULL) { - return NULL; - } - lcr_list_init(conf); - - for (i = 0; i < l->namespaces_len; i++) { - char *ns_name = NULL; - ns = l->namespaces[i]; - - if (ns->type == NULL || ns->path == NULL) { - continue; - } - - ns_name = trans_oci_namespace_to_lxc(ns->type); - if (ns_name == NULL) { - continue; - } - - node = create_lcr_list_node(ns_name, ns->path); - free(ns_name); - if (node == NULL) { - goto out_free; - } - lcr_list_add_tail(conf, node); - } - - return conf; - -out_free: - lcr_free_config(conf); - free(conf); - - return NULL; -} - -/* trans oci mask ro paths */ -static struct lcr_list *trans_oci_mask_ro_paths(const oci_runtime_config_linux *l) -{ - struct lcr_list *conf = NULL; - struct lcr_list *node = NULL; - size_t i; - char *path = NULL; - - conf = lcr_util_common_calloc_s(sizeof(*conf)); - if (conf == NULL) { - return NULL; - } - lcr_list_init(conf); - - for (i = 0; i < l->masked_paths_len; i++) { - path = l->masked_paths[i]; - if (path == NULL) { - continue; - } - node = create_lcr_list_node("lxc.isulad.rootfs.maskedpaths", path); - if (node == NULL) { - goto out_free; - } - lcr_list_add_tail(conf, node); - } - - for (i = 0; i < l->readonly_paths_len; i++) { - path = l->readonly_paths[i]; - if (path == NULL) { - continue; - } - node = create_lcr_list_node("lxc.isulad.rootfs.ropaths", path); - if (node == NULL) { - goto out_free; - } - lcr_list_add_tail(conf, node); - } - - return conf; - -out_free: - lcr_free_config(conf); - free(conf); - - return NULL; -} - -#define POPULATE_DEVICE_SIZE (300 + PATH_MAX) -/* trans oci linux devices */ -static struct lcr_list *trans_oci_linux_devices(const oci_runtime_config_linux *l) -{ - struct lcr_list *conf = NULL; - struct lcr_list *node = NULL; - size_t i = 0; - int nret = 0; - oci_runtime_defs_linux_device *device = NULL; - char buf_value[POPULATE_DEVICE_SIZE] = { 0 }; - - conf = lcr_util_common_calloc_s(sizeof(*conf)); - if (conf == NULL) { - return NULL; - } - lcr_list_init(conf); - - for (i = 0; i < l->devices_len; i++) { - device = l->devices[i]; - - if (device->type == NULL || device->path == NULL) { - continue; - } - - /* lxc.populate_device = PATH_IN_CONTAINER:DEVICETYPE:MAJOR:MINOR:MODE:UID:GID - * For e.g. lxc.populate_device = /dev/sda:b:8:0:0666:0:0 - */ - nret = snprintf(buf_value, sizeof(buf_value), "%s:%s:%lld:%lld:%d:%u:%u", device->path, device->type, - (long long int)(device->major), (long long int)(device->minor), device->file_mode, device->uid, - device->gid); - if (nret < 0 || (size_t)nret >= sizeof(buf_value)) { - ERROR("Failed to get populate device string"); - goto out_free; - } - - node = create_lcr_list_node("lxc.isulad.populate.device", buf_value); - if (node == NULL) { - goto out_free; - } - lcr_list_add_tail(conf, node); - } - - return conf; - -out_free: - lcr_free_config(conf); - free(conf); - - return NULL; -} - -static inline bool is_seccomp_action_kill(const char *value) -{ - return strcmp(value, "SCMP_ACT_KILL") == 0; -} - -static inline bool is_seccomp_action_trap(const char *value) -{ - return strcmp(value, "SCMP_ACT_TRAP") == 0; -} - -static inline bool is_seccomp_action_allow(const char *value) -{ - return strcmp(value, "SCMP_ACT_ALLOW") == 0; -} - -static inline bool is_seccomp_action_trace(const char *value) -{ - return strcmp(value, "SCMP_ACT_TRACE") == 0; -} - -static inline bool is_seccomp_action_errno(const char *value) -{ - return strcmp(value, "SCMP_ACT_ERRNO") == 0; -} - -/* seccomp trans action */ -static char *seccomp_trans_action(const char *action) -{ - if (is_seccomp_action_kill(action)) { - return lcr_util_strdup_s("kill"); - } else if (is_seccomp_action_trap(action)) { - return lcr_util_strdup_s("trap"); - } else if (is_seccomp_action_allow(action)) { - return lcr_util_strdup_s("allow"); - } else if (is_seccomp_action_trace(action)) { - return lcr_util_strdup_s("trace 1"); - } else if (is_seccomp_action_errno(action)) { - return lcr_util_strdup_s("errno 1"); - } - - return NULL; -} - -static bool is_action_allow(const char *value) -{ - return strcmp(value, "allow") == 0; -} - -#define DEFAULT_ACTION_OFFSET 12 -/* seccomp append head info */ -static int seccomp_append_head_info(const char *action, Buffer *buffer) -{ - int ret = 0; - char *default_action = NULL; - - if (action == NULL) { - return -1; - } - - default_action = seccomp_trans_action(action); - if (default_action == NULL) { - ERROR("Failed to translate seccomp action"); - return -1; - } - - if (is_action_allow(default_action)) { - ret = buffer_nappendf(buffer, strlen(default_action) + DEFAULT_ACTION_OFFSET, "blacklist %s\n", default_action); - } else { - ret = buffer_nappendf(buffer, strlen(default_action) + DEFAULT_ACTION_OFFSET, "whitelist %s\n", default_action); - } - if (ret != 0) { - ERROR("Failed to append seccomp config head info\n"); - ret = -1; - goto out; - } - -out: - free(default_action); - return ret; -} - -/* get hostarch */ -static char *get_hostarch(void) -{ - struct utsname uts; - size_t len; - size_t i; - /* no x32 kernels */ - lcr_host_arch arch_type[] = { - { "i686", "[x86]", 4 }, { "x32", "[x32]", 3 }, { "x86_64", "[x86_64]", 6 }, - { "armv7", "[arm]", 5 }, { "aarch64", "[arm64]", 7 }, { "ppc64le", "[ppc64le]", 7 }, - { "ppc64", "[ppc64]", 5 }, { "ppc", "[ppc]", 3 }, { "mips64n32", "[mips64n32]", 9 }, - { "mips64", "[mips64]", 6 }, { "mips", "[mips]", 4 }, { "s390x", "[s390x]", 5 }, - { "s390", "[s390]", 4 }, { "parisc64", "[parisc64]", 8 }, { "parisc", "[parisc]", 6 }, - }; - - if (uname(&uts) < 0) { - SYSERROR("Failed to read host arch"); - return NULL; - } - len = sizeof(arch_type) / sizeof(lcr_host_arch); - for (i = 0; i < len; i++) { - if (i == 0 || i == 1 || i == 2) { - if (strcmp(uts.machine, arch_type[i].arch) == 0) { - return lcr_util_strdup_s(arch_type[i].value); - } - } else { - if (strncmp(uts.machine, arch_type[i].arch, (size_t)(arch_type[i].num)) == 0) { - return lcr_util_strdup_s(arch_type[i].value); - } - } - } - - ERROR("Failed to get machine type"); - return NULL; -} - -/* seccomp trans arch */ -static char *seccomp_trans_arch(const char *arch) -{ - lcr_arch_value arch_type[] = { - { "SCMP_ARCH_X86", "[x86]" }, - { "SCMP_ARCH_X86_64", "[x86_64]" }, - { "SCMP_ARCH_X32", "[x32]" }, - { "SCMP_ARCH_ARM", "[arm]" }, - { "SCMP_ARCH_AARCH64", "[arm64]" }, - { "SCMP_ARCH_MIPS", "[mips]" }, - { "SCMP_ARCH_MIPS64", "[mips64]" }, - { "SCMP_ARCH_MIPS64N32", "[mips64n32]" }, - { "SCMP_ARCH_MIPSEL", "[mipsel]" }, - { "SCMP_ARCH_MIPSEL64", "[mipsel64]" }, - { "SCMP_ARCH_MIPSEL64N32", "[mipsel64n32]" }, - { "SCMP_ARCH_PPC", "[ppc]" }, - { "SCMP_ARCH_PPC64", "[ppc64]" }, - { "SCMP_ARCH_PPC64LE", "[ppc64le]" }, - { "SCMP_ARCH_S390", "[s390]" }, - { "SCMP_ARCH_S390X", "[s390x]" }, - { "SCMP_ARCH_PARISC", "[parisc]" }, - { "SCMP_ARCH_PARISC64", "[parisc64]" }, - { "SCMP_ARCH_ALL", "[all]" }, - { "SCMP_ARCH_AUTO", "" }, - }; - size_t len; - size_t i = 0; - len = sizeof(arch_type) / sizeof(lcr_arch_value); - for (i = 0; i < len; i++) { - if (strcmp(arch_type[i].arch, "SCMP_ARCH_AUTO") == 0) { - return get_hostarch(); - } else if (strcmp(arch, arch_type[i].arch) == 0) { - return lcr_util_strdup_s(arch_type[i].value); - } - } - return NULL; -} - -/* seccomp append arch */ -static int seccomp_append_arch(char *arch, Buffer *buffer) -{ - int ret = 0; - char *trans_arch = NULL; - - if (arch == NULL) { - return -1; - } - - trans_arch = seccomp_trans_arch(arch); - if (trans_arch == NULL) { - ERROR("Failed to translate seccomp arch: %s", arch); - return -1; - } - - if (buffer_nappendf(buffer, strlen(trans_arch) + 2, "%s\n", trans_arch)) { - ERROR("Failed to append seccomp config head info\n"); - ret = -1; - } - - free(trans_arch); - return ret; -} - -/* seccomp append rule */ -static int seccomp_append_rule(const oci_runtime_defs_linux_syscall *syscall, size_t i, Buffer *buffer, char *action) -{ - int ret = 0; - size_t j = 0; - - if (syscall->names[i] == NULL) { - ERROR("Failed to get syscall name"); - ret = -1; - goto out; - } - if (buffer_nappendf(buffer, strlen(syscall->names[i]) + strlen(action) + 2, "%s %s", syscall->names[i], action)) { - ERROR("Failed to append syscall name and action\n"); - ret = -1; - goto out; - } - - for (j = 0; j < syscall->args_len; j++) { - if ((syscall->args[j] == NULL) || (syscall->args[j]->op == NULL)) { - ERROR("Failed to get syscall args"); - ret = -1; - goto out; - } - if (buffer_nappendf(buffer, 20 * 3 + strlen(syscall->args[j]->op), " [%u,%llu,%s,%llu]", - syscall->args[j]->index, syscall->args[j]->value, syscall->args[j]->op, - syscall->args[j]->value_two)) { - ERROR("Failed to append syscall rules\n"); - ret = -1; - goto out; - } - } - - if (buffer_nappendf(buffer, 2, "\n")) { - ERROR("Failed to append newline\n"); - ret = -1; - goto out; - } -out: - return ret; -} - -/* seccomp append rules */ -static int seccomp_append_rules(const oci_runtime_defs_linux_syscall *syscall, Buffer *buffer) -{ - int ret = 0; - size_t i = 0; - char *action = NULL; - - if (syscall == NULL) { - return -1; - } - - if ((syscall->action == NULL) || syscall->names_len == 0) { - return -1; - } - - action = seccomp_trans_action(syscall->action); - if (action == NULL) { - ERROR("Failed to translate action"); - ret = -1; - goto out; - } - - for (i = 0; i < syscall->names_len; i++) { - if (seccomp_append_rule(syscall, i, buffer, action)) { - ret = -1; - goto out; - } - } -out: - free(action); - return ret; -} - -static struct lcr_list *trans_oci_linux_sysctl(const json_map_string_string *sysctl) -{ - struct lcr_list *conf = NULL; - struct lcr_list *node = NULL; - size_t i; - - conf = lcr_util_common_calloc_s(sizeof(*conf)); - if (conf == NULL) { - return NULL; - } - lcr_list_init(conf); - - for (i = 0; i < sysctl->len; i++) { - char sysk[BUFSIZ] = { 0 }; - int nret = snprintf(sysk, sizeof(sysk), "lxc.sysctl.%s", sysctl->keys[i]); - if (nret < 0 || (size_t)nret >= sizeof(sysk)) { - ERROR("Failed to print string"); - goto out_free; - } - node = create_lcr_list_node(sysk, sysctl->values[i]); - if (node == NULL) { - goto out_free; - } - lcr_list_add_tail(conf, node); - } - - return conf; - -out_free: - lcr_free_config(conf); - free(conf); - return NULL; -} - -static int append_seccomp_with_archs(const oci_runtime_config_linux_seccomp *seccomp, Buffer *buffer) -{ - int ret = 0; - size_t i = 0; - size_t j = 0; - - for (i = 0; i < seccomp->architectures_len; i++) { - if (seccomp_append_arch(seccomp->architectures[i], buffer)) { - ret = -1; - goto out; - } - /* append rules */ - for (j = 0; j < seccomp->syscalls_len; j++) { - if (seccomp_append_rules(seccomp->syscalls[j], buffer)) { - ret = -1; - goto out; - } - } - } -out: - return ret; -} - -/* lxc seccomp conf format: - To support limit syscall arguments, extend the version 2 file to the following format: - - syscall_name action [index,value,op,valueTwo] [index,value,op]... - for one arguments, [index,value,valueTwo,op] - - index: the index for syscall arguments (type uint) - - value: the value for syscall arguments (type uint64) - - op: the operator for syscall arguments(string), a valid list of constants as of libseccomp v2.3.2 is - SCMP_CMP_NE,SCMP_CMP_LE,SCMP_CMP_LE, SCMP_CMP_EQ, SCMP_CMP_GE, - SCMP_CMP_GT, SCMP_CMP_MASKED_EQ, or !=,<=,==,>=,>,&= - - valueTwo: the value for syscall arguments only used for mask eq (type uint64, optional) - -For example: - - 2 - blacklist allow - reject_force_umount # comment this to allow umount -f; not recommended - [all] - kexec_load errno 1 [0,1,SCMP_CMP_LE][3,1,==][5,1,SCMP_CMP_MASKED_EQ,1] - open_by_handle_at errno 1 - init_module errno 1 - finit_module errno 1 - delete_module errno 1 - -*/ -static int trans_oci_seccomp(const oci_runtime_config_linux_seccomp *seccomp, char **seccomp_conf) -{ - int ret = 0; - size_t j = 0; - size_t init_size = 4 * SIZE_KB; - - Buffer *buffer = buffer_alloc(init_size); - if (buffer == NULL) { - ERROR("Failed to malloc output_buffer\n"); - return -1; - } - - /* config version */ - if (buffer_nappendf(buffer, 3, "2\n")) { - ERROR("Failed to append seccomp config version\n"); - ret = -1; - goto out_free; - } - - /* append head info */ - if (seccomp_append_head_info(seccomp->default_action, buffer)) { - ret = -1; - goto out_free; - } - - /* append architectures */ - if (seccomp->architectures_len != 0) { - ret = append_seccomp_with_archs(seccomp, buffer); - if (ret != 0) { - goto out_free; - } - } else { - // add rules directly(eg: blacklist) - for (j = 0; j < seccomp->syscalls_len; j++) { - if (seccomp_append_rules(seccomp->syscalls[j], buffer)) { - ret = -1; - goto out_free; - } - } - } - *seccomp_conf = buffer_to_s(buffer); - if (*seccomp_conf == NULL) { - ret = -1; - goto out_free; - } - -out_free: - buffer_free(buffer); - return ret; -} - -/* trans oci linux */ -struct lcr_list *trans_oci_linux(const oci_runtime_config_linux *l, char **seccomp_conf) -{ - int ret = 0; - struct lcr_list *tmp = NULL; - - struct lcr_list *conf = lcr_util_common_calloc_s(sizeof(*conf)); - if (conf == NULL) { - return NULL; - } - lcr_list_init(conf); - - // UID/GID Mapping - tmp = trans_oci_id_mapping(l); - if (tmp == NULL) { - goto out_free; - } - lcr_list_merge(conf, tmp); - - // Resources - if (l->resources != NULL) { - tmp = trans_oci_resources(l->resources); - if (tmp == NULL) { - goto out_free; - } - lcr_list_merge(conf, tmp); - } - - // linux devices - tmp = trans_oci_linux_devices(l); - if (tmp == NULL) { - goto out_free; - } - lcr_list_merge(conf, tmp); - - // Namespaces - tmp = trans_oci_namespaces(l); - if (tmp == NULL) { - goto out_free; - } - lcr_list_merge(conf, tmp); - - // MaskedPaths and ReadonlyPaths - tmp = trans_oci_mask_ro_paths(l); - if (tmp == NULL) { - goto out_free; - } - lcr_list_merge(conf, tmp); - - // sysctl - if (l->sysctl != NULL && l->uid_mappings == NULL && l->gid_mappings == NULL) { - tmp = trans_oci_linux_sysctl(l->sysctl); - if (tmp == NULL) { - goto out_free; - } - lcr_list_merge(conf, tmp); - } - - // seccomp - if (l->seccomp != NULL && seccomp_conf != NULL) { - ret = trans_oci_seccomp(l->seccomp, seccomp_conf); - if (ret) { - goto out_free; - } - } - - return conf; -out_free: - lcr_free_config(conf); - free(conf); - - return NULL; -} - -/* trans annotations */ -struct lcr_list *trans_annotations(const json_map_string_string *anno) -{ - size_t i, j; - size_t len; - int ret = 0; - - struct lcr_list *conf = lcr_util_common_calloc_s(sizeof(*conf)); - if (conf == NULL) { - return NULL; - } - lcr_list_init(conf); - - len = sizeof(g_require_annotations) / sizeof(lcr_annotation_item_t); - - // trans annotations - for (i = 0; i < anno->len; i++) { - if (anno->keys[i] == NULL) { - continue; - } - for (j = 0; j < len; j++) { - if (strcmp(anno->keys[i], g_require_annotations[j].name) != 0) { - continue; - } - - ret = g_require_annotations[j].checker(anno->values[i]); - if (ret == -1) { - ERROR("item: %s, value: %s, checker failed", anno->keys[i], anno->values[i]); - goto out_free; - } else if (ret == 1) { - DEBUG("Skip this config item: %s", anno->keys[i]); - continue; - } - - struct lcr_list *node = create_lcr_list_node(g_require_annotations[j].lxc_item_name, anno->values[i]); - if (node == NULL) { - goto out_free; - } - lcr_list_add_tail(conf, node); - break; - } - } - - return conf; -out_free: - lcr_free_config(conf); - free(conf); - - return NULL; -} - -static int add_needed_pty_conf(struct lcr_list *conf) -{ - struct lcr_list *node = create_lcr_list_node("lxc.pty.max", "1024"); - if (node == NULL) { - return -1; - } - lcr_list_add_tail(conf, node); - - return 0; -} - -static int add_needed_net_conf(struct lcr_list *conf) -{ - struct lcr_list *node = create_lcr_list_node("lxc.net.0.type", "empty"); - if (node == NULL) { - return -1; - } - lcr_list_add_tail(conf, node); - - node = create_lcr_list_node("lxc.net.0.flags", "up"); - if (node == NULL) { - return -1; - } - lcr_list_add_tail(conf, node); - return 0; -} - -/* get needed lxc conf */ -struct lcr_list *get_needed_lxc_conf() -{ - struct lcr_list *conf = lcr_util_common_calloc_s(sizeof(*conf)); - if (conf == NULL) { - return NULL; - } - lcr_list_init(conf); - - if (add_needed_pty_conf(conf) < 0) { - goto out_free; - } - if (add_needed_net_conf(conf) < 0) { - goto out_free; - } - - return conf; -out_free: - lcr_free_config(conf); - free(conf); - return NULL; -} diff --git a/src/conf.h b/src/conf.h deleted file mode 100644 index c649f2f..0000000 --- a/src/conf.h +++ /dev/null @@ -1,113 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide container conf function - ******************************************************************************/ -#ifndef __LCR_CONF_H -#define __LCR_CONF_H - -#include "oci_runtime_spec.h" -#include "lcr_list.h" - -#define INVALID_INT 0 - -/* - * Store lcr configuration - */ -typedef struct { - char *name; - char *value; -} lcr_config_item_t; - -/* - * return value: - * 0 is valid item - * 1 will skip this - * -1 is invalid item - * */ -typedef int(*lcr_check_item_t)(const char *); -/* - * Store annotations configuration - * */ -typedef struct { - char *name; - char *lxc_item_name; - lcr_check_item_t checker; -} lcr_annotation_item_t; - -/* - * seccomp trans arch - * */ -typedef struct { - char *arch; - char *value; -} lcr_arch_value; - -/* - * get host arch - * */ -typedef struct { - char *arch; - char *value; - int num; -} lcr_host_arch; - -/* - * Create a lcr_list node, and initialize the elem to a lcr_config_item_t with - * key and value - */ -struct lcr_list *create_lcr_list_node(const char *key, const char *value); - -/* - * Free a lcr_list node - */ -void free_lcr_list_node(struct lcr_list *node); - -/* - * Translate oci hostname to lcr config - */ -struct lcr_list *trans_oci_hostname(const char *hostname); - -/* - * Translate oci process struct to lcr config - */ -struct lcr_list *trans_oci_process(const oci_runtime_spec_process *proc); - -/* - * Translate oci root struct to lcr config - */ -struct lcr_list *trans_oci_root(const oci_runtime_spec_root *root, const oci_runtime_config_linux *linux); -/* - * Translate oci mounts struct to lcr config - */ -struct lcr_list *trans_oci_mounts(const oci_runtime_spec *c); - -/* - * Translate oci linux struct to lcr config - */ -struct lcr_list *trans_oci_linux(const oci_runtime_config_linux *l, char **seccomp_conf); - -/* - * Translate oci annotations to lcr config - * This is not supported in standard oci runtime-spec - */ -struct lcr_list *trans_annotations(const json_map_string_string *anno); - -/* - * Get other lxc needed configurations - */ -struct lcr_list *get_needed_lxc_conf(); - - -bool is_system_container(const oci_runtime_spec *container); - -#endif /*__LCR_CONF_H*/ diff --git a/src/constants.h b/src/constants.h deleted file mode 100644 index 6818ce4..0000000 --- a/src/constants.h +++ /dev/null @@ -1,52 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide constant definition - ******************************************************************************/ - -#ifndef _LCR_CONSTANTS_H -#define _LCR_CONSTANTS_H - -/* mode of file and directory */ - -#define DEFAULT_SECURE_FILE_MODE 0640 - -#define DEFAULT_SECURE_DIRECTORY_MODE 0750 - -#define ROOTFS_MNT_DIRECTORY_MODE 0640 - -#define CONFIG_DIRECTORY_MODE 0750 - -#define CONFIG_FILE_MODE 0640 - -#define NETWORK_MOUNT_FILE_MODE 0644 - -#define ARCH_LOG_FILE_MODE 0440 - -#define WORKING_LOG_FILE_MODE 0640 - -#define LOG_DIRECTORY_MODE 0750 - -#define TEMP_DIRECTORY_MODE 0750 - -#define DEBUG_FILE_MODE 0640 - -#define DEBUG_DIRECTORY_MODE 0750 - -// Config file path -#define OCIHOOKSFILE "ocihooks.json" -#define OCICONFIGFILE "ociconfig.json" -#define LXCCONFIGFILE "config" - -#define PARAM_NUM 50 - -#endif diff --git a/src/error.c b/src/error.c deleted file mode 100644 index fa87b94..0000000 --- a/src/error.c +++ /dev/null @@ -1,117 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide container error definition - ******************************************************************************/ -#include "utils.h" -#include "error.h" -#include -#include - -// record the lcr error -__thread engine_error_t g_lcr_error = { - .errcode = LCR_SUCCESS, - .errmsg = NULL -}; - -#define LCR_ERRMSG_GEN(n, s) { LCR_##n, s }, -struct lcr_strerror_tab_t { - lcr_errno_t lcr_errno; - const char *errmsg; -}; -static const struct lcr_strerror_tab_t g_lcr_strerror_tab[] = { - LCR_ERRNO_MAP(LCR_ERRMSG_GEN) -}; -#undef LCR_ERRMSG_GEN - -const char *errno_to_error_message(lcr_errno_t err) -{ - if ((size_t)err >= sizeof(g_lcr_strerror_tab) / sizeof(g_lcr_strerror_tab[0])) { - return g_lcr_strerror_tab[LCR_ERR_UNKNOWN].errmsg; - } - return g_lcr_strerror_tab[err].errmsg; -} - -void clear_error_message(engine_error_t *error) -{ - if (error == NULL) { - return; - } - error->errcode = LCR_SUCCESS; - free(error->errmsg); - error->errmsg = NULL; -} - -void lcr_set_error_message(lcr_errno_t errcode, const char *format, ...) -{ - int ret = 0; - char errbuf[BUFSIZ + 1] = { 0 }; - - va_list argp; - va_start(argp, format); - - ret = vsprintf(errbuf, format, argp); - va_end(argp); - clear_error_message(&g_lcr_error); - if (ret < 0) { - g_lcr_error.errcode = LCR_ERR_FORMAT; - return; - } - g_lcr_error.errcode = errcode; - g_lcr_error.errmsg = lcr_util_strdup_s(errbuf); -} - -void lcr_try_set_error_message(lcr_errno_t errcode, const char *format, ...) -{ - int ret = 0; - char errbuf[BUFSIZ + 1] = { 0 }; - va_list argp; - - if (g_lcr_error.errmsg != NULL || g_lcr_error.errcode != LCR_SUCCESS) { - return; - } - va_start(argp, format); - ret = vsprintf(errbuf, format, argp); - va_end(argp); - clear_error_message(&g_lcr_error); - if (ret < 0) { - g_lcr_error.errcode = LCR_ERR_FORMAT; - return; - } - g_lcr_error.errcode = errcode; - g_lcr_error.errmsg = lcr_util_strdup_s(errbuf); -} - -void lcr_append_error_message(lcr_errno_t errcode, const char *format, ...) -{ - int ret = 0; - char errbuf[BUFSIZ + 1] = { 0 }; - char *result = NULL; - - va_list argp; - va_start(argp, format); - - ret = vsprintf(errbuf, format, argp); - va_end(argp); - if (ret < 0) { - g_lcr_error.errcode = LCR_ERR_FORMAT; - return; - } - g_lcr_error.errcode = errcode; - result = lcr_util_string_append(g_lcr_error.errmsg, errbuf); - if (result == NULL) { - g_lcr_error.errcode = LCR_ERR_MEMOUT; - return; - } - free(g_lcr_error.errmsg); - g_lcr_error.errmsg = result; -} diff --git a/src/error.h b/src/error.h deleted file mode 100644 index 89901a5..0000000 --- a/src/error.h +++ /dev/null @@ -1,68 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide container error definition - ******************************************************************************/ -#ifndef __LCR_ERROR_H -#define __LCR_ERROR_H - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct engine_error { - uint32_t errcode; - char *errmsg; -} engine_error_t; - -/* record the lcr error */ -extern __thread engine_error_t g_lcr_error; - -#define DEF_SUCCESS_STR "Success" -#define DEF_ERR_RUNTIME_STR "Runtime error" - -#define LCR_ERRNO_MAP(XX) \ - XX(SUCCESS, DEF_SUCCESS_STR) \ - \ - /* err in posix api call */ \ - XX(ERR_MEMOUT, "Out of memory") \ - XX(ERR_MEMSET, "Memory set error") \ - \ - /* err in other case or call function int thirdparty library */ \ - XX(ERR_FORMAT, "Error message is too long") \ - XX(ERR_INPUT, "Invalid input parameter") \ - XX(ERR_INTERNAL, "Server internal error") \ - \ - /* err in runtime module */ \ - XX(ERR_RUNTIME, DEF_ERR_RUNTIME_STR) \ - \ - /* err max */ \ - XX(ERR_UNKNOWN, "Unknown error") - -#define LCR_ERRNO_GEN(n, s) LCR_##n, -typedef enum { LCR_ERRNO_MAP(LCR_ERRNO_GEN) } lcr_errno_t; -#undef LCR_ERRNO_GEN - -const char *errno_to_error_message(lcr_errno_t err); - -void clear_error_message(engine_error_t *error); - -void lcr_set_error_message(lcr_errno_t errcode, const char *format, ...); - -void lcr_try_set_error_message(lcr_errno_t errcode, const char *format, ...); - -void lcr_append_error_message(lcr_errno_t errcode, const char *format, ...); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/json/CMakeLists.txt b/src/json/CMakeLists.txt deleted file mode 100644 index d3cd170..0000000 --- a/src/json/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -# generate .c and .h files for json -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/schema) diff --git a/src/json/oci_runtime_hooks.c b/src/json/oci_runtime_hooks.c deleted file mode 100644 index dcd3149..0000000 --- a/src/json/oci_runtime_hooks.c +++ /dev/null @@ -1,77 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: maoweiyong - * Create: 2018-11-08 - * Description: provide oci runtime hooks functions - ******************************************************************************/ - -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -#include "read_file.h" -#include "oci_runtime_hooks.h" -#include - -#define PARSE_ERR_BUFFER_SIZE 1024 - -char *oci_runtime_spec_hooks_generate_json(const oci_runtime_spec_hooks *ptr, const struct parser_context *ctx, - parser_error *err) -{ - yajl_gen g = NULL; - struct parser_context tmp_ctx = { 0 }; - const unsigned char *gen_buf = NULL; - char *json_buf = NULL; - size_t gen_len = 0; - - if (ptr == NULL || err == NULL) { - return NULL; - } - - *err = NULL; - if (ctx == NULL) { - ctx = &tmp_ctx; - } - - if (!json_gen_init(&g, ctx)) { - *err = strdup("Json_gen init failed"); - goto out; - } - if (yajl_gen_status_ok != gen_oci_runtime_spec_hooks(g, ptr, ctx, err)) { - if (*err == NULL) { - *err = strdup("Failed to generate json"); - } - goto free_out; - } - yajl_gen_get_buf(g, &gen_buf, &gen_len); - if (gen_buf == NULL) { - *err = strdup("Error to get generated json"); - goto free_out; - } - - if (gen_len > SIZE_MAX - 1) { - *err = strdup("Generated json too long"); - goto free_out; - } - - json_buf = malloc(gen_len + 1); - if (json_buf == NULL) { - *err = strdup("Out of memory"); - goto free_out; - } - (void)memcpy((void *)json_buf, (void *)gen_buf, gen_len); - json_buf[gen_len] = '\0'; - -free_out: - yajl_gen_clear(g); - yajl_gen_free(g); -out: - return json_buf; -} diff --git a/src/json/oci_runtime_hooks.h b/src/json/oci_runtime_hooks.h deleted file mode 100644 index 6b6d396..0000000 --- a/src/json/oci_runtime_hooks.h +++ /dev/null @@ -1,24 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: maoweiyong - * Create: 2018-11-08 - * Description: provide oci runtime hooks functions - ******************************************************************************/ - -#ifndef _CONTAINER_HOOKS_H -#define _CONTAINER_HOOKS_H - -#include "oci_runtime_spec.h" - -char *oci_runtime_spec_hooks_generate_json(const oci_runtime_spec_hooks *ptr, const struct parser_context *ctx, - parser_error *err); - -#endif diff --git a/src/json/schema/CMakeLists.txt b/src/json/schema/CMakeLists.txt deleted file mode 100644 index 48a4479..0000000 --- a/src/json/schema/CMakeLists.txt +++ /dev/null @@ -1,16 +0,0 @@ -project (JSONGenerator) - -set(cmdpath python3) -set(pysrcpath ${CMAKE_CURRENT_SOURCE_DIR}/src/generate.py) -set(schemapath ${CMAKE_CURRENT_SOURCE_DIR}/schema) -set(outputpath ${CMAKE_BINARY_DIR}/json) -add_subdirectory(src) - -message("-- Generate .c and .h file into: " ${outputpath}) - -execute_process(COMMAND ${cmdpath} ${pysrcpath} --gen-common --gen-ref -r --root=${schemapath} --out=${outputpath} ${schemapath} - ERROR_VARIABLE err - ) -if (err) - message("error: " ${err}) -endif() diff --git a/src/json/schema/schema/defs.json b/src/json/schema/schema/defs.json deleted file mode 100644 index c8739d1..0000000 --- a/src/json/schema/schema/defs.json +++ /dev/null @@ -1,233 +0,0 @@ -{ - " description": "Definitions used throughout the OpenContainer Specification", - "definitions": { - "int8": { - "type": "integer", - "minimum": -128, - "maximum": 127 - }, - "int16": { - "type": "integer", - "minimum": -32768, - "maximum": 32767 - }, - "int32": { - "type": "integer", - "minimum": -2147483648, - "maximum": 2147483647 - }, - "int64": { - "type": "integer", - "minimum": -9223372036854776000, - "maximum": 9223372036854776000 - }, - "uint8": { - "type": "integer", - "minimum": 0, - "maximum": 255 - }, - "uint16": { - "type": "integer", - "minimum": 0, - "maximum": 65535 - }, - "uint32": { - "type": "integer", - "minimum": 0, - "maximum": 4294967295 - }, - "uint64": { - "type": "integer", - "minimum": 0, - "maximum": 18446744073709552000 - }, - "uint16Pointer": { - "oneOf": [ - { - "$ref": "#/definitions/uint16" - }, - { - "type": "null" - } - ] - }, - "uint64Pointer": { - "oneOf": [ - { - "$ref": "#/definitions/uint64" - }, - { - "type": "null" - } - ] - }, - "stringPointer": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ] - }, - "percent": { - "type": "integer", - "minimum": 0, - "maximum": 100 - }, - "UID": { - "$ref": "#/definitions/uint32" - }, - "GID": { - "$ref": "#/definitions/uint32" - }, - "ArrayOfGIDs": { - "type": "array", - "items": { - "$ref": "#/definitions/GID" - } - }, - "FilePath": { - "type": "string" - }, - "Env": { - "$ref": "#/definitions/ArrayOfStrings" - }, - "Hook": { - "type": "object", - "properties": { - "path": { - "$ref": "#/definitions/FilePath" - }, - "args": { - "$ref": "#/definitions/ArrayOfStrings" - }, - "env": { - "$ref": "#/definitions/Env" - }, - "timeout": { - "type": "integer", - "minimum": 1 - } - }, - "required": [ - "path" - ] - }, - "ArrayOfHooks": { - "type": "array", - "items": { - "$ref": "#/definitions/Hook" - } - }, - "IDMapping": { - "type": "object", - "properties": { - "hostID": { - "$ref": "#/definitions/uint32" - }, - "containerID": { - "$ref": "#/definitions/uint32" - }, - "size": { - "$ref": "#/definitions/uint32" - } - }, - "required": [ - "hostID", - "containerID", - "size" - ] - }, - "Mount": { - "type": "object", - "properties": { - "source": { - "$ref": "#/definitions/FilePath" - }, - "destination": { - "$ref": "#/definitions/FilePath" - }, - "options": { - "$ref": "#/definitions/ArrayOfStrings" - }, - "type": { - "type": "string" - } - }, - "required": [ - "destination" - ] - }, - "ArrayOfStrings": { - "type": "array", - "items": { - "type": "string" - } - }, - "mapStringString": { - "type": "object", - "patternProperties": { - ".{1,}": { - "type": "string" - } - } - }, - "mapStringInt": { - "type": "object", - "patternProperties": { - ".{1,}": { - "type": "integer" - } - } - }, - "mapStringBool": { - "type": "object", - "patternProperties": { - ".{1,}": { - "type": "boolean" - } - } - }, - "mapIntString": { - "type": "object", - "patternProperties": { - ".{2,}": { - "type": "string" - } - } - }, - "mapIntInt": { - "type": "object", - "patternProperties": { - ".{2,}": { - "type": "integer" - } - } - }, - "mapIntBool": { - "type": "object", - "patternProperties": { - ".{2,}": { - "type": "boolean" - } - } - }, - "mapStringObject": { - "type": "object", - "patternProperties": { - ".{1,}": { - "type": "object" - } - } - }, - "ociVersion": { - "description": "The version of Open Container Runtime Specification that the document complies with", - "type": "string" - }, - "annotations": { - "$ref": "#/definitions/mapStringString" - } - } -} diff --git a/src/json/schema/schema/oci/runtime/config-linux.json b/src/json/schema/schema/oci/runtime/config-linux.json deleted file mode 100644 index 70b05e0..0000000 --- a/src/json/schema/schema/oci/runtime/config-linux.json +++ /dev/null @@ -1,271 +0,0 @@ -{ - "linux": { - "description": "Linux platform-specific configurations", - "id": "https://opencontainers.org/schema/bundle/linux", - "type": "object", - "properties": { - "devices": { - "id": "https://opencontainers.org/schema/bundle/linux/devices", - "type": "array", - "items": { - "$ref": "defs-linux.json#/definitions/Device" - } - }, - "uidMappings": { - "id": "https://opencontainers.org/schema/bundle/linux/uidMappings", - "type": "array", - "items": { - "$ref": "../../defs.json#/definitions/IDMapping" - } - }, - "gidMappings": { - "id": "https://opencontainers.org/schema/bundle/linux/gidMappings", - "type": "array", - "items": { - "$ref": "../../defs.json#/definitions/IDMapping" - } - }, - "namespaces": { - "id": "https://opencontainers.org/schema/bundle/linux/namespaces", - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "defs-linux.json#/definitions/NamespaceReference" - } - ] - } - }, - "resources": { - "id": "https://opencontainers.org/schema/bundle/linux/resources", - "type": "object", - "properties": { - "devices": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/devices", - "type": "array", - "items": { - "$ref": "defs-linux.json#/definitions/DeviceCgroup" - } - }, - "pids": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/pids", - "type": "object", - "properties": { - "limit": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/pids/limit", - "$ref": "../../defs.json#/definitions/int64" - } - }, - "required": [ - "limit" - ] - }, - "blockIO": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/blockIO", - "type": "object", - "properties": { - "weight": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/blockIO/weight", - "$ref": "defs-linux.json#/definitions/weight" - }, - "leafWeight": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/blockIO/leafWeight", - "$ref": "defs-linux.json#/definitions/weight" - }, - "throttleReadBpsDevice": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/blockIO/throttleReadBpsDevice", - "type": "array", - "items": { - "$ref": "defs-linux.json#/definitions/blockIODeviceThrottle" - } - }, - "throttleWriteBpsDevice": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/blockIO/throttleWriteBpsDevice", - "type": "array", - "items": { - "$ref": "defs-linux.json#/definitions/blockIODeviceThrottle" - } - }, - "throttleReadIOPSDevice": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/blockIO/throttleReadIOPSDevice", - "type": "array", - "items": { - "$ref": "defs-linux.json#/definitions/blockIODeviceThrottle" - } - }, - "throttleWriteIOPSDevice": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/blockIO/throttleWriteIOPSDevice", - "type": "array", - "items": { - "$ref": "defs-linux.json#/definitions/blockIODeviceThrottle" - } - }, - "weightDevice": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/blockIO/weightDevice", - "type": "array", - "items": { - "$ref": "defs-linux.json#/definitions/blockIODeviceWeight" - } - } - } - }, - "cpu": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/cpu", - "type": "object", - "properties": { - "cpus": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/cpu/cpus", - "type": "string" - }, - "mems": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/cpu/mems", - "type": "string" - }, - "period": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/cpu/period", - "$ref": "../../defs.json#/definitions/uint64" - }, - "quota": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/cpu/quota", - "$ref": "../../defs.json#/definitions/int64" - }, - "realtimePeriod": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/cpu/realtimePeriod", - "$ref": "../../defs.json#/definitions/uint64" - }, - "realtimeRuntime": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/cpu/realtimeRuntime", - "$ref": "../../defs.json#/definitions/int64" - }, - "shares": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/cpu/shares", - "$ref": "../../defs.json#/definitions/uint64" - } - } - }, - "hugepageLimits": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/hugepageLimits", - "type": "array", - "items": { - "type": "object", - "properties": { - "pageSize": { - "type": "string" - }, - "limit": { - "$ref": "../../defs.json#/definitions/uint64" - } - }, - "required": [ - "pageSize", - "limit" - ] - } - }, - "memory": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/memory", - "type": "object", - "properties": { - "kernel": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/memory/kernel", - "$ref": "../../defs.json#/definitions/int64" - }, - "kernelTCP": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/memory/kernelTCP", - "$ref": "../../defs.json#/definitions/int64" - }, - "limit": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/memory/limit", - "$ref": "../../defs.json#/definitions/int64" - }, - "reservation": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/memory/reservation", - "$ref": "../../defs.json#/definitions/int64" - }, - "swap": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/memory/swap", - "$ref": "../../defs.json#/definitions/int64" - }, - "swappiness": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/memory/swappiness", - "$ref": "../../defs.json#/definitions/uint64" - }, - "disableOOMKiller": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/memory/disableOOMKiller", - "type": "boolean" - } - } - }, - "network": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/network", - "type": "object", - "properties": { - "classID": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/network/classId", - "$ref": "../../defs.json#/definitions/uint32" - }, - "priorities": { - "id": "https://opencontainers.org/schema/bundle/linux/resources/network/priorities", - "type": "array", - "items": { - "$ref": "defs-linux.json#/definitions/NetworkInterfacePriority" - } - } - } - } - } - }, - "cgroupsPath": { - "id": "https://opencontainers.org/schema/bundle/linux/cgroupsPath", - "type": "string" - }, - "rootfsPropagation": { - "id": "https://opencontainers.org/schema/bundle/linux/rootfsPropagation", - "$ref": "defs-linux.json#/definitions/RootfsPropagation" - }, - "seccomp": { - "id": "https://opencontainers.org/schema/bundle/linux/seccomp", - "type": "object", - "properties": { - "defaultAction": { - "id": "https://opencontainers.org/schema/bundle/linux/seccomp/defaultAction", - "type": "string" - }, - "architectures": { - "id": "https://opencontainers.org/schema/bundle/linux/seccomp/architectures", - "type": "array", - "items": { - "$ref": "defs-linux.json#/definitions/SeccompArch" - } - }, - "syscalls": { - "id": "https://opencontainers.org/schema/bundle/linux/seccomp/syscalls", - "type": "array", - "items": { - "$ref": "defs-linux.json#/definitions/Syscall" - } - } - }, - "required": [ - "defaultAction" - ] - }, - "sysctl": { - "id": "https://opencontainers.org/schema/bundle/linux/sysctl", - "$ref": "../../defs.json#/definitions/mapStringString" - }, - "maskedPaths": { - "id": "https://opencontainers.org/schema/bundle/linux/maskedPaths", - "$ref": "../../defs.json#/definitions/ArrayOfStrings" - }, - "readonlyPaths": { - "id": "https://opencontainers.org/schema/bundle/linux/readonlyPaths", - "$ref": "../../defs.json#/definitions/ArrayOfStrings" - }, - "mountLabel": { - "id": "https://opencontainers.org/schema/bundle/linux/mountLabel", - "type": "string" - } - } - } -} diff --git a/src/json/schema/schema/oci/runtime/defs-linux.json b/src/json/schema/schema/oci/runtime/defs-linux.json deleted file mode 100644 index ccbe3c7..0000000 --- a/src/json/schema/schema/oci/runtime/defs-linux.json +++ /dev/null @@ -1,270 +0,0 @@ -{ - "definitions": { - "RootfsPropagation": { - "type": "string", - "enum": [ - "private", - "shared", - "slave", - "unbindable" - ] - }, - "SeccompArch": { - "type": "string", - "enum": [ - "SCMP_ARCH_X86", - "SCMP_ARCH_X86_64", - "SCMP_ARCH_X32", - "SCMP_ARCH_ARM", - "SCMP_ARCH_AARCH64", - "SCMP_ARCH_MIPS", - "SCMP_ARCH_MIPS64", - "SCMP_ARCH_MIPS64N32", - "SCMP_ARCH_MIPSEL", - "SCMP_ARCH_MIPSEL64", - "SCMP_ARCH_MIPSEL64N32", - "SCMP_ARCH_PPC", - "SCMP_ARCH_PPC64", - "SCMP_ARCH_PPC64LE", - "SCMP_ARCH_S390", - "SCMP_ARCH_S390X", - "SCMP_ARCH_PARISC", - "SCMP_ARCH_PARISC64" - ] - }, - "SeccompAction": { - "type": "string", - "enum": [ - "SCMP_ACT_KILL", - "SCMP_ACT_TRAP", - "SCMP_ACT_ERRNO", - "SCMP_ACT_TRACE", - "SCMP_ACT_ALLOW" - ] - }, - "SeccompOperators": { - "type": "string", - "enum": [ - "SCMP_CMP_NE", - "SCMP_CMP_LT", - "SCMP_CMP_LE", - "SCMP_CMP_EQ", - "SCMP_CMP_GE", - "SCMP_CMP_GT", - "SCMP_CMP_MASKED_EQ" - ] - }, - "SyscallArg": { - "type": "object", - "properties": { - "index": { - "$ref": "../../defs.json#/definitions/uint32" - }, - "value": { - "$ref": "../../defs.json#/definitions/uint64" - }, - "valueTwo": { - "$ref": "../../defs.json#/definitions/uint64" - }, - "op": { - "$ref": "#/definitions/SeccompOperators" - } - }, - "required": [ - "index", - "value", - "op" - ] - }, - "Syscall": { - "type": "object", - "properties": { - "names": { - "type": "array", - "items": { - "type": "string" - }, - "minItems": 1 - }, - "action": { - "$ref": "#/definitions/SeccompAction" - }, - "args": { - "type": "array", - "items": { - "$ref": "#/definitions/SyscallArg" - } - } - }, - "required": [ - "names", - "action" - ] - }, - "Major": { - "description": "major device number", - "$ref": "../../defs.json#/definitions/int64" - }, - "Minor": { - "description": "minor device number", - "$ref": "../../defs.json#/definitions/int64" - }, - "FileMode": { - "description": "File permissions mode (typically an octal value)", - "type": "integer", - "minimum": 0, - "maximum": 512 - }, - "FileType": { - "description": "Type of a block or special character device", - "type": "string", - "pattern": "^[cbup]$" - }, - "Device": { - "type": "object", - "required": [ - "type", - "path" - ], - "properties": { - "type": { - "$ref": "#/definitions/FileType" - }, - "path": { - "$ref": "../../defs.json#/definitions/FilePath" - }, - "fileMode": { - "$ref": "#/definitions/FileMode" - }, - "major": { - "$ref": "#/definitions/Major" - }, - "minor": { - "$ref": "#/definitions/Minor" - }, - "uid": { - "$ref": "../../defs.json#/definitions/UID" - }, - "gid": { - "$ref": "../../defs.json#/definitions/GID" - } - } - }, - "weight": { - "type": "integer" - }, - "blockIODevice": { - "type": "object", - "properties": { - "major": { - "$ref": "#/definitions/Major" - }, - "minor": { - "$ref": "#/definitions/Minor" - } - }, - "required": [ - "major", - "minor" - ] - }, - "blockIODeviceWeight": { - "type": "object", - "allOf": [ - { - "$ref": "#/definitions/blockIODevice" - }, - { - "type": "object", - "properties": { - "weight": { - "$ref": "#/definitions/weight" - }, - "leafWeight": { - "$ref": "#/definitions/weight" - } - } - } - ] - }, - "blockIODeviceThrottle": { - "allOf": [ - { - "$ref": "#/definitions/blockIODevice" - }, - { - "type": "object", - "properties": { - "rate": { - "$ref": "../../defs.json#/definitions/uint64" - } - } - } - ] - }, - "DeviceCgroup": { - "type": "object", - "properties": { - "allow": { - "type": "boolean" - }, - "type": { - "type": "string" - }, - "major": { - "$ref": "#/definitions/Major" - }, - "minor": { - "$ref": "#/definitions/Minor" - }, - "access": { - "type": "string" - } - }, - "required": [ - "allow" - ] - }, - "NetworkInterfacePriority": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "priority": { - "$ref": "../../defs.json#/definitions/uint32" - } - }, - "required": [ - "name", - "priority" - ] - }, - "NamespaceType": { - "type": "string", - "enum": [ - "mount", - "pid", - "network", - "uts", - "ipc", - "user", - "cgroup" - ] - }, - "NamespaceReference": { - "type": "object", - "properties": { - "type": { - "$ref": "#/definitions/NamespaceType" - }, - "path": { - "$ref": "../../defs.json#/definitions/FilePath" - } - }, - "required": [ - "type" - ] - } - } -} diff --git a/src/json/schema/schema/oci/runtime/spec.json b/src/json/schema/schema/oci/runtime/spec.json deleted file mode 100644 index 61eacbd..0000000 --- a/src/json/schema/schema/oci/runtime/spec.json +++ /dev/null @@ -1,216 +0,0 @@ -{ - "description": "Open Container Runtime Specification Container Configuration Schema", - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "https://opencontainers.org/schema/bundle", - "type": "object", - "properties": { - "ociVersion": { - "id": "https://opencontainers.org/schema/bundle/ociVersion", - "$ref": "../../defs.json#/definitions/ociVersion" - }, - "hooks": { - "id": "https://opencontainers.org/schema/bundle/hooks", - "type": "object", - "properties": { - "prestart": { - "$ref": "../../defs.json#/definitions/ArrayOfHooks" - }, - "poststart": { - "$ref": "../../defs.json#/definitions/ArrayOfHooks" - }, - "poststop": { - "$ref": "../../defs.json#/definitions/ArrayOfHooks" - } - } - }, - "annotations": { - "$ref": "../../defs.json#/definitions/annotations" - }, - "hostname": { - "id": "https://opencontainers.org/schema/bundle/hostname", - "type": "string" - }, - "mounts": { - "id": "https://opencontainers.org/schema/bundle/mounts", - "type": "array", - "items": { - "$ref": "../../defs.json#/definitions/Mount" - } - }, - "root": { - "description": "Configures the container's root filesystem.", - "id": "https://opencontainers.org/schema/bundle/root", - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "id": "https://opencontainers.org/schema/bundle/root/path", - "$ref": "../../defs.json#/definitions/FilePath" - }, - "readonly": { - "id": "https://opencontainers.org/schema/bundle/root/readonly", - "type": "boolean" - } - } - }, - "process": { - "id": "https://opencontainers.org/schema/bundle/process", - "type": "object", - "required": [ - "cwd", - "args" - ], - "properties": { - "args": { - "id": "https://opencontainers.org/schema/bundle/process/args", - "$ref": "../../defs.json#/definitions/ArrayOfStrings" - }, - "consoleSize": { - "id": "https://opencontainers.org/schema/bundle/process/consoleSize", - "type": "object", - "required": [ - "height", - "width" - ], - "properties": { - "height": { - "id": "https://opencontainers.org/schema/bundle/process/consoleSize/height", - "$ref": "../../defs.json#/definitions/uint64" - }, - "width": { - "id": "https://opencontainers.org/schema/bundle/process/consoleSize/width", - "$ref": "../../defs.json#/definitions/uint64" - } - } - }, - "cwd": { - "id": "https://opencontainers.org/schema/bundle/process/cwd", - "type": "string" - }, - "env": { - "id": "https://opencontainers.org/schema/bundle/process/env", - "$ref": "../../defs.json#/definitions/Env" - }, - "terminal": { - "id": "https://opencontainers.org/schema/bundle/process/terminal", - "type": "boolean" - }, - "user": { - "id": "https://opencontainers.org/schema/bundle/process/user", - "type": "object", - "properties": { - "uid": { - "id": "https://opencontainers.org/schema/bundle/process/user/uid", - "$ref": "../../defs.json#/definitions/UID" - }, - "gid": { - "id": "https://opencontainers.org/schema/bundle/process/user/gid", - "$ref": "../../defs.json#/definitions/GID" - }, - "additionalGids": { - "id": "https://opencontainers.org/schema/bundle/process/user/additionalGids", - "$ref": "../../defs.json#/definitions/ArrayOfGIDs" - }, - "username": { - "id": "https://opencontainers.org/schema/bundle/process/user/username", - "type": "string" - } - } - }, - "capabilities": { - "id": "https://opencontainers.org/schema/bundle/process/linux/capabilities", - "type": "object", - "properties": { - "bounding": { - "id": "https://opencontainers.org/schema/bundle/process/linux/capabilities/bounding", - "type": "array", - "items": { - "type": "string" - } - }, - "permitted": { - "id": "https://opencontainers.org/schema/bundle/process/linux/capabilities/permitted", - "type": "array", - "items": { - "type": "string" - } - }, - "effective": { - "id": "https://opencontainers.org/schema/bundle/process/linux/capabilities/effective", - "type": "array", - "items": { - "type": "string" - } - }, - "inheritable": { - "id": "https://opencontainers.org/schema/bundle/process/linux/capabilities/inheritable", - "type": "array", - "items": { - "type": "string" - } - }, - "ambient": { - "id": "https://opencontainers.org/schema/bundle/process/linux/capabilities/ambient", - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "apparmorProfile": { - "id": "https://opencontainers.org/schema/bundle/process/linux/apparmorProfile", - "type": "string" - }, - "oomScoreAdj": { - "id": "https://opencontainers.org/schema/bundle/process/linux/oomScoreAdj", - "type": "integer" - }, - "selinuxLabel": { - "id": "https://opencontainers.org/schema/bundle/process/linux/selinuxLabel", - "type": "string" - }, - "noNewPrivileges": { - "id": "https://opencontainers.org/schema/bundle/process/linux/noNewPrivileges", - "type": "boolean" - }, - "rlimits": { - "id": "https://opencontainers.org/schema/bundle/linux/rlimits", - "type": "array", - "items": { - "id": "https://opencontainers.org/schema/bundle/linux/rlimits/0", - "type": "object", - "required": [ - "type", - "soft", - "hard" - ], - "properties": { - "hard": { - "id": "https://opencontainers.org/schema/bundle/linux/rlimits/0/hard", - "$ref": "../../defs.json#/definitions/uint64" - }, - "soft": { - "id": "https://opencontainers.org/schema/bundle/linux/rlimits/0/soft", - "$ref": "../../defs.json#/definitions/uint64" - }, - "type": { - "id": "https://opencontainers.org/schema/bundle/linux/rlimits/0/type", - "type": "string", - "pattern": "^RLIMIT_[A-Z]+$" - } - } - } - } - } - }, - "linux": { - "$ref": "config-linux.json#/linux" - } - }, - "required": [ - "ociVersion" - ] -} diff --git a/src/json/schema/schema/oci/runtime/state.json b/src/json/schema/schema/oci/runtime/state.json deleted file mode 100644 index 93b8160..0000000 --- a/src/json/schema/schema/oci/runtime/state.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "description": "Open Container Runtime State Schema", - "$schema": "http://json-schema.org/draft-04/schema#", - "id": "https://opencontainers.org/schema/state", - "type": "object", - "properties": { - "ociVersion": { - "id": "https://opencontainers.org/schema/runtime/state/ociVersion", - "$ref": "../../defs.json#/definitions/ociVersion" - }, - "id": { - "id": "https://opencontainers.org/schema/runtime/state/id", - "description": "the container's ID", - "type": "string" - }, - "status": { - "id": "https://opencontainers.org/schema/runtime/state/status", - "type": "string", - "enum": [ - "creating", - "created", - "running", - "stopped" - ] - }, - "pid": { - "id": "https://opencontainers.org/schema/runtime/state/pid", - "type": "integer", - "minimum": 0 - }, - "bundle": { - "id": "https://opencontainers.org/schema/runtime/state/bundle", - "type": "string" - }, - "annotations": { - "$ref": "../../defs.json#/definitions/annotations" - } - }, - "required": [ - "ociVersion", - "id", - "status", - "bundle" - ] -} diff --git a/src/json/schema/schema/start-generate-config.json b/src/json/schema/schema/start-generate-config.json deleted file mode 100644 index a7c470c..0000000 --- a/src/json/schema/schema/start-generate-config.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "type": "object", - "properties": { - "uid": { - "id": "https://opencontainers.org/schema/bundle/process/user/uid", - "$ref": "defs.json#/definitions/UID" - }, - "gid": { - "id": "https://opencontainers.org/schema/bundle/process/user/gid", - "$ref": "defs.json#/definitions/GID" - }, - "additionalGids": { - "id": "https://opencontainers.org/schema/bundle/process/user/additionalGids", - "$ref": "defs.json#/definitions/ArrayOfGIDs" - } - } -} diff --git a/src/json/schema/src/CMakeLists.txt b/src/json/schema/src/CMakeLists.txt deleted file mode 100644 index 8db178e..0000000 --- a/src/json/schema/src/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# get current directory sources files - -message("-- do nothing ") diff --git a/src/json/schema/src/common_c.py b/src/json/schema/src/common_c.py deleted file mode 100644 index 239440a..0000000 --- a/src/json/schema/src/common_c.py +++ /dev/null @@ -1,1185 +0,0 @@ -# -*- coding: utf-8 -*- -''' -Description: commom source file -Interface: None -History: 2019-06-17 -''' -# -# libocispec - a C library for parsing OCI spec files. -# -# Copyright (C) 2017, 2019 Giuseppe Scrivano -# Copyright (C) Huawei Technologies., Ltd. 2018-2019. All rights reserved. -# -# libocispec is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# libocispec 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with libocispec. If not, see . -# -# As a special exception, you may create a larger work that contains -# part or all of the libocispec parser skeleton and distribute that work -# under terms of your choice, so long as that work isn't itself a -# parser generator using the skeleton or a modified version thereof -# as a parser skeleton. Alternatively, if you modify or redistribute -# the parser skeleton itself, you may (at your option) remove this -# special exception, which will cause the skeleton and the resulting -# libocispec output files to be licensed under the GNU General Public -# License without this special exception. - -CODE = '''// Auto generated file. Do not edit! -# define _GNU_SOURCE -# include -# include -# include -# include "json_common.h" - -# define MAX_NUM_STR_LEN 21 - - - -yajl_gen_status map_uint(void *ctx, long long unsigned int num) { - char numstr[MAX_NUM_STR_LEN]; - int ret; - - ret = snprintf(numstr, sizeof(numstr), "%llu", num); - if (ret < 0 || (size_t)ret >= sizeof(numstr)) { - return yajl_gen_in_error_state; - } - return yajl_gen_number((yajl_gen)ctx, (const char *)numstr, strlen(numstr)); -} - -yajl_gen_status map_int(void *ctx, long long int num) { - char numstr[MAX_NUM_STR_LEN]; - int ret; - - ret = snprintf(numstr, sizeof(numstr), "%lld", num); - if (ret < 0 || (size_t)ret >= sizeof(numstr)) { - return yajl_gen_in_error_state; - } - return yajl_gen_number((yajl_gen)ctx, (const char *)numstr, strlen(numstr)); -} - - -bool json_gen_init(yajl_gen *g, const struct parser_context *ctx) { - *g = yajl_gen_alloc(NULL); - if (NULL == *g) { - return false; - - } - yajl_gen_config(*g, yajl_gen_beautify, (int)(!(ctx->options & OPT_GEN_SIMPLIFY))); - yajl_gen_config(*g, yajl_gen_validate_utf8, (int)(!(ctx->options & OPT_GEN_NO_VALIDATE_UTF8))); - return true; -} - -yajl_val get_val(yajl_val tree, const char *name, yajl_type type) { - const char *path[] = { name, NULL }; - return yajl_tree_get(tree, path, type); -} - -void *safe_malloc(size_t size) { - void *ret = NULL; - if (size == 0) { - abort(); - } - ret = calloc(1, size); - if (ret == NULL) { - abort(); - } - return ret; -} - -int common_safe_double(const char *numstr, double *converted) { - char *err_str = NULL; - double d; - - if (numstr == NULL) { - return -EINVAL; - } - - errno = 0; - d = strtod(numstr, &err_str); - if (errno > 0) { - return -errno; - } - - if (err_str == NULL || err_str == numstr || *err_str != '\\0') { - return -EINVAL; - } - - *converted = d; - return 0; -} - -int common_safe_uint8(const char *numstr, uint8_t *converted) { - char *err = NULL; - unsigned long int uli; - - if (numstr == NULL) { - return -EINVAL; - } - - errno = 0; - uli = strtoul(numstr, &err, 0); - if (errno > 0) { - return -errno; - } - - if (err == NULL || err == numstr || *err != '\\0') { - return -EINVAL; - } - - if (uli > UINT8_MAX) { - return -ERANGE; - } - - *converted = (uint8_t)uli; - return 0; -} - -int common_safe_uint16(const char *numstr, uint16_t *converted) { - char *err = NULL; - unsigned long int uli; - - if (numstr == NULL) { - return -EINVAL; - } - - errno = 0; - uli = strtoul(numstr, &err, 0); - if (errno > 0) { - return -errno; - } - - if (err == NULL || err == numstr || *err != '\\0') { - return -EINVAL; - } - - if (uli > UINT16_MAX) { - return -ERANGE; - } - - *converted = (uint16_t)uli; - return 0; -} - -int common_safe_uint32(const char *numstr, uint32_t *converted) { - char *err = NULL; - unsigned long long int ull; - - if (numstr == NULL) { - return -EINVAL; - } - - errno = 0; - ull = strtoull(numstr, &err, 0); - if (errno > 0) { - return -errno; - } - - if (err == NULL || err == numstr || *err != '\\0') { - return -EINVAL; - } - - if (ull > UINT32_MAX) { - return -ERANGE; - } - - *converted = (uint32_t)ull; - return 0; -} - -int common_safe_uint64(const char *numstr, uint64_t *converted) { - char *err = NULL; - unsigned long long int ull; - - if (numstr == NULL) { - return -EINVAL; - } - - errno = 0; - ull = strtoull(numstr, &err, 0); - if (errno > 0) { - return -errno; - } - - if (err == NULL || err == numstr || *err != '\\0') { - return -EINVAL; - } - - *converted = (uint64_t)ull; - return 0; -} - -int common_safe_uint(const char *numstr, unsigned int *converted) { - char *err = NULL; - unsigned long long int ull; - - if (numstr == NULL) { - return -EINVAL; - } - - errno = 0; - ull = strtoull(numstr, &err, 0); - if (errno > 0) { - return -errno; - } - - if (err == NULL || err == numstr || *err != '\\0') { - return -EINVAL; - } - - if (ull > UINT_MAX) { - return -ERANGE; - } - - *converted = (unsigned int)ull; - return 0; -} - -int common_safe_int8(const char *numstr, int8_t *converted) { - char *err = NULL; - long int li; - - if (numstr == NULL) { - return -EINVAL; - } - - errno = 0; - li = strtol(numstr, &err, 0); - if (errno > 0) { - return -errno; - } - - if (err == NULL || err == numstr || *err != '\\0') { - return -EINVAL; - } - - if (li > INT8_MAX || li < INT8_MIN) { - return -ERANGE; - } - - *converted = (int8_t)li; - return 0; -} - -int common_safe_int16(const char *numstr, int16_t *converted) { - char *err = NULL; - long int li; - - if (numstr == NULL) { - return -EINVAL; - } - - errno = 0; - li = strtol(numstr, &err, 0); - if (errno > 0) { - return -errno; - } - - if (err == NULL || err == numstr || *err != '\\0') { - return -EINVAL; - } - - if (li > INT16_MAX || li < INT16_MIN) { - return -ERANGE; - } - - *converted = (int16_t)li; - return 0; -} - -int common_safe_int32(const char *numstr, int32_t *converted) { - char *err = NULL; - long long int lli; - - if (numstr == NULL) { - return -EINVAL; - } - - errno = 0; - lli = strtol(numstr, &err, 0); - if (errno > 0) { - return -errno; - } - - if (err == NULL || err == numstr || *err != '\\0') { - return -EINVAL; - } - - if (lli > INT32_MAX || lli < INT32_MIN) { - return -ERANGE; - } - - *converted = (int32_t)lli; - return 0; -} - -int common_safe_int64(const char *numstr, int64_t *converted) { - char *err = NULL; - long long int lli; - - if (numstr == NULL) { - return -EINVAL; - } - - errno = 0; - lli = strtoll(numstr, &err, 0); - if (errno > 0) { - return -errno; - } - - if (err == NULL || err == numstr || *err != '\\0') { - return -EINVAL; - } - - *converted = (int64_t)lli; - return 0; -} - -int common_safe_int(const char *numstr, int *converted) { - char *err = NULL; - long long int lli; - - if (numstr == NULL) { - return -EINVAL; - } - - errno = 0; - lli = strtol(numstr, &err, 0); - if (errno > 0) { - return -errno; - } - - if (err == NULL || err == numstr || *err != '\\0') { - return -EINVAL; - } - - if (lli > INT_MAX || lli < INT_MIN) { - return -ERANGE; - } - - *converted = (int)lli; - return 0; -} - -char *safe_strdup(const char *src) -{ - char *dst = NULL; - - if (src == NULL) { - return NULL; - } - - dst = strdup(src); - if (dst == NULL) { - abort(); - } - - return dst; -} - - -yajl_gen_status gen_json_map_int_int(void *ctx, const json_map_int_int *map, const struct parser_context *ptx, parser_error *err) { - yajl_gen_status stat = yajl_gen_status_ok; - yajl_gen g = (yajl_gen) ctx; - size_t len = 0, i = 0; - if (map != NULL) { - len = map->len; - } - if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) { - yajl_gen_config(g, yajl_gen_beautify, 0); - } - stat = yajl_gen_map_open((yajl_gen)g); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - - } - for (i = 0; i < len; i++) { - char numstr[MAX_NUM_STR_LEN]; - int nret; - nret = snprintf(numstr, sizeof(numstr), "%lld", (long long int)map->keys[i]); - if (nret < 0 || (size_t)nret >= sizeof(numstr)) { - if (!*err && asprintf(err, "Error to print string") < 0) { - *(err) = safe_strdup("error allocating memory"); - } - return yajl_gen_in_error_state; - } - stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)numstr, strlen(numstr)); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - stat = map_int(g, map->values[i]); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - } - - stat = yajl_gen_map_close((yajl_gen)g); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) { - yajl_gen_config(g, yajl_gen_beautify, 1); - } - return yajl_gen_status_ok; -} - -void free_json_map_int_int(json_map_int_int *map) { - if (map != NULL) { - free(map->keys); - map->keys = NULL; - free(map->values); - map->values = NULL; - free(map); - } -} -json_map_int_int *make_json_map_int_int(yajl_val src, const struct parser_context *ctx, parser_error *err) { - json_map_int_int *ret = NULL; - if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { - size_t i; - size_t len = YAJL_GET_OBJECT(src)->len; - ret = safe_malloc(sizeof(*ret)); - ret->len = len; - ret->keys = safe_malloc((len + 1) * sizeof(int)); - ret->values = safe_malloc((len + 1) * sizeof(int)); - for (i = 0; i < len; i++) { - const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; - yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; - - if (srckey != NULL) { - int invalid; - invalid = common_safe_int(srckey, &(ret->keys[i])); - if (invalid) { - if (*err == NULL && asprintf(err, "Invalid key '%s' with type 'int': %s", srckey, strerror(-invalid)) < 0) { - *(err) = safe_strdup("error allocating memory"); - } - free_json_map_int_int(ret); - return NULL; - } - } - - if (srcval != NULL) { - int invalid; - if (!YAJL_IS_NUMBER(srcval)) { - if (*err == NULL && asprintf(err, "Invalid value with type 'int' for key '%s'", srckey) < 0) { - *(err) = safe_strdup("error allocating memory"); - } - free_json_map_int_int(ret); - return NULL; - } - invalid = common_safe_int(YAJL_GET_NUMBER(srcval), &(ret->values[i])); - if (invalid) { - if (*err == NULL && asprintf(err, "Invalid value with type 'int' for key '%s': %s", srckey, strerror(-invalid)) < 0) { - *(err) = safe_strdup("error allocating memory"); - } - free_json_map_int_int(ret); - return NULL; - } - } - } - } - return ret; -} -int append_json_map_int_int(json_map_int_int *map, int key, int val) { - size_t len; - int *keys = NULL; - int *vals = NULL; - - if (map == NULL) { - return -1; - } - - if ((SIZE_MAX / sizeof(int) - 1) < map->len) { - return -1; - } - - len = map->len + 1; - keys = safe_malloc(len * sizeof(int)); - vals = safe_malloc(len * sizeof(int)); - - if (map->len) { - (void)memcpy(keys, map->keys, map->len * sizeof(int)); - (void)memcpy(vals, map->values, map->len * sizeof(int)); - } - free(map->keys); - map->keys = keys; - free(map->values); - map->values = vals; - map->keys[map->len] = key; - map->values[map->len] = val; - - map->len++; - return 0; -} - -yajl_gen_status gen_json_map_int_bool(void *ctx, const json_map_int_bool *map, const struct parser_context *ptx, parser_error *err) { - yajl_gen_status stat = yajl_gen_status_ok; - yajl_gen g = (yajl_gen) ctx; - size_t len = 0, i = 0; - if (map != NULL) { - len = map->len; - } - if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) { - yajl_gen_config(g, yajl_gen_beautify, 0); - } - stat = yajl_gen_map_open((yajl_gen)g); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - - } - for (i = 0; i < len; i++) { - char numstr[MAX_NUM_STR_LEN]; - int nret; - nret = snprintf(numstr, sizeof(numstr), "%lld", (long long int)map->keys[i]); - if (nret < 0 || (size_t)nret >= sizeof(numstr)) { - if (!*err && asprintf(err, "Error to print string") < 0) { - *(err) = safe_strdup("error allocating memory"); - } - return yajl_gen_in_error_state; - } - stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)numstr, strlen(numstr)); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - stat = yajl_gen_bool((yajl_gen)g, (int)(map->values[i])); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - } - - stat = yajl_gen_map_close((yajl_gen)g); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) { - yajl_gen_config(g, yajl_gen_beautify, 1); - } - return yajl_gen_status_ok; -} - -void free_json_map_int_bool(json_map_int_bool *map) { - if (map != NULL) { - size_t i; - for (i = 0; i < map->len; i++) { - // No need to free key for type int - // No need to free value for type bool - } - free(map->keys); - map->keys = NULL; - free(map->values); - map->values = NULL; - free(map); - } -} -json_map_int_bool *make_json_map_int_bool(yajl_val src, const struct parser_context *ctx, parser_error *err) { - json_map_int_bool *ret = NULL; - if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { - size_t i; - size_t len = YAJL_GET_OBJECT(src)->len; - ret = safe_malloc(sizeof(*ret)); - ret->len = len; - ret->keys = safe_malloc((len + 1) * sizeof(int)); - ret->values = safe_malloc((len + 1) * sizeof(bool)); - for (i = 0; i < len; i++) { - const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; - yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; - - if (srckey != NULL) { - int invalid; - invalid = common_safe_int(srckey, &(ret->keys[i])); - if (invalid) { - if (*err == NULL && asprintf(err, "Invalid key '%s' with type 'int': %s", srckey, strerror(-invalid)) < 0) { - *(err) = safe_strdup("error allocating memory"); - } - free_json_map_int_bool(ret); - return NULL; - } - } - - if (srcval != NULL) { - if (YAJL_IS_TRUE(srcval)) { - ret->values[i] = true; - } else if (YAJL_IS_FALSE(srcval)) { - ret->values[i] = false; - } else { - if (*err == NULL && asprintf(err, "Invalid value with type 'bool' for key '%s'", srckey) < 0) { - *(err) = safe_strdup("error allocating memory"); - } - free_json_map_int_bool(ret); - return NULL; - } - } - } - } - return ret; -} -int append_json_map_int_bool(json_map_int_bool *map, int key, bool val) { - size_t len; - int *keys = NULL; - bool *vals = NULL; - - if (map == NULL) { - return -1; - } - - if ((SIZE_MAX / sizeof(int) - 1) < map->len || (SIZE_MAX / sizeof(bool) - 1) < map->len) { - return -1; - } - - len = map->len + 1; - keys = safe_malloc(len * sizeof(int)); - vals = safe_malloc(len * sizeof(bool)); - - if (map->len) { - (void)memcpy(keys, map->keys, map->len * sizeof(int)); - (void)memcpy(vals, map->values, map->len * sizeof(bool)); - } - free(map->keys); - map->keys = keys; - free(map->values); - map->values = vals; - map->keys[map->len] = key; - map->values[map->len] = val; - - map->len++; - return 0; -} - -yajl_gen_status gen_json_map_int_string(void *ctx, const json_map_int_string *map, const struct parser_context *ptx, parser_error *err) { - yajl_gen_status stat = yajl_gen_status_ok; - yajl_gen g = (yajl_gen) ctx; - size_t len = 0, i = 0; - if (map != NULL) { - len = map->len; - } - if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) { - yajl_gen_config(g, yajl_gen_beautify, 0); - } - stat = yajl_gen_map_open((yajl_gen)g); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - - } - for (i = 0; i < len; i++) { - char numstr[MAX_NUM_STR_LEN]; - int nret; - nret = snprintf(numstr, sizeof(numstr), "%lld", (long long int)map->keys[i]); - if (nret < 0 || (size_t)nret >= sizeof(numstr)) { - if (!*err && asprintf(err, "Error to print string") < 0) { - *(err) = safe_strdup("error allocating memory"); - } - return yajl_gen_in_error_state; - } - stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)numstr, strlen(numstr)); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)(map->values[i]), strlen(map->values[i])); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - } - - stat = yajl_gen_map_close((yajl_gen)g); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) { - yajl_gen_config(g, yajl_gen_beautify, 1); - } - return yajl_gen_status_ok; -} - -void free_json_map_int_string(json_map_int_string *map) { - if (map != NULL) { - size_t i; - for (i = 0; i < map->len; i++) { - // No need to free key for type int - free(map->values[i]); - map->values[i] = NULL; - } - free(map->keys); - map->keys = NULL; - free(map->values); - map->values = NULL; - free(map); - } -} -json_map_int_string *make_json_map_int_string(yajl_val src, const struct parser_context *ctx, parser_error *err) { - json_map_int_string *ret = NULL; - if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { - size_t i; - size_t len = YAJL_GET_OBJECT(src)->len; - ret = safe_malloc(sizeof(*ret)); - ret->len = len; - ret->keys = safe_malloc((len + 1) * sizeof(int)); - ret->values = safe_malloc((len + 1) * sizeof(char *)); - for (i = 0; i < len; i++) { - const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; - yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; - - if (srckey != NULL) { - int invalid; - invalid = common_safe_int(srckey, &(ret->keys[i])); - if (invalid) { - if (*err == NULL && asprintf(err, "Invalid key '%s' with type 'int': %s", srckey, strerror(-invalid)) < 0) { - *(err) = safe_strdup("error allocating memory"); - } - free_json_map_int_string(ret); - return NULL; - } - } - - if (srcval != NULL) { - if (!YAJL_IS_STRING(srcval)) { - if (*err == NULL && asprintf(err, "Invalid value with type 'string' for key '%s'", srckey) < 0) { - *(err) = safe_strdup("error allocating memory"); - } - free_json_map_int_string(ret); - return NULL; - } - char *str = YAJL_GET_STRING(srcval); - ret->values[i] = safe_strdup(str ? str : ""); - } - } - } - return ret; -} -int append_json_map_int_string(json_map_int_string *map, int key, const char *val) { - size_t len; - int *keys = NULL; - char **vals = NULL; - - if (map == NULL) { - return -1; - } - - if ((SIZE_MAX / sizeof(int) - 1) < map->len || (SIZE_MAX / sizeof(char *) - 1) < map->len) { - return -1; - } - - len = map->len + 1; - keys = safe_malloc(len * sizeof(int)); - vals = safe_malloc(len * sizeof(char *)); - - if (map->len) { - (void)memcpy(keys, map->keys, map->len * sizeof(int)); - (void)memcpy(vals, map->values, map->len * sizeof(char *)); - } - free(map->keys); - map->keys = keys; - free(map->values); - map->values = vals; - map->keys[map->len] = key; - map->values[map->len] = safe_strdup(val ? val : ""); - - map->len++; - return 0; -} - -yajl_gen_status gen_json_map_string_int(void *ctx, const json_map_string_int *map, const struct parser_context *ptx, parser_error *err) { - yajl_gen_status stat = yajl_gen_status_ok; - yajl_gen g = (yajl_gen) ctx; - size_t len = 0, i = 0; - if (map != NULL) { - len = map->len; - } - if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) { - yajl_gen_config(g, yajl_gen_beautify, 0); - } - stat = yajl_gen_map_open((yajl_gen)g); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - - } - for (i = 0; i < len; i++) { - stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)(map->keys[i]), strlen(map->keys[i])); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - stat = map_int(g, map->values[i]); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - } - - stat = yajl_gen_map_close((yajl_gen)g); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) { - yajl_gen_config(g, yajl_gen_beautify, 1); - } - return yajl_gen_status_ok; -} - -void free_json_map_string_int(json_map_string_int *map) { - if (map != NULL) { - size_t i; - for (i = 0; i < map->len; i++) { - free(map->keys[i]); - map->keys[i] = NULL; - } - free(map->keys); - map->keys = NULL; - free(map->values); - map->values = NULL; - free(map); - } -} -json_map_string_int *make_json_map_string_int(yajl_val src, const struct parser_context *ctx, parser_error *err) { - json_map_string_int *ret = NULL; - if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { - size_t i; - size_t len = YAJL_GET_OBJECT(src)->len; - ret = safe_malloc(sizeof(*ret)); - ret->len = len; - ret->keys = safe_malloc((len + 1) * sizeof(char *)); - ret->values = safe_malloc((len + 1) * sizeof(int)); - for (i = 0; i < len; i++) { - const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; - yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; - ret->keys[i] = safe_strdup(srckey ? srckey : ""); - - if (srcval != NULL) { - int invalid; - if (!YAJL_IS_NUMBER(srcval)) { - if (*err == NULL && asprintf(err, "Invalid value with type 'int' for key '%s'", srckey) < 0) { - *(err) = safe_strdup("error allocating memory"); - } - free_json_map_string_int(ret); - return NULL; - } - invalid = common_safe_int(YAJL_GET_NUMBER(srcval), &(ret->values[i])); - if (invalid) { - if (*err == NULL && asprintf(err, "Invalid value with type 'int' for key '%s': %s", srckey, strerror(-invalid)) < 0) { - *(err) = safe_strdup("error allocating memory"); - } - free_json_map_string_int(ret); - return NULL; - } - } - } - } - return ret; -} -int append_json_map_string_int(json_map_string_int *map, const char *key, int val) { - size_t len; - char **keys = NULL; - int *vals = NULL; - - if (map == NULL) { - return -1; - } - - if ((SIZE_MAX / sizeof(char *) - 1) < map->len || (SIZE_MAX / sizeof(int) - 1) < map->len) { - return -1; - } - - len = map->len + 1; - keys = safe_malloc(len * sizeof(char *)); - vals = safe_malloc(len * sizeof(int)); - - if (map->len) { - (void)memcpy(keys, map->keys, map->len * sizeof(char *)); - (void)memcpy(vals, map->values, map->len * sizeof(int)); - } - free(map->keys); - map->keys = keys; - free(map->values); - map->values = vals; - map->keys[map->len] = safe_strdup(key ? key : ""); - map->values[map->len] = val; - - map->len++; - return 0; -} - -yajl_gen_status gen_json_map_string_bool(void *ctx, const json_map_string_bool *map, const struct parser_context *ptx, parser_error *err) { - yajl_gen_status stat = yajl_gen_status_ok; - yajl_gen g = (yajl_gen) ctx; - size_t len = 0, i = 0; - if (map != NULL) { - len = map->len; - } - if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) { - yajl_gen_config(g, yajl_gen_beautify, 0); - } - stat = yajl_gen_map_open((yajl_gen)g); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - - } - for (i = 0; i < len; i++) { - stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)(map->keys[i]), strlen(map->keys[i])); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - stat = yajl_gen_bool((yajl_gen)g, (int)(map->values[i])); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - } - - stat = yajl_gen_map_close((yajl_gen)g); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) { - yajl_gen_config(g, yajl_gen_beautify, 1); - } - return yajl_gen_status_ok; -} - -void free_json_map_string_bool(json_map_string_bool *map) { - if (map != NULL) { - size_t i; - for (i = 0; i < map->len; i++) { - free(map->keys[i]); - map->keys[i] = NULL; - // No need to free value for type bool - } - free(map->keys); - map->keys = NULL; - free(map->values); - map->values = NULL; - free(map); - } -} -json_map_string_bool *make_json_map_string_bool(yajl_val src, const struct parser_context *ctx, parser_error *err) { - json_map_string_bool *ret = NULL; - if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { - size_t i; - size_t len = YAJL_GET_OBJECT(src)->len; - ret = safe_malloc(sizeof(*ret)); - ret->len = len; - ret->keys = safe_malloc((len + 1) * sizeof(char *)); - ret->values = safe_malloc((len + 1) * sizeof(bool)); - for (i = 0; i < len; i++) { - const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; - yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; - ret->keys[i] = safe_strdup(srckey ? srckey : ""); - - if (srcval != NULL) { - if (YAJL_IS_TRUE(srcval)) { - ret->values[i] = true; - } else if (YAJL_IS_FALSE(srcval)) { - ret->values[i] = false; - } else { - if (*err == NULL && asprintf(err, "Invalid value with type 'bool' for key '%s'", srckey) < 0) { - *(err) = safe_strdup("error allocating memory"); - } - free_json_map_string_bool(ret); - return NULL; - } - } - } - } - return ret; -} -int append_json_map_string_bool(json_map_string_bool *map, const char *key, bool val) { - size_t len; - char **keys = NULL; - bool *vals = NULL; - - if (map == NULL) { - return -1; - } - - if ((SIZE_MAX / sizeof(char *) - 1) < map->len || (SIZE_MAX / sizeof(bool) - 1) < map->len) { - return -1; - } - - len = map->len + 1; - keys = safe_malloc(len * sizeof(char *)); - vals = safe_malloc(len * sizeof(bool)); - - if (map->len) { - (void)memcpy(keys, map->keys, map->len * sizeof(char *)); - (void)memcpy(vals, map->values, map->len * sizeof(bool)); - } - free(map->keys); - map->keys = keys; - free(map->values); - map->values = vals; - map->keys[map->len] = safe_strdup(key ? key : ""); - map->values[map->len] = val; - - map->len++; - return 0; -} - -yajl_gen_status gen_json_map_string_string(void *ctx, const json_map_string_string *map, const struct parser_context *ptx, parser_error *err) { - yajl_gen_status stat = yajl_gen_status_ok; - yajl_gen g = (yajl_gen) ctx; - size_t len = 0, i = 0; - if (map != NULL) { - len = map->len; - } - if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) { - yajl_gen_config(g, yajl_gen_beautify, 0); - } - stat = yajl_gen_map_open((yajl_gen)g); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - - } - for (i = 0; i < len; i++) { - stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)(map->keys[i]), strlen(map->keys[i])); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)(map->values[i]), strlen(map->values[i])); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - } - - stat = yajl_gen_map_close((yajl_gen)g); - if (yajl_gen_status_ok != stat) { - GEN_SET_ERROR_AND_RETURN(stat, err); - } - if (!len && !(ptx->options & OPT_GEN_SIMPLIFY)) { - yajl_gen_config(g, yajl_gen_beautify, 1); - } - return yajl_gen_status_ok; -} - -void free_json_map_string_string(json_map_string_string *map) { - if (map != NULL) { - size_t i; - for (i = 0; i < map->len; i++) { - free(map->keys[i]); - map->keys[i] = NULL; - free(map->values[i]); - map->values[i] = NULL; - } - free(map->keys); - map->keys = NULL; - free(map->values); - map->values = NULL; - free(map); - } -} -json_map_string_string *make_json_map_string_string(yajl_val src, const struct parser_context *ctx, parser_error *err) { - json_map_string_string *ret = NULL; - if (src != NULL && YAJL_GET_OBJECT(src) != NULL) { - size_t i; - size_t len = YAJL_GET_OBJECT(src)->len; - ret = safe_malloc(sizeof(*ret)); - ret->len = len; - ret->keys = safe_malloc((len + 1) * sizeof(char *)); - ret->values = safe_malloc((len + 1) * sizeof(char *)); - for (i = 0; i < len; i++) { - const char *srckey = YAJL_GET_OBJECT(src)->keys[i]; - yajl_val srcval = YAJL_GET_OBJECT(src)->values[i]; - ret->keys[i] = safe_strdup(srckey ? srckey : ""); - - if (srcval != NULL) { - if (!YAJL_IS_STRING(srcval)) { - if (*err == NULL && asprintf(err, "Invalid value with type 'string' for key '%s'", srckey) < 0) { - *(err) = safe_strdup("error allocating memory"); - } - free_json_map_string_string(ret); - return NULL; - } - char *str = YAJL_GET_STRING(srcval); - ret->values[i] = safe_strdup(str ? str : ""); - } - } - } - return ret; -} -int append_json_map_string_string(json_map_string_string *map, const char *key, const char *val) { - size_t len, i; - char **keys = NULL; - char **vals = NULL; - - if (map == NULL) { - return -1; - } - - for (i = 0; i < map->len; i++) { - if (strcmp(map->keys[i], key) == 0) { - free(map->values[i]); - map->values[i] = safe_strdup(val ? val : ""); - return 0; - } - } - - if ((SIZE_MAX / sizeof(char *) - 1) < map->len) { - return -1; - } - - len = map->len + 1; - keys = safe_malloc(len * sizeof(char *)); - vals = safe_malloc(len * sizeof(char *)); - - if (map->len) { - (void)memcpy(keys, map->keys, map->len * sizeof(char *)); - (void)memcpy(vals, map->values, map->len * sizeof(char *)); - } - free(map->keys); - map->keys = keys; - free(map->values); - map->values = vals; - map->keys[map->len] = safe_strdup(key ? key : ""); - map->values[map->len] = safe_strdup(val ? val : ""); - - map->len++; - return 0; -} - -char *json_marshal_string(const char *str, size_t strlen, const struct parser_context *ctx, parser_error *err) -{ - yajl_gen g = NULL; - struct parser_context tmp_ctx = { 0 }; - const unsigned char *gen_buf = NULL; - char *json_buf = NULL; - size_t gen_len = 0; - yajl_gen_status stat; - - if (str == NULL || err == NULL) - return NULL; - - *err = NULL; - if (ctx == NULL) { - ctx = (const struct parser_context *)(&tmp_ctx); - } - - if (!json_gen_init(&g, ctx)) { - *err = safe_strdup("Json_gen init failed"); - goto out; - } - stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)str, strlen); - if (yajl_gen_status_ok != stat) { - if (asprintf(err, "error generating json, errcode: %d", (int)stat) < 0) { - *err = safe_strdup("error allocating memory"); - } - goto free_out; - } - yajl_gen_get_buf(g, &gen_buf, &gen_len); - if (gen_buf == NULL) { - *err = safe_strdup("Error to get generated json"); - goto free_out; - } - - json_buf = safe_malloc(gen_len + 1); - (void)memcpy(json_buf, gen_buf, gen_len); - json_buf[gen_len] = '\\0'; - -free_out: - yajl_gen_clear(g); - yajl_gen_free(g); -out: - return json_buf; -} - -''' diff --git a/src/json/schema/src/common_h.py b/src/json/schema/src/common_h.py deleted file mode 100644 index 8baafbe..0000000 --- a/src/json/schema/src/common_h.py +++ /dev/null @@ -1,213 +0,0 @@ -# -*- coding: utf-8 -*- -''' -Description: commom header file -Interface: None -History: 2019-06-17 -''' -# -# libocispec - a C library for parsing OCI spec files. -# -# Copyright (C) 2017, 2019 Giuseppe Scrivano -# Copyright (C) Huawei Technologies., Ltd. 2018-2019. All rights reserved. -# -# libocispec is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# libocispec 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with libocispec. If not, see . -# -# As a special exception, you may create a larger work that contains -# part or all of the libocispec parser skeleton and distribute that work -# under terms of your choice, so long as that work isn't itself a -# parser generator using the skeleton or a modified version thereof -# as a parser skeleton. Alternatively, if you modify or redistribute -# the parser skeleton itself, you may (at your option) remove this -# special exception, which will cause the skeleton and the resulting -# libocispec output files to be licensed under the GNU General Public -# License without this special exception. -#!/usr/bin/python -Es - -""" -Description: json common c code -Interface: None -History: 2019-06-18 -Purpose: defined the common tool function for parse json -Defined the CODE global variable to hold the c code -""" -# - Defined the CODE global variable to hold the c code -CODE = '''// Auto generated file. Do not edit! -# ifndef _JSON_COMMON_H -# define _JSON_COMMON_H - -# include -# include -# include -# include -# include -# include -# include - -# ifdef __cplusplus -extern "C" { -# endif - -# undef linux - -// options to report error if there is unknown key found in json -# define OPT_PARSE_STRICT 0x01 -// options to generate all key and value -# define OPT_GEN_KAY_VALUE 0x02 -// options to generate simplify(no indent) json string -# define OPT_GEN_SIMPLIFY 0x04 -// options not to validate utf8 data -# define OPT_GEN_NO_VALIDATE_UTF8 0x08 - -# define GEN_SET_ERROR_AND_RETURN(stat, err) { \\ - if (*(err) == NULL) {\\ - if (asprintf(err, "%s: %s: %d: error generating json, errcode: %u", __FILE__, __func__, __LINE__, stat) < 0) { \\ - *(err) = safe_strdup("error allocating memory"); \\ - } \\ - }\\ - return stat; \\ -} - -typedef char *parser_error; - -struct parser_context { - unsigned int options; - FILE *stderr; -}; - -yajl_gen_status map_uint(void *ctx, long long unsigned int num); - -yajl_gen_status map_int(void *ctx, long long int num); - -bool json_gen_init(yajl_gen *g, const struct parser_context *ctx); - -yajl_val get_val(yajl_val tree, const char *name, yajl_type type); - -void *safe_malloc(size_t size); - -int common_safe_double(const char *numstr, double *converted); - -int common_safe_uint8(const char *numstr, uint8_t *converted); - -int common_safe_uint16(const char *numstr, uint16_t *converted); - -int common_safe_uint32(const char *numstr, uint32_t *converted); - -int common_safe_uint64(const char *numstr, uint64_t *converted); - -int common_safe_uint(const char *numstr, unsigned int *converted); - -int common_safe_int8(const char *numstr, int8_t *converted); - -int common_safe_int16(const char *numstr, int16_t *converted); - -int common_safe_int32(const char *numstr, int32_t *converted); - -int common_safe_int64(const char *numstr, int64_t *converted); - -int common_safe_int(const char *numstr, int *converted); - -char *safe_strdup(const char *src); - -typedef struct { - int *keys; - int *values; - size_t len; -} json_map_int_int; - -void free_json_map_int_int(json_map_int_int *map); - -json_map_int_int *make_json_map_int_int(yajl_val src, const struct parser_context *ctx, parser_error *err); - -yajl_gen_status gen_json_map_int_int(void *ctx, const json_map_int_int *map, const struct parser_context *ptx, parser_error *err); - -int append_json_map_int_int(json_map_int_int *map, int key, int val); - -typedef struct { - int *keys; - bool *values; - size_t len; -} json_map_int_bool; - -void free_json_map_int_bool(json_map_int_bool *map); - -json_map_int_bool *make_json_map_int_bool(yajl_val src, const struct parser_context *ctx, parser_error *err); - -yajl_gen_status gen_json_map_int_bool(void *ctx, const json_map_int_bool *map, const struct parser_context *ptx, parser_error *err); - -int append_json_map_int_bool(json_map_int_bool *map, int key, bool val); - -typedef struct { - int *keys; - char **values; - size_t len; -} json_map_int_string; - -void free_json_map_int_string(json_map_int_string *map); - -json_map_int_string *make_json_map_int_string(yajl_val src, const struct parser_context *ctx, parser_error *err); - -yajl_gen_status gen_json_map_int_string(void *ctx, const json_map_int_string *map, const struct parser_context *ptx, parser_error *err); - -int append_json_map_int_string(json_map_int_string *map, int key, const char *val); - -typedef struct { - char **keys; - int *values; - size_t len; -} json_map_string_int; - -void free_json_map_string_int(json_map_string_int *map); - -json_map_string_int *make_json_map_string_int(yajl_val src, const struct parser_context *ctx, parser_error *err); - -yajl_gen_status gen_json_map_string_int(void *ctx, const json_map_string_int *map, const struct parser_context *ptx, parser_error *err); - -int append_json_map_string_int(json_map_string_int *map, const char *key, int val); - -typedef struct { - char **keys; - bool *values; - size_t len; -} json_map_string_bool; - -void free_json_map_string_bool(json_map_string_bool *map); - -json_map_string_bool *make_json_map_string_bool(yajl_val src, const struct parser_context *ctx, parser_error *err); - -yajl_gen_status gen_json_map_string_bool(void *ctx, const json_map_string_bool *map, const struct parser_context *ptx, parser_error *err); - -int append_json_map_string_bool(json_map_string_bool *map, const char *key, bool val); - -typedef struct { - char **keys; - char **values; - size_t len; -} json_map_string_string; - -void free_json_map_string_string(json_map_string_string *map); - -json_map_string_string *make_json_map_string_string(yajl_val src, const struct parser_context *ctx, parser_error *err); - -yajl_gen_status gen_json_map_string_string(void *ctx, const json_map_string_string *map, const struct parser_context *ptx, parser_error *err); - -int append_json_map_string_string(json_map_string_string *map, const char *key, const char *val); - -char *json_marshal_string(const char *str, size_t strlen, const struct parser_context *ctx, parser_error *err); - -# ifdef __cplusplus -} -# endif - -# endif -''' diff --git a/src/json/schema/src/generate.py b/src/json/schema/src/generate.py deleted file mode 100644 index 698262c..0000000 --- a/src/json/schema/src/generate.py +++ /dev/null @@ -1,841 +0,0 @@ -# -*- coding: utf-8 -*- -''' -Description: header class and functions -Interface: None -History: 2019-06-17 -''' - -# libocispec - a C library for parsing OCI spec files. -# -# Copyright (C) 2017, 2019 Giuseppe Scrivano -# Copyright (C) Huawei Technologies., Ltd. 2018-2019. All rights reserved. -# -# libocispec is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# libocispec 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with libocispec. If not, see . -# -# As a special exception, you may create a larger work that contains -# part or all of the libocispec parser skeleton and distribute that work -# under terms of your choice, so long as that work isn't itself a -# parser generator using the skeleton or a modified version thereof -# as a parser skeleton. Alternatively, if you modify or redistribute -# the parser skeleton itself, you may (at your option) remove this -# special exception, which will cause the skeleton and the resulting -# libocispec output files to be licensed under the GNU General Public -# License without this special exception. - -import traceback -import os -import sys -import json -import fcntl -import argparse - -from collections import OrderedDict -import helpers -import headers -import sources -import common_h -import common_c - -# - json suffix -JSON_SUFFIX = ".json" - -''' -Description: ref suffix -Interface: ref_suffix -History: 2019-06-17 -''' -# - Description: ref suffix -REF_SUFFIX = "_json" - -''' -Description: root paths -Interface: rootpaths -History: 2019-06-17 -''' -class MyRoot(object): - ''' - Description: Store schema information - Interface: None - History: 2019-06-17 - ''' - def __init__(self, root_path): - self.root_path = root_path - - def get_repr(self): - ''' - Description: Store schema information - Interface: None - History: 2019-06-17 - ''' - return "{root_path:(%s)}" % (self.root_path) - - def get_path(self): - ''' - Description: Store schema information - Interface: None - History: 2019-06-17 - ''' - return self.root_path - - -def trim_json_suffix(name): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - if name.endswith(JSON_SUFFIX) or name.endswith(REF_SUFFIX): - name = name[:-len(JSON_SUFFIX)] - return helpers.conv_to_c_style(name.replace('.', '_').replace('-', '_')) - - -def get_prefix_package(filepath, rootpath): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - realpath = os.path.realpath(filepath) - - if realpath.startswith(rootpath) and len(realpath) > len(rootpath): - return helpers.conv_to_c_style(os.path.dirname(realpath)[(len(rootpath) + 1):]) - else: - raise RuntimeError('schema path \"%s\" is not in scope of root path \"%s\"' \ - % (realpath, rootpath)) - - -def get_prefix_from_file(filepath): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - prefix_file = trim_json_suffix(os.path.basename(filepath)) - root_path = MyRoot.root_path - prefix_package = get_prefix_package(filepath, root_path) - prefix = prefix_file if prefix_package == "" else prefix_package + "_" + prefix_file - return prefix - - -def schema_from_file(filepath, srcpath): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - schemapath = helpers.FilePath(filepath) - prefix = get_prefix_from_file(schemapath.name) - header = helpers.FilePath(os.path.join(srcpath, prefix + ".h")) - source = helpers.FilePath(os.path.join(srcpath, prefix + ".c")) - schema_info = helpers.SchemaInfo(schemapath, header, source, prefix, srcpath) - return schema_info - - -def make_ref_name(refname, reffile): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - prefix = get_prefix_from_file(reffile) - if refname == "" or prefix.endswith(refname): - return prefix - return prefix + "_" + helpers.conv_to_c_style(refname) - - -def splite_ref_name(ref): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - tmp_f, tmp_r = ref.split("#/") if '#/' in ref else (ref, "") - return tmp_f, tmp_r - - -def merge(children): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - subchildren = [] - for i in children: - for j in i.children: - subchildren.append(j) - - return subchildren - -# BASIC_TYPES include all basic types -BASIC_TYPES = ( - "byte", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "UID", "GID", - "bytePointer", "doublePointer", "int8Pointer", "int16Pointer", "int32Pointer", "int64Pointer", - "uint8Pointer", "uint16Pointer", "uint32Pointer", "uint64Pointer", "ArrayOfStrings", - "booleanPointer" -) - - -def judge_support_type(typ): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - return typ in ("integer", "boolean", "string", "double") or typ in BASIC_TYPES - - -def get_ref_subref(src, subref): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - cur = src - subrefname = "" - for j in subref.split('/'): - subrefname = j - if j in BASIC_TYPES: - return src, {"type": j}, subrefname - cur = cur[j] - - return src, cur, subrefname - - -def get_ref_root(schema_info, src, ref, curfile): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - refname = "" - tmp_f, tmp_r = splite_ref_name(ref) - - if tmp_f == "": - cur = src - else: - realpath = os.path.realpath(os.path.join(os.path.dirname(curfile), tmp_f)) - curfile = realpath - - subschema = schema_from_file(realpath, schema_info.filesdir) - if schema_info.refs is None: - schema_info.refs = {} - schema_info.refs[subschema.header.basename] = subschema - with open(realpath) as i: - cur = src = json.loads(i.read()) - subcur = cur - if tmp_r != "": - src, subcur, refname = get_ref_subref(src, tmp_r) - - if 'type' not in subcur and '$ref' in subcur: - subf, subr = splite_ref_name(subcur['$ref']) - if subf == "": - src, subcur, refname = get_ref_subref(src, subr) - if 'type' not in subcur: - raise RuntimeError("Not support reference of nesting more than 2 level: ", ref) - else: - return get_ref_root(schema_info, src, subcur['$ref'], curfile) - return src, subcur, curfile, make_ref_name(refname, curfile) - - -def get_type_pattern_incur(cur, schema_info, src, curfile): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - # pattern of key: - # '.{1,}' represents type 'string', - # '.{2,}' represents type 'integer' - if '.{2,}' in cur['patternProperties']: - map_key = 'Int' - else: - map_key = 'String' - for i, value in enumerate(cur['patternProperties'].values()): - # only use the first value - if i == 0: - if 'type' in value: - val = value["type"] - else: - dummy_subsrc, subcur, dummy_subcurfile, dummy_subrefname = get_ref_root( - schema_info, src, value['$ref'], curfile) - val = subcur['type'] - break - - m_key = { - 'object': 'Object', - 'string': 'String', - 'integer': 'Int', - 'boolean': 'Bool' - }[val] - map_val = m_key - - typ = 'map' + map_key + map_val - return typ - - -class GenerateNodeInfo(object): - ''' - Description: Store schema information - Interface: None - History: 2019-06-17 - ''' - def __init__(self, schema_info, name, cur, curfile): - self.schema_info = schema_info - self.name = name - self.cur = cur - self.curfile = curfile - - def get_repr(self): - ''' - Description: Store schema information - Interface: None - History: 2019-06-17 - ''' - return "{schema_info:(%s) name:(%s) cur:(%s) curfile:(%s)}" \ - % (self.schema_info, self.name, self.cur, self.curfile) - - def get_name(self): - ''' - Description: Store schema information - Interface: None - History: 2019-06-17 - ''' - return self.name - - -def gen_all_arr_typnode(node_info, src, typ, refname): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - schema_info = node_info.schema_info - name = node_info.name - cur = node_info.cur - curfile = node_info.curfile - subtyp = None - subtypobj = None - required = None - children = merge(resolve_list(schema_info, name, src, cur["items"]['allOf'], curfile)) - subtyp = children[0].typ - subtypobj = children - return helpers.Unite(name, - typ, - children, - subtyp=subtyp, - subtypobj=subtypobj, - subtypname=refname, - required=required), src - - -def gen_any_arr_typnode(node_info, src, typ, refname): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - schema_info = node_info.schema_info - name = node_info.name - cur = node_info.cur - curfile = node_info.curfile - subtyp = None - subtypobj = None - required = None - anychildren = resolve_list(schema_info, name, src, cur["items"]['anyOf'], curfile) - subtyp = anychildren[0].typ - children = anychildren[0].children - subtypobj = children - refname = anychildren[0].subtypname - return helpers.Unite(name, - typ, - children, - subtyp=subtyp, - subtypobj=subtypobj, - subtypname=refname, - required=required), src - - -def gen_ref_arr_typnode(node_info, src, typ, refname): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - schema_info = node_info.schema_info - name = node_info.name - cur = node_info.cur - curfile = node_info.curfile - - item_type, src = resolve_type(schema_info, name, src, cur["items"], curfile) - ref_file, subref = splite_ref_name(cur['items']['$ref']) - if ref_file == "": - src, dummy_subcur, subrefname = get_ref_subref(src, subref) - refname = make_ref_name(subrefname, curfile) - else: - refname = item_type.subtypname - return helpers.Unite(name, - typ, - None, - subtyp=item_type.typ, - subtypobj=item_type.children, - subtypname=refname, - required=item_type.required), src - - -def gen_type_arr_typnode(node_info, src, typ, refname): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - schema_info = node_info.schema_info - name = node_info.name - cur = node_info.cur - curfile = node_info.curfile - - item_type, src = resolve_type(schema_info, name, src, cur["items"], curfile) - return helpers.Unite(name, - typ, - None, - subtyp=item_type.typ, - subtypobj=item_type.children, - subtypname=refname, - required=item_type.required), src - - -def gen_arr_typnode(node_info, src, typ, refname): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - cur = node_info.cur - - if 'allOf' in cur["items"]: - return gen_all_arr_typnode(node_info, src, typ, refname) - elif 'anyOf' in cur["items"]: - return gen_any_arr_typnode(node_info, src, typ, refname) - elif '$ref' in cur["items"]: - return gen_ref_arr_typnode(node_info, src, typ, refname) - elif 'type' in cur["items"]: - return gen_type_arr_typnode(node_info, src, typ, refname) - return None - - -def gen_obj_typnode(node_info, src, typ, refname): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - schema_info = node_info.schema_info - name = node_info.name - cur = node_info.cur - curfile = node_info.curfile - children = None - subtyp = None - subtypobj = None - required = None - - if 'allOf' in cur: - children = merge(resolve_list(schema_info, name, src, cur['allOf'], curfile)) - elif 'anyOf' in cur: - children = resolve_list(schema_info, name, src, cur['anyOf'], curfile) - elif 'patternProperties' in cur: - children = parse_properties(schema_info, name, src, cur, curfile) - children[0].name = children[0].name.replace('_{1,}', 'element').replace('_{2,}', \ - 'element') - children[0].fixname = "values" - if helpers.valid_basic_map_name(children[0].typ): - children[0].name = helpers.make_basic_map_name(children[0].typ) - else: - children = parse_properties(schema_info, name, src, cur, curfile) \ - if 'properties' in cur else None - if 'required' in cur: - required = cur['required'] - return helpers.Unite(name,\ - typ,\ - children,\ - subtyp=subtyp,\ - subtypobj=subtypobj,\ - subtypname=refname,\ - required=required), src - - -def get_typ_notoneof(schema_info, src, cur, curfile): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - if 'patternProperties' in cur: - typ = get_type_pattern_incur(cur, schema_info, src, curfile) - elif "type" in cur: - typ = cur["type"] - else: - typ = "object" - - return typ - - -def resolve_type(schema_info, name, src, cur, curfile): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - children = None - subtyp = None - subtypobj = None - required = None - refname = None - - if '$ref' in cur: - src, cur, curfile, refname = get_ref_root(schema_info, src, cur['$ref'], curfile) - - if "oneOf" in cur: - cur = cur['oneOf'][0] - if '$ref' in cur: - return resolve_type(schema_info, name, src, cur, curfile) - else: - typ = cur['type'] - else: - typ = get_typ_notoneof(schema_info, src, cur, curfile) - - node_info = GenerateNodeInfo(schema_info, name, cur, curfile) - - if helpers.valid_basic_map_name(typ): - pass - elif typ == 'array': - return gen_arr_typnode(node_info, src, typ, refname) - elif typ == 'object' or typ == 'mapStringObject': - return gen_obj_typnode(node_info, src, typ, refname) - elif typ == 'ArrayOfStrings': - typ = 'array' - subtyp = 'string' - children = subtypobj = None - else: - if not judge_support_type(typ): - raise RuntimeError("Invalid schema type: %s" % typ) - children = None - - return helpers.Unite(name, - typ, - children, - subtyp=subtyp, - subtypobj=subtypobj, - subtypname=refname, - required=required), src - - -def resolve_list(schema_info, name, schema, objs, curfile): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - obj = [] - index = 0 - for i in objs: - generated_name = helpers.CombinateName( \ - i['$ref'].split("/")[-1]) if '$ref' in i \ - else helpers.CombinateName(name.name + str(index)) - node, _ = resolve_type(schema_info, generated_name, schema, i, curfile) - if node: - obj.append(node) - index += 1 - if not obj: - obj = None - return obj - - -def parse_dict(schema_info, name, schema, objs, curfile): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - obj = [] - for i in objs: - node, _ = resolve_type(schema_info, name.append(i), schema, objs[i], curfile) - if node: - obj.append(node) - if not obj: - obj = None - return obj - - -def parse_properties(schema_info, name, schema, props, curfile): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - if 'definitions' in props: - return parse_dict(schema_info, name, schema, props['definitions'], curfile) - if 'patternProperties' in props: - return parse_dict(schema_info, name, schema, props['patternProperties'], curfile) - return parse_dict(schema_info, name, schema, props['properties'], curfile) - - -def handle_type_not_in_schema(schema_info, schema, prefix): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - required = None - if 'definitions' in schema: - return helpers.Unite( \ - helpers.CombinateName("definitions"), 'definitions', \ - parse_properties(schema_info, helpers.CombinateName(""), schema, schema, \ - schema_info.name.name), None, None, None, None) - else: - if len(schema) > 1: - print('More than one element found in schema') - return None - value_nodes = [] - for value in schema: - if 'required' in schema[value]: - required = schema[value]['required'] - childrens = parse_properties(schema_info, helpers.CombinateName(""), \ - schema[value], schema[value], \ - schema_info.name.name) - value_node = helpers.Unite(helpers.CombinateName(prefix), \ - 'object', childrens, None, None, \ - None, required) - value_nodes.append(value_node) - return helpers.Unite(helpers.CombinateName("definitions"), \ - 'definitions', value_nodes, None, None, \ - None, None) - - -def parse_schema(schema_info, schema, prefix): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - required = None - if 'type' not in schema: - return handle_type_not_in_schema(schema_info, schema, prefix) - - if 'object' in schema['type']: - if 'required' in schema: - required = schema['required'] - return helpers.Unite( - helpers.CombinateName(prefix), 'object', - parse_properties(schema_info, \ - helpers.CombinateName(""), \ - schema, schema, schema_info.name.name), \ - None, None, None, required) - elif 'array' in schema['type']: - item_type, _ = resolve_type(schema_info, helpers.CombinateName(""), \ - schema['items'], schema['items'], schema_info.name.name) - return helpers.Unite(helpers.CombinateName(prefix), 'array', None, item_type.typ, \ - item_type.children, None, item_type.required) - else: - print("Not supported type '%s'") % schema['type'] - return prefix, None - - -def expand(tree, structs, visited): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - if tree.children is not None: - for i in tree.children: - if tree.subtypname: - i.subtypname = "from_ref" - expand(i, structs, visited=visited) - if tree.subtypobj is not None: - for i in tree.subtypobj: - expand(i, structs, visited=visited) - - if tree.typ == 'array' and helpers.valid_basic_map_name(tree.subtyp): - name = helpers.CombinateName(tree.name + "_element") - node = helpers.Unite(name, tree.subtyp, None) - expand(node, structs, visited) - - id_ = "%s:%s" % (tree.name, tree.typ) - if id_ not in visited.keys(): - structs.append(tree) - visited[id_] = tree - - return structs - - -def reflection(schema_info, gen_ref): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - with open(schema_info.header.name, "w") as \ - header_file, open(schema_info.source.name, "w") as source_file: - fcntl.flock(header_file, fcntl.LOCK_EX) - fcntl.flock(source_file, fcntl.LOCK_EX) - - with open(schema_info.name.name) as schema_file: - schema_json = json.loads(schema_file.read(), object_pairs_hook=OrderedDict) - try: - tree = parse_schema(schema_info, schema_json, schema_info.prefix) - if tree is None: - print("Failed parse schema") - sys.exit(1) - structs = expand(tree, [], {}) - headers.header_reflect(structs, schema_info, header_file) - sources.src_reflect(structs, schema_info, source_file, tree.typ) - except RuntimeError: - traceback.print_exc() - print("Failed to parse schema file: %s") % schema_info.name.name - sys.exit(1) - finally: - pass - - fcntl.flock(source_file, fcntl.LOCK_UN) - fcntl.flock(header_file, fcntl.LOCK_UN) - - if gen_ref is True: - if schema_info.refs: - for reffile in schema_info.refs.values(): - reflection(reffile, True) - - -def gen_common_files(out): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - print(out, " gao\n") - with open(os.path.join(out, 'json_common.h'), "w") as \ - header_file, open(os.path.join(out, 'json_common.c'), "w") as source_file: - fcntl.flock(header_file, fcntl.LOCK_EX) - fcntl.flock(source_file, fcntl.LOCK_EX) - - header_file.write(common_h.CODE) - source_file.write(common_c.CODE) - - fcntl.flock(source_file, fcntl.LOCK_UN) - fcntl.flock(header_file, fcntl.LOCK_UN) - - -def handle_single_file(args, srcpath, gen_ref, schemapath): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - if not os.path.exists(schemapath.name) or not os.path.exists(srcpath.name): - print('Path %s is not exist') % schemapath.name - sys.exit(1) - - if os.path.isdir(schemapath.name): - if args.recursive is True: - # recursively parse schema - for dirpath, dummy_dirnames, files in os.walk(schemapath.name): - for target_file in files: - if target_file.endswith(JSON_SUFFIX): - schema_info = schema_from_file(os.path.join(dirpath, target_file), \ - srcpath.name) - reflection(schema_info, gen_ref) - else: - # only parse files in current direcotory - for target_file in os.listdir(schemapath.name): - fullpath = os.path.join(schemapath.name, target_file) - if fullpath.endswith(JSON_SUFFIX) and os.path.isfile(fullpath): - schema_info = schema_from_file(fullpath, srcpath.name) - reflection(schema_info, gen_ref) - else: - if schemapath.name.endswith(JSON_SUFFIX): - schema_info = schema_from_file(schemapath.name, srcpath.name) - reflection(schema_info, gen_ref) - else: - print('File %s is not ends with .json') % schemapath.name - - -def handle_files(args, srcpath): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - for path in args.path: - gen_ref = args.gen_ref - schemapath = helpers.FilePath(path) - handle_single_file(args, srcpath, gen_ref, schemapath) - - -def main(): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - parser = argparse.ArgumentParser(prog='generate.py', - usage='%(prog)s [options] path [path ...]', - description='Generate C header and source from json-schema') - parser.add_argument('path', nargs='+', help='File or directory to parse') - parser.add_argument( - '--root', - required=True, - help= - 'All schema files must be placed in root directory or sub-directory of root," \ - " and naming of C variables is started from this path' - ) - parser.add_argument('--gen-common', - action='store_true', - help='Generate json_common.c and json_common.h') - parser.add_argument('--gen-ref', - action='store_true', - help='Generate reference file defined in schema with key \"$ref\"') - parser.add_argument('-r', - '--recursive', - action='store_true', - help='Recursively generate all schema files in directory') - parser.add_argument( - '--out', - help='Specify a directory to save C header and source(default is current directory)') - args = parser.parse_args() - - if not args.root: - print('Missing root path, see help') - sys.exit(1) - - root_path = os.path.realpath(args.root) - if not os.path.exists(root_path): - print('Root %s is not exist') % args.root - sys.exit(1) - - MyRoot.root_path = root_path - - if args.out: - srcpath = helpers.FilePath(args.out) - else: - srcpath = helpers.FilePath(os.getcwd()) - if not os.path.exists(srcpath.name): - os.makedirs(srcpath.name) - - if args.gen_common: - gen_common_files(srcpath.name) - handle_files(args, srcpath) - - -if __name__ == "__main__": - main() - - diff --git a/src/json/schema/src/headers.py b/src/json/schema/src/headers.py deleted file mode 100644 index e35d24c..0000000 --- a/src/json/schema/src/headers.py +++ /dev/null @@ -1,220 +0,0 @@ -# -*- coding: utf-8 -*- -''' -Description: header class and functions -Interface: None -History: 2019-06-17 -''' -# -# libocispec - a C library for parsing OCI spec files. -# -# Copyright (C) 2017, 2019 Giuseppe Scrivano -# Copyright (C) Huawei Technologies., Ltd. 2018-2019. All rights reserved. -# -# libocispec is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# libocispec 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with libocispec. If not, see . -# -# As a special exception, you may create a larger work that contains -# part or all of the libocispec parser skeleton and distribute that work -# under terms of your choice, so long as that work isn't itself a -# parser generator using the skeleton or a modified version thereof -# as a parser skeleton. Alternatively, if you modify or redistribute -# the parser skeleton itself, you may (at your option) remove this -# special exception, which will cause the skeleton and the resulting -# libocispec output files to be licensed under the GNU General Public -# License without this special exception. -# -#!/usr/bin/python -Es -import helpers - -def append_header_arr(obj, header, prefix): - ''' - Description: Write c header file of array - Interface: None - History: 2019-06-17 - ''' - if not obj.subtypobj or obj.subtypname: - return - header.write("typedef struct {\n") - for i in obj.subtypobj: - if i.typ == 'array': - c_typ = helpers.get_prefixe_pointer(i.name, i.subtyp, prefix) or \ - helpers.get_map_c_types(i.subtyp) - if i.subtypobj is not None: - c_typ = helpers.get_name_substr(i.name, prefix) - - if not helpers.judge_complex(i.subtyp): - header.write(" %s%s*%s;\n" % (c_typ, " " if '*' not in c_typ else "", \ - i.fixname)) - else: - header.write(" %s **%s;\n" % (c_typ, i.fixname)) - header.write(" size_t %s;\n\n" % (i.fixname + "_len")) - else: - c_typ = helpers.get_prefixe_pointer(i.name, i.typ, prefix) or \ - helpers.get_map_c_types(i.typ) - header.write(" %s%s%s;\n" % (c_typ, " " if '*' not in c_typ else "", i.fixname)) - typename = helpers.get_name_substr(obj.name, prefix) - header.write("}\n%s;\n\n" % typename) - header.write("void free_%s(%s *ptr);\n\n" % (typename, typename)) - header.write("%s *make_%s(yajl_val tree, const struct parser_context *ctx, parser_error *err);"\ - "\n\n" % (typename, typename)) - - -def append_header_map_str_obj(obj, header, prefix): - ''' - Description: Write c header file of mapStringObject - Interface: None - History: 2019-06-17 - ''' - child = obj.children[0] - header.write("typedef struct {\n") - header.write(" char **keys;\n") - if helpers.valid_basic_map_name(child.typ): - c_typ = helpers.get_prefixe_pointer("", child.typ, "") - elif child.subtypname: - c_typ = child.subtypname - else: - c_typ = helpers.get_prefixe_pointer(child.name, child.typ, prefix) - header.write(" %s%s*%s;\n" % (c_typ, " " if '*' not in c_typ else "", child.fixname)) - header.write(" size_t len;\n") - - -def append_header_child_arr(child, header, prefix): - ''' - Description: Write c header file of array of child - Interface: None - History: 2019-06-17 - ''' - if helpers.get_map_c_types(child.subtyp) != "": - c_typ = helpers.get_map_c_types(child.subtyp) - elif helpers.valid_basic_map_name(child.subtyp): - c_typ = '%s *' % helpers.make_basic_map_name(child.subtyp) - elif child.subtypname is not None: - c_typ = child.subtypname - elif child.subtypobj is not None: - c_typ = helpers.get_name_substr(child.name, prefix) - else: - c_typ = helpers.get_prefixe_pointer(child.name, child.subtyp, prefix) - - if helpers.valid_basic_map_name(child.subtyp): - header.write(" %s **%s;\n" % (helpers.make_basic_map_name(child.subtyp), child.fixname)) - elif not helpers.judge_complex(child.subtyp): - header.write(" %s%s*%s;\n" % (c_typ, " " if '*' not in c_typ else "", child.fixname)) - else: - header.write(" %s%s**%s;\n" % (c_typ, " " if '*' not in c_typ else "", child.fixname)) - header.write(" size_t %s;\n\n" % (child.fixname + "_len")) - - -def append_header_child_others(child, header, prefix): - ''' - Description: Write c header file of others of child - Interface: None - History: 2019-06-17 - ''' - if helpers.get_map_c_types(child.typ) != "": - c_typ = helpers.get_map_c_types(child.typ) - elif helpers.valid_basic_map_name(child.typ): - c_typ = '%s *' % helpers.make_basic_map_name(child.typ) - elif child.subtypname: - c_typ = helpers.get_prefixe_pointer(child.subtypname, child.typ, "") - else: - c_typ = helpers.get_prefixe_pointer(child.name, child.typ, prefix) - header.write(" %s%s%s;\n\n" % (c_typ, " " if '*' not in c_typ else "", child.fixname)) - - -def append_type_c_header(obj, header, prefix): - ''' - Description: Write c header file - Interface: None - History: 2019-06-17 - ''' - if not helpers.judge_complex(obj.typ): - return - - if obj.typ == 'array': - append_header_arr(obj, header, prefix) - return - - if obj.typ == 'mapStringObject': - if obj.subtypname is not None: - return - append_header_map_str_obj(obj, header, prefix) - elif obj.typ == 'object': - if obj.subtypname is not None: - return - header.write("typedef struct {\n") - if obj.children is None: - header.write(" char unuseful; // unuseful definition to avoid empty struct\n") - for i in obj.children or []: - if i.typ == 'array': - append_header_child_arr(i, header, prefix) - else: - append_header_child_others(i, header, prefix) - - typename = helpers.get_prefixe_name(obj.name, prefix) - header.write("}\n%s;\n\n" % typename) - header.write("void free_%s(%s *ptr);\n\n" % (typename, typename)) - header.write("%s *make_%s(yajl_val tree, const struct parser_context *ctx, parser_error *err)"\ - ";\n\n" % (typename, typename)) - header.write("yajl_gen_status gen_%s(yajl_gen g, const %s *ptr, const struct parser_context "\ - "*ctx, parser_error *err);\n\n" % (typename, typename)) - - -def header_reflect(structs, schema_info, header): - ''' - Description: Reflection header files - Interface: None - History: 2019-06-17 - ''' - prefix = schema_info.prefix - header.write("// Generated from %s. Do not edit!\n" % (schema_info.name.basename)) - header.write("#ifndef %s_SCHEMA_H\n" % prefix.upper()) - header.write("#define %s_SCHEMA_H\n\n" % prefix.upper()) - header.write("#include \n") - header.write("#include \n") - header.write("#include \"json_common.h\"\n") - if schema_info.refs: - for ref in schema_info.refs.keys(): - header.write("#include \"%s\"\n" % (ref)) - header.write("\n#ifdef __cplusplus\n") - header.write("extern \"C\" {\n") - header.write("#endif\n\n") - - for i in structs: - append_type_c_header(i, header, prefix) - length = len(structs) - toptype = structs[length - 1].typ if length != 0 else "" - if toptype == 'object': - header.write("%s *%s_parse_file(const char *filename, const struct parser_context *ctx, "\ - "parser_error *err);\n\n" % (prefix, prefix)) - header.write("%s *%s_parse_file_stream(FILE *stream, const struct parser_context *ctx, "\ - "parser_error *err);\n\n" % (prefix, prefix)) - header.write("%s *%s_parse_data(const char *jsondata, const struct parser_context *ctx, "\ - "parser_error *err);\n\n" % (prefix, prefix)) - header.write("char *%s_generate_json(const %s *ptr, const struct parser_context *ctx, "\ - "parser_error *err);\n\n" % (prefix, prefix)) - elif toptype == 'array': - header.write("void free_%s(%s_element **ptr, size_t len);\n\n" % (prefix, prefix)) - header.write("%s_element **%s_parse_file(const char *filename, const struct "\ - "parser_context *ctx, parser_error *err, size_t *len);\n\n" % (prefix, prefix)) - header.write("%s_element **%s_parse_file_stream(FILE *stream, const struct "\ - "parser_context *ctx, parser_error *err, size_t *len);\n\n" % (prefix, prefix)) - header.write("%s_element **%s_parse_data(const char *jsondata, const struct "\ - "parser_context *ctx, parser_error *err, size_t *len);\n\n" % (prefix, prefix)) - header.write("char *%s_generate_json(const %s_element **ptr, size_t len, "\ - "const struct parser_context *ctx, parser_error *err);\n\n" % (prefix, prefix)) - - header.write("#ifdef __cplusplus\n") - header.write("}\n") - header.write("#endif\n\n") - header.write("#endif\n\n") - diff --git a/src/json/schema/src/helpers.py b/src/json/schema/src/helpers.py deleted file mode 100644 index cb344c6..0000000 --- a/src/json/schema/src/helpers.py +++ /dev/null @@ -1,333 +0,0 @@ -# -*- coding: utf-8 -*- -''' -Description: helper class and functions -Interface: None -History: 2019-06-17 -''' -# -# libocispec - a C library for parsing OCI spec files. -# -# Copyright (C) 2017, 2019 Giuseppe Scrivano -# Copyright (C) Huawei Technologies., Ltd. 2018-2019. All rights reserved. -# -# libocispec is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# libocispec 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with libocispec. If not, see . -# -# As a special exception, you may create a larger work that contains -# part or all of the libocispec parser skeleton and distribute that work -# under terms of your choice, so long as that work isn't itself a -# parser generator using the skeleton or a modified version thereof -# as a parser skeleton. Alternatively, if you modify or redistribute -# the parser skeleton itself, you may (at your option) remove this -# special exception, which will cause the skeleton and the resulting -# libocispec output files to be licensed under the GNU General Public -# License without this special exception. -#!/usr/bin/python -Es -import os -import sys - -def append_separator(substr): - ''' - Description: append only '_' at last position of subStr - Interface: None - History: 2019-09-20 - ''' - if substr and substr[-1] != '_': - substr.append('_') - -def conv_to_c_style(name): - ''' - Description: convert name to linux c format - Interface: None - History: 2019-06-17 - ''' - if name is None or name == "": - return "" - name = name.replace('.', '_').replace('-', '_').replace('/', '_') - substr = [] - preindex = 0 - index = 0 - for index, char in enumerate(name): - if char == '_': - append_separator(substr) - substr.append(name[preindex:index].lower()) - preindex = index + 1 - if not char.isupper() and name[preindex].isupper() and \ - name[preindex + 1].isupper(): - append_separator(substr) - substr.append(name[preindex:index - 1].lower()) - preindex = index - 1 - continue - if char.isupper() and index > 0 and name[index - 1].islower(): - append_separator(substr) - substr.append(name[preindex:index].lower()) - preindex = index - - if preindex <= index and index >= 0 and name[index] != '_' and \ - preindex != 0: - append_separator(substr) - substr.append(name[preindex:index + 1].lower()) - result = ''.join(substr) - return result - -def get_map_c_types(typ): - ''' - Description: Get map c types - Interface: None - History: 2019-06-17 - ''' - map_c_types = { - 'byte': 'uint8_t', - 'string': 'char *', - 'integer': 'int', - 'boolean': 'bool', - 'double': 'double', - 'int8': 'int8_t', - "int16": 'int16_t', - "int32": "int32_t", - "int64": "int64_t", - 'uint8': 'uint8_t', - "uint16": 'uint16_t', - "uint32": "uint32_t", - "uint64": "uint64_t", - "UID": "uid_t", - "GID": "gid_t", - "booleanPointer": "bool *", - 'bytePointer': 'uint8_t *', - 'integerPointer': 'int *', - 'doublePointer': 'double *', - 'int8Pointer': 'int8_t *', - "int16Pointer": 'int16_t *', - "int32Pointer": "int32_t *", - "int64Pointer": "int64_t *", - 'uint8Pointer': 'uint8_t *', - "uint16Pointer": 'uint16_t *', - "uint32Pointer": "uint32_t *", - "uint64Pointer": "uint64_t *", - } - if typ in map_c_types: - return map_c_types[typ] - return "" - -def valid_basic_map_name(typ): - ''' - Description: Valid basic map name - Interface: None - History: 2019-06-17 - ''' - return typ != 'mapStringObject' and hasattr(typ, 'startswith') and \ - typ.startswith('map') - -def make_basic_map_name(mapname): - ''' - Description: Make basic map name - Interface: None - History: 2019-06-17 - ''' - basic_map_types = ('string', 'int', 'bool') - parts = conv_to_c_style(mapname).split('_') - if len(parts) != 3 or parts[0] != 'map' or \ - (parts[1] not in basic_map_types) or \ - (parts[2] not in basic_map_types): - print('Invalid map name: %s') % mapname - sys.exit(1) - return "json_map_%s_%s" % (parts[1], parts[2]) - - -def get_name_substr(name, prefix): - ''' - Description: Make array name - Interface: None - History: 2019-06-17 - ''' - return "%s_element" % prefix if name is None or name == "" or prefix == name \ - else "%s_%s_element" % (prefix, name) - -def get_prefixe_name(name, prefix): - ''' - Description: Make name - Interface: None - History: 2019-06-17 - ''' - if name is None or name == "" or prefix.endswith(name): - return "%s" % prefix - if prefix is None or prefix == "" or prefix == name or name.endswith(prefix): - return "%s" % name - return "%s_%s" % (prefix, name) - -def get_prefixe_pointer(name, typ, prefix): - ''' - Description: Make pointer name - Interface: None - History: 2019-06-17 - ''' - if typ != 'object' and typ != 'mapStringObject' and \ - not valid_basic_map_name(typ): - return "" - return '%s *' % make_basic_map_name(typ) if valid_basic_map_name(typ) \ - else "%s *" % get_prefixe_name(name, prefix) - -def judge_complex(typ): - ''' - Description: Check compound object - Interface: None - History: 2019-06-17 - ''' - return typ in ('object', 'array', 'mapStringObject') - -def judge_data_type(typ): - ''' - Description: Check numeric type - Interface: None - History: 2019-06-17 - ''' - if (typ.startswith("int") or typ.startswith("uint")) and \ - "Pointer" not in typ: - return True - return typ in ("integer", "UID", "GID", "double") - -def judge_data_pointer_type(typ): - ''' - Description: Check numeric pointer type - Interface: None - History: 2019-06-17 - ''' - if (typ.startswith("int") or typ.startswith("uint")) and "Pointer" in typ: - return True - return False - -def obtain_data_pointer_type(typ): - ''' - Description: Get numeric pointer type - Interface: None - History: 2019-06-17 - ''' - index = typ.find("Pointer") - return typ[0:index] if index != -1 else "" - -def obtain_pointer(name, typ, prefix): - ''' - Description: Obtain pointer string - Interface: None - History: 2019-06-17 - ''' - ptr = get_prefixe_pointer(name, typ, prefix) - if ptr != "": - return ptr - - return "char *" if typ == "string" else \ - ("%s *" % typ if typ == "ArrayOfStrings" else "") - -class CombinateName(object): - ''' - Description: Store CombinateName information - Interface: None - History: 2019-06-17 - ''' - - def __init__(self, name, leaf=None): - self.name = name - self.leaf = leaf - - def __repr__(self): - return self.name - - def __str__(self): - return self.name - - def append(self, leaf): - ''' - Description: append name - Interface: None - History: 2019-06-17 - ''' - prefix_name = self.name + '_' if self.name != "" else "" - return CombinateName(prefix_name + leaf, leaf) - - -class Unite(object): - ''' - Description: Store Unite information - Interface: None - History: 2019-06-17 - ''' - def __init__(self, name, typ, children, subtyp=None, subtypobj=None, subtypname=None, \ - required=None): - self.typ = typ - self.children = children - self.subtyp = subtyp - self.subtypobj = subtypobj - self.subtypname = subtypname - self.required = required - self.name = conv_to_c_style(name.name.replace('.', '_')) - self.origname = name.leaf or name.name - self.fixname = conv_to_c_style(self.origname.replace('.', '_')) - - - - def __repr__(self): - if self.subtyp is not None: - return "name:(%s) type:(%s -> %s)" \ - % (self.name, self.typ, self.subtyp) - return "name:(%s) type:(%s)" % (self.name, self.typ) - - def __str__(self): - return self.__repr__(self) - - -class FilePath(object): - ''' - Description: Store filepath information - Interface: None - History: 2019-06-17 - ''' - def __init__(self, name): - self.name = os.path.realpath(name) - self.dirname = os.path.dirname(self.name) - self.basename = os.path.basename(self.name) - - def __repr__(self): - return "{name:(%s) dirname:(%s) basename:(%s)}" \ - % (self.name, self.dirname, self.basename) - - def __str__(self): - return self.__repr__(self) - - -class SchemaInfo(object): - ''' - Description: Store schema information - Interface: None - History: 2019-06-17 - ''' - - def __init__(self, name, header, source, prefix, filesdir, refs=None): - self.name = name - self.fileprefix = conv_to_c_style( \ - name.basename.replace('.', '_').replace('-', '_')) - self.header = header - self.source = source - self.prefix = prefix - self.refs = refs - self.filesdir = os.path.realpath(filesdir) - - def __repr__(self): - return "{name:(%s) header:(%s) source:(%s) prefix:(%s)}" \ - % (self.name, self.header, self.source, self.prefix) - - def __str__(self): - return self.__repr__(self) - - - - diff --git a/src/json/schema/src/read_file.c b/src/json/schema/src/read_file.c deleted file mode 100644 index 08b9059..0000000 --- a/src/json/schema/src/read_file.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - Copyright 2017 Giuseppe Scrivano - Copyright (C) Huawei Technologies., Ltd. 2018-2019. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "read_file.h" - -#ifndef O_CLOEXEC -#define O_CLOEXEC 02000000 -#endif - -#define JSON_MAX_SIZE (10LL * 1024LL * 1024LL) -#define FILE_MODE 0640 - -static int do_check_fread_args(const FILE *stream, const size_t *length) -{ - if (stream == NULL) { - return -1; - } - if (length == NULL) { - return -1; - } - - return 0; -} - -char *fread_file(FILE *stream, size_t *length) -{ - char *buf = NULL; - char *tmpbuf = NULL; - size_t off = 0; - - if (do_check_fread_args(stream, length) != 0) { - return NULL; - } - - while (1) { - size_t ret, newsize, sizejudge; - sizejudge = (JSON_MAX_SIZE - BUFSIZ) - 1; - if (sizejudge < off) { - goto out; - } - newsize = off + BUFSIZ + 1; - - tmpbuf = (char *)calloc(1, newsize); - if (tmpbuf == NULL) { - goto out; - } - - if (buf != NULL) { - (void)memcpy(tmpbuf, buf, off); - - (void)memset(buf, 0, off); - - free(buf); - } - - buf = tmpbuf; - tmpbuf = NULL; - - ret = fread(buf + off, 1, BUFSIZ, stream); - if (ret == 0 && ferror(stream)) { - goto out; - } - if (ret < BUFSIZ || feof(stream)) { - *length = off + ret + 1; - buf[*length - 1] = '\0'; - return buf; - } - - off += BUFSIZ; - } -out: - free(buf); - free(tmpbuf); - return NULL; -} - -static int do_check_args(const char *path, const size_t *length) -{ - if (path == NULL || length == NULL) { - return -1; - } - if (strlen(path) > PATH_MAX) { - return -1; - } - return 0; -} - -char *read_file(const char *path, size_t *length) -{ - char *buf = NULL; - char rpath[PATH_MAX + 1] = { 0 }; - int fd = -1; - int tmperrno = -1; - FILE *fp = NULL; - - if (do_check_args(path, length) != 0) { - return NULL; - } - - if (realpath(path, rpath) == NULL) { - return NULL; - } - - fd = open(rpath, O_RDONLY | O_CLOEXEC, FILE_MODE); - if (fd < 0) { - return NULL; - } - - fp = fdopen(fd, "r"); - tmperrno = errno; - if (fp == NULL) { - (void)close(fd); - errno = tmperrno; - return NULL; - } - - buf = fread_file(fp, length); - (void)fclose(fp); - return buf; -} diff --git a/src/json/schema/src/read_file.h b/src/json/schema/src/read_file.h deleted file mode 100644 index 4edc585..0000000 --- a/src/json/schema/src/read_file.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - Copyright 2017 Giuseppe Scrivano - Copyright (C) Huawei Technologies., Ltd. 2018-2019. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -#ifndef __JSON_READ_FILE_H_ -#define __JSON_READ_FILE_H_ - -#include -#include - -char *fread_file(FILE *stream, size_t *length); - -char *read_file(const char *path, size_t *length); - -#endif diff --git a/src/json/schema/src/sources.py b/src/json/schema/src/sources.py deleted file mode 100644 index 3b5d9a1..0000000 --- a/src/json/schema/src/sources.py +++ /dev/null @@ -1,1008 +0,0 @@ -# -*- coding: utf-8 -*- -#!/usr/bin/python -Es -# -# libocispec - a C library for parsing OCI spec files. -# -# Copyright (C) 2017, 2019 Giuseppe Scrivano -# Copyright (C) Huawei Technologies., Ltd. 2018-2019. All rights reserved. -# -# libocispec is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# libocispec 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with libocispec. If not, see . -# -# As a special exception, you may create a larger work that contains -# part or all of the libocispec parser skeleton and distribute that work -# under terms of your choice, so long as that work isn't itself a -# parser generator using the skeleton or a modified version thereof -# as a parser skeleton. Alternatively, if you modify or redistribute -# the parser skeleton itself, you may (at your option) remove this -# special exception, which will cause the skeleton and the resulting -# libocispec output files to be licensed under the GNU General Public -# License without this special exception. -import helpers - - -def append_c_code(obj, c_file, prefix): - """ - Description: append c language code to file - Interface: None - History: 2019-06-17 - """ - parse_json_to_c(obj, c_file, prefix) - make_c_free(obj, c_file, prefix) - get_c_json(obj, c_file, prefix) - - -def parse_map_string_obj(obj, c_file, prefix, obj_typename): - """ - Description: generate c language for parse json map string object - Interface: None - History: 2019-06-17 - """ - child = obj.children[0] - if helpers.valid_basic_map_name(child.typ): - childname = helpers.make_basic_map_name(child.typ) - else: - if child.subtypname: - childname = child.subtypname - else: - childname = helpers.get_prefixe_name(child.name, prefix) - c_file.write(' if (YAJL_GET_OBJECT(tree) != NULL && YAJL_GET_OBJECT(tree)->len > 0) {\n') - c_file.write(' size_t i;\n') - c_file.write(' ret->len = YAJL_GET_OBJECT(tree)->len;\n') - c_file.write(' ret->keys = safe_malloc((YAJL_GET_OBJECT(tree)->len + 1) ' \ - '* sizeof(*ret->keys));\n') - c_file.write(' ret->%s = safe_malloc((YAJL_GET_OBJECT(tree)->len + 1) ' \ - '* sizeof(*ret->%s));\n' % (child.fixname, child.fixname)) - c_file.write(' for (i = 0; i < YAJL_GET_OBJECT(tree)->len; i++) {\n') - c_file.write(' const char *tmpkey = YAJL_GET_OBJECT(tree)->keys[i];\n') - c_file.write(' ret->keys[i] = safe_strdup(tmpkey ? tmpkey : "");\n') - c_file.write(' yajl_val val = YAJL_GET_OBJECT(tree)->values[i];\n') - c_file.write(' ret->%s[i] = make_%s(val, ctx, err);\n' \ - % (child.fixname, childname)) - c_file.write(' if (ret->%s[i] == NULL) {\n' % (child.fixname)) - c_file.write(" free_%s(ret);\n" % obj_typename) - c_file.write(" return NULL;\n") - c_file.write(' }\n') - c_file.write(' }\n') - c_file.write(' }\n') - - -def parse_obj_type(obj, c_file, prefix, obj_typename): - """ - Description: generate c language for parse object type - Interface: None - History: 2019-06-17 - """ - if obj.typ == 'string': - c_file.write(' {\n') - read_val_generator(c_file, 2, 'get_val(tree, "%s", yajl_t_string)' % obj.origname, \ - "ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename) - c_file.write(' }\n') - elif helpers.judge_data_type(obj.typ): - c_file.write(' {\n') - read_val_generator(c_file, 2, 'get_val(tree, "%s", yajl_t_number)' % obj.origname, \ - "ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename) - c_file.write(' }\n') - elif helpers.judge_data_pointer_type(obj.typ): - c_file.write(' {\n') - read_val_generator(c_file, 2, 'get_val(tree, "%s", yajl_t_number)' % obj.origname, \ - "ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename) - c_file.write(' }\n') - if obj.typ == 'boolean': - c_file.write(' {\n') - read_val_generator(c_file, 2, 'get_val(tree, "%s", yajl_t_true)' % obj.origname, \ - "ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename) - c_file.write(' }\n') - if obj.typ == 'booleanPointer': - c_file.write(' {\n') - read_val_generator(c_file, 2, 'get_val(tree, "%s", yajl_t_true)' % obj.origname, \ - "ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename) - c_file.write(' }\n') - elif obj.typ == 'object' or obj.typ == 'mapStringObject': - if obj.subtypname is not None: - typename = obj.subtypname - else: - typename = helpers.get_prefixe_name(obj.name, prefix) - c_file.write( - ' ret->%s = make_%s(get_val(tree, "%s", yajl_t_object), ctx, err);\n' \ - % (obj.fixname, typename, obj.origname)) - c_file.write(" if (ret->%s == NULL && *err != 0) {\n" % obj.fixname) - c_file.write(" free_%s(ret);\n" % obj_typename) - c_file.write(" return NULL;\n") - c_file.write(" }\n") - elif obj.typ == 'array' and (obj.subtypobj or obj.subtyp == 'object'): - if obj.subtypname: - typename = obj.subtypname - else: - typename = helpers.get_name_substr(obj.name, prefix) - c_file.write(' {\n') - c_file.write(' yajl_val tmp = get_val(tree, "%s", yajl_t_array);\n' \ - % (obj.origname)) - c_file.write(' if (tmp != NULL && YAJL_GET_ARRAY(tmp) != NULL &&' \ - ' YAJL_GET_ARRAY(tmp)->len > 0) {\n') - c_file.write(' size_t i;\n') - c_file.write(' ret->%s_len = YAJL_GET_ARRAY(tmp)->len;\n' % (obj.fixname)) - c_file.write(' ret->%s = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) ' \ - '* sizeof(*ret->%s));\n' % (obj.fixname, obj.fixname)) - c_file.write(' for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) {\n') - c_file.write(' yajl_val val = YAJL_GET_ARRAY(tmp)->values[i];\n') - c_file.write(' ret->%s[i] = make_%s(val, ctx, err);\n' \ - % (obj.fixname, typename)) - c_file.write(' if (ret->%s[i] == NULL) {\n' % (obj.fixname)) - c_file.write(" free_%s(ret);\n" % obj_typename) - c_file.write(" return NULL;\n") - c_file.write(' }\n') - c_file.write(' }\n') - c_file.write(' }\n') - c_file.write(' }\n') - elif obj.typ == 'array' and obj.subtyp == 'byte': - c_file.write(' {\n') - c_file.write(' yajl_val tmp = get_val(tree, "%s", yajl_t_string);\n' \ - % (obj.origname)) - c_file.write(' if (tmp != NULL) {\n') - c_file.write(' char *str = YAJL_GET_STRING(tmp);\n') - c_file.write(' ret->%s = (uint8_t *)safe_strdup(str ? str : "");\n' \ - % obj.fixname) - c_file.write(' ret->%s_len = str != NULL ? strlen(str) : 0;\n' \ - % obj.fixname) - c_file.write(' }\n') - c_file.write(' }\n') - elif obj.typ == 'array': - c_file.write(' {\n') - c_file.write(' yajl_val tmp = get_val(tree, "%s", yajl_t_array);\n' \ - % (obj.origname)) - c_file.write(' if (tmp != NULL && YAJL_GET_ARRAY(tmp) != NULL &&' \ - ' YAJL_GET_ARRAY(tmp)->len > 0) {\n') - c_file.write(' size_t i;\n') - c_file.write(' ret->%s_len = YAJL_GET_ARRAY(tmp)->len;\n' % (obj.fixname)) - c_file.write( - ' ret->%s = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) *' \ - ' sizeof(*ret->%s));\n' % (obj.fixname, obj.fixname)) - c_file.write(' for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) {\n') - read_val_generator(c_file, 4, 'YAJL_GET_ARRAY(tmp)->values[i]', \ - "ret->%s[i]" % obj.fixname, obj.subtyp, obj.origname, obj_typename) - c_file.write(' }\n') - c_file.write(' }\n') - c_file.write(' }\n') - elif helpers.valid_basic_map_name(obj.typ): - c_file.write(' {\n') - c_file.write(' yajl_val tmp = get_val(tree, "%s", yajl_t_object);\n' \ - % (obj.origname)) - c_file.write(' if (tmp != NULL) {\n') - c_file.write(' ret->%s = make_%s(tmp, ctx, err);\n' \ - % (obj.fixname, helpers.make_basic_map_name(obj.typ))) - c_file.write(' if (ret->%s == NULL) {\n' % (obj.fixname)) - c_file.write(' char *new_error = NULL;\n') - c_file.write(" if (asprintf(&new_error, \"Value error for key" \ - " '%s': %%s\", *err ? *err : \"null\") < 0) {\n" % (obj.origname)) - c_file.write(' new_error = safe_strdup(' \ - '"error allocating memory");\n') - c_file.write(' }\n') - c_file.write(' free(*err);\n') - c_file.write(' *err = new_error;\n') - c_file.write(' free_%s(ret);\n' % obj_typename) - c_file.write(' return NULL;\n') - c_file.write(' }\n') - c_file.write(' }\n') - c_file.write(' }\n') - -def parse_obj_arr_obj(obj, c_file, prefix, obj_typename): - """ - Description: generate c language for parse object or array object - Interface: None - History: 2019-06-17 - """ - nodes = obj.children if obj.typ == 'object' else obj.subtypobj - required_to_check = [] - for i in nodes or []: - if obj.required and i.origname in obj.required and \ - not helpers.judge_data_type(i.typ) and i.typ != 'boolean': - required_to_check.append(i) - parse_obj_type(i, c_file, prefix, obj_typename) - - for i in required_to_check: - c_file.write(' if (ret->%s == NULL) {\n' % i.fixname) - c_file.write(' if (asprintf(err, "Required field \'%%s\' not present", ' \ - ' "%s") < 0)\n' % i.origname) - c_file.write(' *err = safe_strdup("error allocating memory");\n') - c_file.write(" free_%s(ret);\n" % obj_typename) - c_file.write(" return NULL;\n") - c_file.write(' }\n') - - if obj.typ == 'object' and obj.children is not None: - # O(n^2) complexity, but the objects should not really be big... - condition = " &&\n ".join( \ - ['strcmp(tree->u.object.keys[i], "%s")' % i.origname for i in obj.children]) - c_file.write(""" - if (tree->type == yajl_t_object && (ctx->options & OPT_PARSE_STRICT)) { - size_t i; - for (i = 0; i < tree->u.object.len; i++) - if (%s) { - if (ctx->stderr > 0) - (void)fprintf(ctx->stderr, "WARNING: unknown key found: %%s\\n", - tree->u.object.keys[i]); - } - } -""" % condition) - - -def parse_json_to_c(obj, c_file, prefix): - """ - Description: generate c language for parse json file - Interface: None - History: 2019-06-17 - """ - if not helpers.judge_complex(obj.typ): - return - if obj.typ == 'object' or obj.typ == 'mapStringObject': - if obj.subtypname: - return - obj_typename = typename = helpers.get_prefixe_name(obj.name, prefix) - if obj.typ == 'array': - obj_typename = typename = helpers.get_name_substr(obj.name, prefix) - objs = obj.subtypobj - if objs is None or obj.subtypname: - return - c_file.write("%s *make_%s(yajl_val tree, const struct parser_context *ctx, "\ - "parser_error *err) {\n" % (typename, typename)) - c_file.write(" %s *ret = NULL;\n" % (typename)) - c_file.write(" *err = 0;\n") - c_file.write(" if (tree == NULL)\n") - c_file.write(" return ret;\n") - c_file.write(" ret = safe_malloc(sizeof(*ret));\n") - if obj.typ == 'mapStringObject': - parse_map_string_obj(obj, c_file, prefix, obj_typename) - - if obj.typ == 'object' or (obj.typ == 'array' and obj.subtypobj): - parse_obj_arr_obj(obj, c_file, prefix, obj_typename) - c_file.write(' return ret;\n') - c_file.write("}\n\n") - - -def get_map_string_obj(obj, c_file, prefix): - """ - Description: c language generate map string object - Interface: None - History: 2019-06-17 - """ - child = obj.children[0] - if helpers.valid_basic_map_name(child.typ): - childname = helpers.make_basic_map_name(child.typ) - else: - if child.subtypname: - childname = child.subtypname - else: - childname = helpers.get_prefixe_name(child.name, prefix) - c_file.write(' size_t len = 0, i;\n') - c_file.write(" if (ptr != NULL)\n") - c_file.write(" len = ptr->len;\n") - c_file.write(" if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n") - c_file.write(' yajl_gen_config(g, yajl_gen_beautify, 0);\n') - c_file.write(" stat = yajl_gen_map_open((yajl_gen)g);\n") - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(' if (len ||(ptr != NULL && ptr->keys != NULL && ptr->%s != NULL)) {\n' \ - % child.fixname) - c_file.write(' for (i = 0; i < len; i++) {\n') - c_file.write(' char *str = ptr->keys[i] ? ptr->keys[i] : "";\n') - c_file.write(' stat = yajl_gen_string((yajl_gen)g, \ - (const unsigned char *)str, strlen(str));\n') - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(' stat = gen_%s(g, ptr->%s[i], ctx, err);\n' \ - % (childname, child.fixname)) - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(' }\n') - c_file.write(' }\n') - c_file.write(" stat = yajl_gen_map_close((yajl_gen)g);\n") - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(" if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n") - c_file.write(' yajl_gen_config(g, yajl_gen_beautify, 1);\n') - - -def get_obj_arr_obj(obj, c_file, prefix): - """ - Description: c language generate object or array object - Interface: None - History: 2019-06-17 - """ - if obj.typ == 'string': - c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \ - ' (ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname) - c_file.write(' char *str = "";\n') - c_file.write(' stat = yajl_gen_string((yajl_gen)g, \ - (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname)) - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(" if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname) - c_file.write(" str = ptr->%s;\n" % obj.fixname) - c_file.write(" }\n") - json_value_generator(c_file, 2, "str", 'g', 'ctx', obj.typ) - c_file.write(" }\n") - elif helpers.judge_data_type(obj.typ): - c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \ - ' (ptr != NULL && ptr->%s)) {\n' % obj.fixname) - if obj.typ == 'double': - numtyp = 'double' - elif obj.typ.startswith("uint") or obj.typ == 'GID' or obj.typ == 'UID': - numtyp = 'long long unsigned int' - else: - numtyp = 'long long int' - c_file.write(' %s num = 0;\n' % numtyp) - c_file.write(' stat = yajl_gen_string((yajl_gen)g, \ - (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname)) - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(" if (ptr != NULL && ptr->%s) {\n" % obj.fixname) - c_file.write(" num = (%s)ptr->%s;\n" % (numtyp, obj.fixname)) - c_file.write(" }\n") - json_value_generator(c_file, 2, "num", 'g', 'ctx', obj.typ) - c_file.write(" }\n") - elif helpers.judge_data_pointer_type(obj.typ): - c_file.write(' if ((ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname) - numtyp = helpers.obtain_data_pointer_type(obj.typ) - if numtyp == "": - return - c_file.write(' %s num = 0;\n' % helpers.get_map_c_types(numtyp)) - c_file.write(' stat = yajl_gen_string((yajl_gen)g, \ - (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname)) - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(" if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname) - c_file.write(" num = (%s)*(ptr->%s);\n" \ - % (helpers.get_map_c_types(numtyp), obj.fixname)) - c_file.write(" }\n") - json_value_generator(c_file, 2, "num", 'g', 'ctx', numtyp) - c_file.write(" }\n") - elif obj.typ == 'boolean': - c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \ - ' (ptr != NULL && ptr->%s)) {\n' % obj.fixname) - c_file.write(' bool b = false;\n') - c_file.write(' stat = yajl_gen_string((yajl_gen)g, \ - (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname)) - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(" if (ptr != NULL && ptr->%s) {\n" % obj.fixname) - c_file.write(" b = ptr->%s;\n" % obj.fixname) - c_file.write(" }\n") - json_value_generator(c_file, 2, "b", 'g', 'ctx', obj.typ) - c_file.write(" }\n") - elif obj.typ == 'object' or obj.typ == 'mapStringObject': - if obj.subtypname: - typename = obj.subtypname - else: - typename = helpers.get_prefixe_name(obj.name, prefix) - c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \ - ' (ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname) - c_file.write(' stat = yajl_gen_string((yajl_gen)g, \ - (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname)) - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(' stat = gen_%s(g, ptr != NULL ? ptr->%s : NULL, ctx, err);\n' \ - % (typename, obj.fixname)) - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(" }\n") - elif obj.typ == 'array' and (obj.subtypobj or obj.subtyp == 'object'): - if obj.subtypname: - typename = obj.subtypname - else: - typename = helpers.get_name_substr(obj.name, prefix) - c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) || ' \ - '(ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname) - c_file.write(' size_t len = 0, i;\n') - c_file.write(' stat = yajl_gen_string((yajl_gen)g, \ - (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname)) - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(" if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname) - c_file.write(" len = ptr->%s_len;\n" % obj.fixname) - c_file.write(" }\n") - c_file.write(" if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n") - c_file.write(' yajl_gen_config(g, yajl_gen_beautify, 0);\n') - c_file.write(' stat = yajl_gen_array_open((yajl_gen)g);\n') - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(' for (i = 0; i < len; i++) {\n') - c_file.write(' stat = gen_%s(g, ptr->%s[i], ctx, err);\n' \ - % (typename, obj.fixname)) - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(' }\n') - c_file.write(' stat = yajl_gen_array_close((yajl_gen)g);\n') - c_file.write(" if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n") - c_file.write(' yajl_gen_config(g, yajl_gen_beautify, 1);\n') - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(' }\n') - elif obj.typ == 'array' and obj.subtyp == 'byte': - c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \ - ' (ptr != NULL && ptr->%s != NULL && ptr->%s_len)) {\n' \ - % (obj.fixname, obj.fixname)) - c_file.write(' const char *str = "";\n') - c_file.write(' size_t len = 0;\n') - c_file.write(' stat = yajl_gen_string((yajl_gen)g, \ - (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname)) - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(" if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname) - c_file.write(" str = (const char *)ptr->%s;\n" % obj.fixname) - c_file.write(" len = ptr->%s_len;\n" % obj.fixname) - c_file.write(" }\n") - c_file.write(' stat = yajl_gen_string((yajl_gen)g, \ - (const unsigned char *)str, len);\n') - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(" }\n") - elif obj.typ == 'array': - c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) || ' \ - '(ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname) - c_file.write(' size_t len = 0, i;\n') - c_file.write(' stat = yajl_gen_string((yajl_gen)g, \ - (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname)) - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(" if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname) - c_file.write(" len = ptr->%s_len;\n" % obj.fixname) - c_file.write(" }\n") - c_file.write(" if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n") - c_file.write(' yajl_gen_config(g, yajl_gen_beautify, 0);\n') - c_file.write(' stat = yajl_gen_array_open((yajl_gen)g);\n') - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(' for (i = 0; i < len; i++) {\n') - json_value_generator(c_file, 3, "ptr->%s[i]" % obj.fixname, 'g', 'ctx', obj.subtyp) - c_file.write(' }\n') - c_file.write(' stat = yajl_gen_array_close((yajl_gen)g);\n') - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(" if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n") - c_file.write(' yajl_gen_config(g, yajl_gen_beautify, 1);\n') - c_file.write(' }\n') - elif helpers.valid_basic_map_name(obj.typ): - c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) || ' \ - '(ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname) - c_file.write(' stat = yajl_gen_string((yajl_gen)g, \ - (const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname)) - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(' stat = gen_%s(g, ptr ? ptr->%s : NULL, ctx, err);\n' \ - % (helpers.make_basic_map_name(obj.typ), obj.fixname)) - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - c_file.write(" }\n") - - -def get_c_json(obj, c_file, prefix): - """ - Description: c language generate json file - Interface: None - History: 2019-06-17 - """ - if not helpers.judge_complex(obj.typ) or obj.subtypname: - return - if obj.typ == 'object' or obj.typ == 'mapStringObject': - typename = helpers.get_prefixe_name(obj.name, prefix) - elif obj.typ == 'array': - typename = helpers.get_name_substr(obj.name, prefix) - objs = obj.subtypobj - if objs is None: - return - c_file.write( - "yajl_gen_status gen_%s(yajl_gen g, const %s *ptr, const struct parser_context " \ - "*ctx, parser_error *err) {\n" % (typename, typename)) - c_file.write(" yajl_gen_status stat = yajl_gen_status_ok;\n") - c_file.write(" *err = 0;\n") - if obj.typ == 'mapStringObject': - get_map_string_obj(obj, c_file, prefix) - elif obj.typ == 'object' or (obj.typ == 'array' and obj.subtypobj): - nodes = obj.children if obj.typ == 'object' else obj.subtypobj - if nodes is None: - c_file.write(' if (!(ctx->options & OPT_GEN_SIMPLIFY))\n') - c_file.write(' yajl_gen_config(g, yajl_gen_beautify, 0);\n') - - c_file.write(" stat = yajl_gen_map_open((yajl_gen)g);\n") - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - for i in nodes or []: - get_obj_arr_obj(i, c_file, prefix) - c_file.write(" stat = yajl_gen_map_close((yajl_gen)g);\n") - c_file.write(" if (yajl_gen_status_ok != stat)\n") - c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n") - if nodes is None: - c_file.write(' if (!(ctx->options & OPT_GEN_SIMPLIFY))\n') - c_file.write(' yajl_gen_config(g, yajl_gen_beautify, 1);\n') - c_file.write(' return yajl_gen_status_ok;\n') - c_file.write("}\n\n") - - -def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename): - """ - Description: read value generateor - Interface: None - History: 2019-06-17 - """ - if helpers.valid_basic_map_name(typ): - c_file.write('%syajl_val val = %s;\n' % (' ' * level, src)) - c_file.write('%sif (val != NULL) {\n' % (' ' * level)) - c_file.write('%s%s = make_%s(val, ctx, err);\n' \ - % (' ' * (level + 1), dest, helpers.make_basic_map_name(typ))) - c_file.write('%sif (%s == NULL) {\n' % (' ' * (level + 1), dest)) - c_file.write('%s char *new_error = NULL;\n' % (' ' * (level + 1))) - c_file.write("%s if (asprintf(&new_error, \"Value error for key" \ - " '%s': %%s\", *err ? *err : \"null\") < 0) {\n" \ - % (' ' * (level + 1), keyname)) - c_file.write('%s new_error = safe_strdup("error allocating memory");\n' \ - % (' ' * (level + 1))) - c_file.write('%s }\n' % (' ' * (level + 1))) - c_file.write('%s free(*err);\n' % (' ' * (level + 1))) - c_file.write('%s *err = new_error;\n' % (' ' * (level + 1))) - c_file.write('%s free_%s(ret);\n' % (' ' * (level + 1), obj_typename)) - c_file.write('%s return NULL;\n' % (' ' * (level + 1))) - c_file.write('%s}\n' % (' ' * (level + 1))) - c_file.write('%s}\n' % (' ' * (level))) - elif typ == 'string': - c_file.write('%syajl_val val = %s;\n' % (' ' * (level), src)) - c_file.write('%sif (val != NULL) {\n' % (' ' * (level))) - c_file.write('%schar *str = YAJL_GET_STRING(val);\n' % (' ' * (level + 1))) - c_file.write('%s%s = safe_strdup(str ? str : "");\n' % (' ' * (level + 1), dest)) - c_file.write('%s}\n' % (' ' * level)) - elif helpers.judge_data_type(typ): - c_file.write('%syajl_val val = %s;\n' % (' ' * (level), src)) - c_file.write('%sif (val != NULL) {\n' % (' ' * (level))) - if typ.startswith("uint") or \ - (typ.startswith("int") and typ != "integer") or typ == "double": - c_file.write('%sint invalid = common_safe_%s(YAJL_GET_NUMBER(val), &%s);\n' \ - % (' ' * (level + 1), typ, dest)) - elif typ == "integer": - c_file.write('%sint invalid = common_safe_int(YAJL_GET_NUMBER(val), (int *)&%s);\n' \ - % (' ' * (level + 1), dest)) - elif typ == "UID" or typ == "GID": - c_file.write('%sint invalid = common_safe_uint(YAJL_GET_NUMBER(val),' \ - ' (unsigned int *)&%s);\n' % (' ' * (level + 1), dest)) - c_file.write('%sif (invalid) {\n' % (' ' * (level + 1))) - c_file.write('%s if (asprintf(err, "Invalid value \'%%s\' with type \'%s\' ' - 'for key \'%s\': %%s", YAJL_GET_NUMBER(val), strerror(-invalid)) < 0)\n' \ - % (' ' * (level + 1), typ, keyname)) - c_file.write('%s *err = safe_strdup("error allocating memory");\n' \ - % (' ' * (level + 1))) - c_file.write('%s free_%s(ret);\n' % (' ' * (level + 1), obj_typename)) - c_file.write('%s return NULL;\n' % (' ' * (level + 1))) - c_file.write('%s}\n' % (' ' * (level + 1))) - c_file.write('%s}\n' % (' ' * (level))) - elif helpers.judge_data_pointer_type(typ): - num_type = helpers.obtain_data_pointer_type(typ) - if num_type == "": - return - c_file.write('%syajl_val val = %s;\n' % (' ' * (level), src)) - c_file.write('%sif (val != NULL) {\n' % (' ' * (level))) - c_file.write('%s%s = safe_malloc(sizeof(%s));\n' % - (' ' * (level + 1), dest, helpers.get_map_c_types(num_type))) - c_file.write('%sint invalid = common_safe_%s(YAJL_GET_NUMBER(val), %s);\n' \ - % (' ' * (level + 1), num_type, dest)) - c_file.write('%sif (invalid) {\n' % (' ' * (level + 1))) - c_file.write('%s if (asprintf(err, "Invalid value \'%%s\' with type \'%s\' ' \ - 'for key \'%s\': %%s", YAJL_GET_NUMBER(val), strerror(-invalid)) < 0)\n' \ - % (' ' * (level + 1), typ, keyname)) - c_file.write('%s *err = safe_strdup("error allocating memory");\n' \ - % (' ' * (level + 1))) - c_file.write('%s free_%s(ret);\n' % (' ' * (level + 1), obj_typename)) - c_file.write('%s return NULL;\n' % (' ' * (level + 1))) - c_file.write('%s}\n' % (' ' * (level + 1))) - c_file.write('%s}\n' % (' ' * (level))) - elif typ == 'boolean': - c_file.write('%syajl_val val = %s;\n' % (' ' * (level), src)) - c_file.write('%sif (val != NULL)\n' % (' ' * (level))) - c_file.write('%s%s = YAJL_IS_TRUE(val);\n' % (' ' * (level + 1), dest)) - elif typ == 'booleanPointer': - c_file.write('%syajl_val val = %s;\n' % (' ' * (level), src)) - c_file.write('%sif (val != NULL) {\n' % (' ' * (level))) - c_file.write('%s%s = safe_malloc(sizeof(bool));\n' % (' ' * (level + 1), dest)) - c_file.write('%s*(%s) = YAJL_IS_TRUE(val);\n' % (' ' * (level + 1), dest)) - c_file.write('%s} else {\n' % (' ' * (level))) - c_file.write('%sval = get_val(tree, "%s", yajl_t_false);\n' \ - % (' ' * (level + 1), keyname)) - c_file.write('%sif (val != NULL) {\n' % (' ' * (level + 1))) - c_file.write('%s%s = safe_malloc(sizeof(bool));\n' % (' ' * (level + 2), dest)) - c_file.write('%s*(%s) = YAJL_IS_TRUE(val);\n' % (' ' * (level + 2), dest)) - c_file.write('%s}\n' % (' ' * (level + 1))) - c_file.write('%s}\n' % (' ' * (level))) - - -def json_value_generator(c_file, level, src, dst, ptx, typ): - """ - Description: json value generateor - Interface: None - History: 2019-06-17 - """ - if helpers.valid_basic_map_name(typ): - c_file.write('%sstat = gen_%s(%s, %s, %s, err);\n' \ - % (' ' * (level), helpers.make_basic_map_name(typ), dst, src, ptx)) - c_file.write("%sif (yajl_gen_status_ok != stat)\n" % (' ' * (level))) - c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" % (' ' * (level + 1))) - elif typ == 'string': - c_file.write('%sstat = yajl_gen_string((yajl_gen)%s, \ - (const unsigned char *)(%s), strlen(%s));\n' % (' ' * (level), dst, src, src)) - c_file.write("%sif (yajl_gen_status_ok != stat)\n" % (' ' * (level))) - c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" % (' ' * (level + 1))) - elif helpers.judge_data_type(typ): - if typ == 'double': - c_file.write('%sstat = yajl_gen_double((yajl_gen)%s, %s);\n' \ - % (' ' * (level), dst, src)) - elif typ.startswith("uint") or typ == 'GID' or typ == 'UID': - c_file.write('%sstat = map_uint(%s, %s);\n' % (' ' * (level), dst, src)) - else: - c_file.write('%sstat = map_int(%s, %s);\n' % (' ' * (level), dst, src)) - c_file.write("%sif (yajl_gen_status_ok != stat)\n" % (' ' * (level))) - c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" \ - % (' ' * (level + 1))) - elif typ == 'boolean': - c_file.write('%sstat = yajl_gen_bool((yajl_gen)%s, (int)(%s));\n' \ - % (' ' * (level), dst, src)) - c_file.write("%sif (yajl_gen_status_ok != stat)\n" % (' ' * (level))) - c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" % (' ' * (level + 1))) - - -def make_c_free(obj, c_file, prefix): - """ - Description: generate c free function - Interface: None - History: 2019-06-17 - """ - if not helpers.judge_complex(obj.typ) or obj.subtypname: - return - typename = helpers.get_prefixe_name(obj.name, prefix) - case = obj.typ - result = {'mapStringObject': lambda x: [], 'object': lambda x: x.children, - 'array': lambda x: x.subtypobj}[case](obj) - objs = result - if obj.typ == 'array': - if objs is None: - return - else: - typename = helpers.get_name_substr(obj.name, prefix) - c_file.write("void free_%s(%s *ptr) {\n" % (typename, typename)) - c_file.write(" if (ptr == NULL)\n") - c_file.write(" return;\n") - if obj.typ == 'mapStringObject': - child = obj.children[0] - if helpers.valid_basic_map_name(child.typ): - childname = helpers.make_basic_map_name(child.typ) - else: - if child.subtypname: - childname = child.subtypname - else: - childname = helpers.get_prefixe_name(child.name, prefix) - c_file_map_str(c_file, child, childname) - for i in objs or []: - if helpers.valid_basic_map_name(i.typ): - free_func = helpers.make_basic_map_name(i.typ) - c_file.write(" free_%s(ptr->%s);\n" % (free_func, i.fixname)) - c_file.write(" ptr->%s = NULL;\n" % (i.fixname)) - if i.typ == 'mapStringObject': - if i.subtypname: - free_func = i.subtypname - else: - free_func = helpers.get_prefixe_name(i.name, prefix) - c_file.write(" free_%s(ptr->%s);\n" % (free_func, i.fixname)) - c_file.write(" ptr->%s = NULL;\n" % (i.fixname)) - elif i.typ == 'array': - if helpers.valid_basic_map_name(i.subtyp): - free_func = helpers.make_basic_map_name(i.subtyp) - c_file.write(" if (ptr->%s != NULL) {\n" % i.fixname) - c_file.write(" size_t i;\n") - c_file.write(" for (i = 0; i < ptr->%s_len; i++) {\n" % i.fixname) - c_file.write(" if (ptr->%s[i] != NULL) {\n" % (i.fixname)) - c_file.write(" free_%s(ptr->%s[i]);\n" % (free_func, i.fixname)) - c_file.write(" ptr->%s[i] = NULL;\n" % (i.fixname)) - c_file.write(" }\n") - c_file.write(" }\n") - c_file.write(" free(ptr->%s);\n" % (i.fixname)) - c_file.write(" ptr->%s = NULL;\n" % (i.fixname)) - c_file.write(" }\n") - elif i.subtyp == 'string': - c_file_str(c_file, i) - elif not helpers.judge_complex(i.subtyp): - c_file.write(" free(ptr->%s);\n" % (i.fixname)) - c_file.write(" ptr->%s = NULL;\n" % (i.fixname)) - elif i.subtyp == 'object' or i.subtypobj is not None: - if i.subtypname is not None: - free_func = i.subtypname - else: - free_func = helpers.get_name_substr(i.name, prefix) - c_file.write(" if (ptr->%s != NULL) {\n" % i.fixname) - c_file.write(" size_t i;\n") - c_file.write(" for (i = 0; i < ptr->%s_len; i++)\n" % i.fixname) - c_file.write(" if (ptr->%s[i] != NULL) {\n" % (i.fixname)) - c_file.write(" free_%s(ptr->%s[i]);\n" % (free_func, i.fixname)) - c_file.write(" ptr->%s[i] = NULL;\n" % (i.fixname)) - c_file.write(" }\n") - c_file.write(" free(ptr->%s);\n" % i.fixname) - c_file.write(" ptr->%s = NULL;\n" % (i.fixname)) - c_file.write(" }\n") - c_typ = helpers.obtain_pointer(i.name, i.subtypobj, prefix) - if c_typ == "": - continue - if i.subobj is not None: - c_typ = c_typ + "_element" - c_file.write(" free_%s(ptr->%s);\n" % (c_typ, i.fixname)) - c_file.write(" ptr->%s = NULL;\n" % (i.fixname)) - else: - typename = helpers.get_prefixe_name(i.name, prefix) - if i.typ == 'string' or i.typ == 'booleanPointer' or \ - helpers.judge_data_pointer_type(i.typ): - c_file.write(" free(ptr->%s);\n" % (i.fixname)) - c_file.write(" ptr->%s = NULL;\n" % (i.fixname)) - elif i.typ == 'object': - if i.subtypname is not None: - typename = i.subtypname - c_file.write(" if (ptr->%s != NULL) {\n" % (i.fixname)) - c_file.write(" free_%s(ptr->%s);\n" % (typename, i.fixname)) - c_file.write(" ptr->%s = NULL;\n" % (i.fixname)) - c_file.write(" }\n") - c_file.write(" free(ptr);\n") - c_file.write("}\n\n") - - -def c_file_map_str(c_file, child, childname): - """ - Description: generate c code for map string - Interface: None - History: 2019-10-31 - """ - c_file.write(" if (ptr->keys != NULL && ptr->%s != NULL) {\n" % child.fixname) - c_file.write(" size_t i;\n") - c_file.write(" for (i = 0; i < ptr->len; i++) {\n") - c_file.write(" free(ptr->keys[i]);\n") - c_file.write(" ptr->keys[i] = NULL;\n") - c_file.write(" free_%s(ptr->%s[i]);\n" % (childname, child.fixname)) - c_file.write(" ptr->%s[i] = NULL;\n" % (child.fixname)) - c_file.write(" }\n") - c_file.write(" free(ptr->keys);\n") - c_file.write(" ptr->keys = NULL;\n") - c_file.write(" free(ptr->%s);\n" % (child.fixname)) - c_file.write(" ptr->%s = NULL;\n" % (child.fixname)) - c_file.write(" }\n") - - -def c_file_str(c_file, i): - """ - Description: generate c code template - Interface: None - History: 2019-10-31 - """ - c_file.write(" if (ptr->%s != NULL) {\n" % i.fixname) - c_file.write(" size_t i;\n") - c_file.write(" for (i = 0; i < ptr->%s_len; i++) {\n" % i.fixname) - c_file.write(" if (ptr->%s[i] != NULL) {\n" % (i.fixname)) - c_file.write(" free(ptr->%s[i]);\n" % (i.fixname)) - c_file.write(" ptr->%s[i] = NULL;\n" % (i.fixname)) - c_file.write(" }\n") - c_file.write(" }\n") - c_file.write(" free(ptr->%s);\n" % (i.fixname)) - c_file.write(" ptr->%s = NULL;\n" % (i.fixname)) - c_file.write(" }\n") - - -def src_reflect(structs, schema_info, c_file, root_typ): - """ - Description: reflect code - Interface: None - History: 2019-06-17 - """ - c_file.write("// Generated from %s. Do not edit!\n" \ - % (schema_info.name.basename)) - c_file.write("#ifndef _GNU_SOURCE\n") - c_file.write("#define _GNU_SOURCE\n") - c_file.write("#endif\n") - c_file.write('#include \n') - c_file.write('#include \n') - c_file.write('#include "%s"\n\n' % schema_info.header.basename) - for i in structs: - append_c_code(i, c_file, schema_info.prefix) - get_c_epilog(c_file, schema_info.prefix, root_typ) - - -def get_c_epilog(c_file, prefix, typ): - """ - Description: generate c language epilogue - Interface: None - History: 2019-06-17 - """ - if typ != 'array' and typ != 'object': - return - if typ == 'array': - c_file.write("""\n -%s_element **make_%s(yajl_val tree, const struct parser_context *ctx, parser_error *err, size_t *len) { - %s_element **ptr = NULL; - size_t i, alen; - if (tree == NULL || err == NULL || !len || YAJL_GET_ARRAY(tree) == NULL) - return NULL; - *err = 0; - alen = YAJL_GET_ARRAY(tree)->len; - if (alen == 0) - return NULL; - ptr = safe_malloc((alen + 1) * sizeof(%s_element *)); - for (i = 0; i < alen; i++) { - yajl_val val = YAJL_GET_ARRAY(tree)->values[i]; - ptr[i] = make_%s_element(val, ctx, err); - if (ptr[i] == NULL) { - free_%s(ptr, alen); - return NULL; - } - } - *len = alen; - return ptr; -} -""" % (prefix, prefix, prefix, prefix, prefix, prefix)) - c_file.write("""\n -void free_%s(%s_element **ptr, size_t len) { - size_t i; - - if (ptr == NULL || len == 0) - return; - - for (i = 0; i < len; i++) { - if (ptr[i] != NULL) { - free_%s_element(ptr[i]); - ptr[i] = NULL; - } - } - free(ptr); -} -""" % (prefix, prefix, prefix)) - c_file.write("""\n -yajl_gen_status gen_%s(yajl_gen g, const %s_element **ptr, size_t len, const struct parser_context *ctx, - parser_error *err) { - yajl_gen_status stat; - size_t i; - *err = 0; - stat = yajl_gen_array_open((yajl_gen)g); - if (yajl_gen_status_ok != stat) - GEN_SET_ERROR_AND_RETURN(stat, err); - for (i = 0; i < len; i++) { - stat = gen_%s_element(g, ptr[i], ctx, err); - if (yajl_gen_status_ok != stat) - GEN_SET_ERROR_AND_RETURN(stat, err); - } - stat = yajl_gen_array_close((yajl_gen)g); - if (yajl_gen_status_ok != stat) - GEN_SET_ERROR_AND_RETURN(stat, err); - return yajl_gen_status_ok; -} -""" % (prefix, prefix, prefix)) - c_file.write(""" -%s%s*%s_parse_file(const char *filename, const struct parser_context *ctx, parser_error *err%s) { - %s%s*ptr = NULL;""" % (prefix, ' ' if typ == 'object' else '_element *', \ - prefix, '' if typ == 'object' else ', size_t *len', \ - prefix, ' ' if typ == 'object' else '_element *')) - c_file.write(""" - size_t filesize; - char *content = NULL; - - if (filename == NULL || err == NULL) - return NULL; - - *err = NULL; - content = read_file(filename, &filesize); - if (content == NULL) { - if (asprintf(err, "cannot read the file: %%s", filename) < 0) - *err = safe_strdup("error allocating memory"); - return NULL; - } - ptr = %s_parse_data(content, ctx, err%s); - free(content); - return ptr; -} -""" % (prefix, '' if typ == 'object' else ', len')) - c_file.write(""" -%s%s*%s_parse_file_stream(FILE *stream, const struct parser_context *ctx, parser_error *err%s) { - %s%s*ptr = NULL;""" % (prefix, ' ' if typ == 'object' else '_element *', \ - prefix, '' if typ == 'object' else ', size_t *len', \ - prefix, ' ' if typ == 'object' else '_element *')) - c_file.write(""" - size_t filesize; - char *content = NULL ; - - if (stream == NULL || err == NULL) - return NULL; - - *err = NULL; - content = fread_file(stream, &filesize); - if (content == NULL) { - *err = safe_strdup("cannot read the file"); - return NULL; - } - ptr = %s_parse_data(content, ctx, err%s); - free(content); - return ptr; -} -""" % (prefix, '' if typ == 'object' else ', len')) - c_file.write(""" -%s%s*%s_parse_data(const char *jsondata, const struct parser_context *ctx, parser_error *err%s) { - %s%s*ptr = NULL;""" % (prefix, ' ' if typ == 'object' else '_element *', \ - prefix, '' if typ == 'object' else ', size_t *len', \ - prefix, ' ' if typ == 'object' else '_element *')) - c_file.write(""" - yajl_val tree; - char errbuf[1024]; - struct parser_context tmp_ctx = { 0 }; - - if (jsondata == NULL || err == NULL) - return NULL; - - *err = NULL; - if (ctx == NULL) { - ctx = (const struct parser_context *)(&tmp_ctx); - } - tree = yajl_tree_parse(jsondata, errbuf, sizeof(errbuf)); - if (tree == NULL) { - if (asprintf(err, "cannot parse the data: %%s", errbuf) < 0) - *err = safe_strdup("error allocating memory"); - return NULL; - } - ptr = make_%s(tree, ctx, err%s); - yajl_tree_free(tree); - return ptr; -} -""" % (prefix, '' if typ == 'object' else ', len')) - c_file.write("char *%s_generate_json(const %s%s*ptr%s, const struct parser_context *ctx," \ - " parser_error *err) {" % (prefix, prefix, \ - ' ' if typ == 'object' else '_element *', \ - '' if typ == 'object' else ', size_t len')) - c_file.write(""" - yajl_gen g = NULL; - struct parser_context tmp_ctx = { 0 }; - const unsigned char *gen_buf = NULL; - char *json_buf = NULL; - size_t gen_len = 0; - - if (ptr == NULL || err == NULL) - return NULL; - - *err = NULL; - if (ctx == NULL) { - ctx = (const struct parser_context *)(&tmp_ctx); - } - - if (!json_gen_init(&g, ctx)) { - *err = safe_strdup("Json_gen init failed"); - goto out; - } - if (yajl_gen_status_ok != gen_%s(g, ptr%s, ctx, err)) { - if (*err == NULL) - *err = safe_strdup("Failed to generate json"); - goto free_out; - } - yajl_gen_get_buf(g, &gen_buf, &gen_len); - if (gen_buf == NULL) { - *err = safe_strdup("Error to get generated json"); - goto free_out; - } - - json_buf = safe_malloc(gen_len + 1); - (void)memcpy(json_buf, gen_buf, gen_len); - json_buf[gen_len] = '\\0'; - -free_out: - yajl_gen_clear(g); - yajl_gen_free(g); -out: - return json_buf; -} - -""" % (prefix, '' if typ == 'object' else ', len')) - - diff --git a/src/lcr_list.h b/src/lcr_list.h deleted file mode 100644 index c7b5c9b..0000000 --- a/src/lcr_list.h +++ /dev/null @@ -1,138 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide container lcr list definition - ******************************************************************************/ -#ifndef __LCR_LIST_H -#define __LCR_LIST_H - - -struct lcr_list { - void *elem; - struct lcr_list *next; - struct lcr_list *prev; -}; - -/* Iterate through an lcr list. */ -#define lcr_list_for_each(__iterator, __list) \ - for ((__iterator) = (__list)->next; \ - (__iterator) != (__list); \ - (__iterator) = (__iterator)->next) - -/* - * Iterate safely through an lcr list - */ -#define lcr_list_for_each_safe(__iterator, __list, __next) \ - for ((__iterator) = (__list)->next, (__next) = (__iterator)->next; \ - (__iterator) != (__list); \ - (__iterator) = (__next), (__next) = (__next)->next) - -/* Initialize list. */ -static inline void lcr_list_init(struct lcr_list *list) -{ - list->elem = NULL; - list->next = list->prev = list; -} - -/* Add an element to a list. See lcr_list_add() and lcr_list_add_tail() for an - * idiom. */ -static inline void lcr_list_add_elem(struct lcr_list *list, void *elem) -{ - list->elem = elem; -} - -/* Retrieve first element of list. */ -static inline void *lcr_list_first_elem(struct lcr_list *list) -{ - return list->next->elem; -} - -/* Retrieve last element of list. */ -static inline void *lcr_list_last_elem(struct lcr_list *list) -{ - return list->prev->elem; -} - -/* Determine if list is empty. */ -static inline int lcr_list_empty(const struct lcr_list *list) -{ - return list == list->next; -} - -/* Workhorse to be called from lcr_list_add() and lcr_list_add_tail(). */ -static inline void __lcr_list_add(struct lcr_list *new, struct lcr_list *prev, struct lcr_list *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/* - * Idiom to add an element to the beginning of an lcr list - */ -static inline void lcr_list_add(struct lcr_list *head, struct lcr_list *list) -{ - __lcr_list_add(list, head, head->next); -} - -/* - * Idiom to add an element to the end of an lcr list - */ -static inline void lcr_list_add_tail( - struct lcr_list *head, struct lcr_list *list) -{ - __lcr_list_add(list, head->prev, head); -} - -/* Idiom to merge two lcr list */ -static inline void lcr_list_merge( - struct lcr_list *list1, struct lcr_list *list2) -{ - struct lcr_list *list1_tail, *list2_tail; - list1_tail = list1->prev; - list2_tail = list2->prev; - // to merge two list, we need: - // 1. update list1's prev (next is not needed) to list2's tail - list1->prev = list2_tail; - // 2. update list1's tail's next to list2 - list1_tail->next = list2; - // 3. update list2's prev to list1's tail - list2->prev = list1_tail; - // 4. update list2's tail's next to list1 - list2_tail->next = list1; -} - -/* Idiom to free an lcr list */ -static inline void lcr_list_del(struct lcr_list *list) -{ - struct lcr_list *next, *prev; - - next = list->next; - prev = list->prev; - next->prev = prev; - prev->next = next; -} - -/* Return length of the list. */ -static inline size_t lcr_list_len(struct lcr_list *list) -{ - size_t i = 0; - struct lcr_list *iter; - lcr_list_for_each(iter, list) { - i++; - } - - return i; -} - -#endif diff --git a/src/lcrcontainer.c b/src/lcrcontainer.c deleted file mode 100644 index 4c1a27f..0000000 --- a/src/lcrcontainer.c +++ /dev/null @@ -1,1237 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide container definition - ******************************************************************************/ -/* - * liblcrapi - */ - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include - -#include - -#include "constants.h" -#include "error.h" -#include "lcrcontainer.h" -#include "lcrcontainer_execute.h" -#include "lcrcontainer_extend.h" -#include "log.h" -#include "utils.h" -#include "oci_runtime_spec.h" - -/* - * Free lcr_container_info array returned by lcr_list_{active,all}_containers - */ -void lcr_containers_info_free(struct lcr_container_info **info_arr, size_t size) -{ - size_t i = 0; - struct lcr_container_info *in = NULL; - - if (info_arr == NULL) { - return; - } - if (size == 0) { - return; - } - for (i = 0, in = *info_arr; i < size; i++, in++) { - free(in->interface); - free(in->ipv4); - free(in->ipv6); - free(in->name); - free(in->state); - } - free(*info_arr); - *info_arr = NULL; -} - -/* - * Free lcr_container_info returned lcr_container_info_get - */ -void lcr_container_info_free(struct lcr_container_info *info) -{ - if (info == NULL) { - return; - } - free(info->interface); - info->interface = NULL; - free(info->ipv4); - info->ipv4 = NULL; - free(info->ipv6); - info->ipv6 = NULL; - free(info->name); - info->name = NULL; - free(info->state); - info->state = NULL; - free(info); -} - -static inline bool is_container_exists(struct lxc_container *c) -{ - return c->is_defined(c); -} - -static inline bool is_container_can_control(struct lxc_container *c) -{ - return c->may_control(c); -} - -/* - * Get one container info for a given name and lcrpath. - * return struct of container info, or NULL on error. - */ -struct lcr_container_info *lcr_container_info_get(const char *name, const char *lcrpath) -{ - int nret = -1; - struct lcr_container_info *info = NULL; - const char *st = NULL; - bool run_flag = false; - - struct lxc_container *c = lxc_container_without_config_new(name, lcrpath); - if (c == NULL) { - return NULL; - } - - if (!is_container_exists(c)) { - goto put_and_finish; - } - - st = c->state(c); - if (st == NULL) { - st = "UNKNOWN"; - } - run_flag = (strcmp(st, "STOPPED") != 0); - - /* Now it makes sense to allocate memory */ - info = lcr_util_common_calloc_s(sizeof(*info)); - if (info == NULL) { - nret = -1; - goto put_and_finish; - } - info->init = -1; - info->running = run_flag; - info->name = lcr_util_strdup_s(name); - info->state = lcr_util_strdup_s(st); - if (run_flag) { - info->init = c->init_pid(c); - } - - nret = 0; -put_and_finish: - lxc_container_put(c); - if (nret != 0) { - lcr_container_info_free(info); - info = NULL; - } - return info; -} - -/* - * Get a complete list of all containers for a given lcrpath. - * return Number of containers, or -1 on error. - **/ -int lcr_list_all_containers(const char *lcrpath, struct lcr_container_info **info_arr) -{ - char **container = NULL; - int n = 0; - int nret = -1; - size_t info_size = 0; - const char *path = lcrpath ? lcrpath : LCRPATH; - - clear_error_message(&g_lcr_error); - n = list_all_containers(path, &container, NULL); - if (n == -1) { - n = 0; - } - - nret = lcr_containers_info_get(path, info_arr, &info_size, container, n); - if (info_arr == NULL && nret == 0) { - return -1; - } else if (info_arr == NULL || nret == -1) { - lcr_containers_info_free(info_arr, info_size); - return -1; - } - - return (int)info_size; -} - -static inline bool is_invalid_container(const struct lxc_container *c) -{ - return c == NULL || c->name == NULL || c->config_path == NULL; -} - -static inline bool is_annotation_key_net_mode(const char *key) -{ - return strcmp(key, "host.network.mode") == 0; -} - -static inline bool is_annotation_value_host(const char *value) -{ - return strcmp(value, "host") == 0; -} - -static inline bool is_root(const char *path) -{ - return strcmp(path, "/") == 0; -} - -static int create_partial(const struct lxc_container *c) -{ - size_t len = 0; - int fd = 0; - int ret = 0; - struct flock lk; - - if (strlen(c->name) > ((SIZE_MAX - strlen(c->config_path)) - 10)) { - return -1; - } - - // $lxcpath + '/' + $name + '/partial' + \0 - len = strlen(c->config_path) + strlen(c->name) + 10; - - char *path = lcr_util_common_calloc_s(len); - if (path == NULL) { - ERROR("Out of memory in create_partial"); - return -1; - } - - ret = snprintf(path, len, "%s/%s/partial", c->config_path, c->name); - if (ret < 0 || (size_t)ret >= len) { - ERROR("Error writing partial pathname"); - goto out_free; - } - - fd = lcr_util_open(path, O_RDWR | O_CREAT | O_EXCL, DEFAULT_SECURE_FILE_MODE); - if (fd < 0) { - SYSERROR("Error creating partial file: %s", path); - goto out_free; - } - lk.l_type = F_WRLCK; - lk.l_whence = SEEK_SET; - lk.l_start = 0; - lk.l_len = 0; - if (fcntl(fd, F_SETLKW, &lk) < 0) { - SYSERROR("Error locking partial file %s", path); - close(fd); - goto out_free; - } - - free(path); - return fd; - -out_free: - free(path); - return -1; -} - -static void remove_partial(const struct lxc_container *c) -{ - size_t len = 0; - int ret = 0; - - if (strlen(c->name) > ((SIZE_MAX - strlen(c->config_path)) - 10)) { - return; - } - - // $lxcpath + '/' + $name + '/partial' + \0 - len = strlen(c->config_path) + strlen(c->name) + 10; - - char *path = lcr_util_common_calloc_s(len); - if (path == NULL) { - ERROR("Out of memory in remove_partial"); - return; - } - - ret = snprintf(path, len, "%s/%s/partial", c->config_path, c->name); - if (ret < 0 || (size_t)ret >= len) { - ERROR("Error writing partial pathname"); - goto out_free; - } - if (unlink(path) < 0) { - SYSERROR("Error unlink partial file %s", path); - } - -out_free: - free(path); -} - -static bool lcr_create_spec(struct lxc_container *c, oci_runtime_spec *oci_spec) -{ - // Translate oci config - DEBUG("Translate oci config...\n"); - if (!translate_spec(c, oci_spec)) { - return false; - } - DEBUG("Translate oci config... done\n"); - return true; -} - -bool lcr_create(const char *name, const char *lcrpath, void *oci_config) -{ - struct lxc_container *c = NULL; - int partial_fd = -1; - bool bret = false; - const char *tmp_path = lcrpath ? lcrpath : LCRPATH; - oci_runtime_spec *oci_spec = (oci_runtime_spec *)oci_config; - - clear_error_message(&g_lcr_error); - engine_set_log_prefix(name); - - c = lxc_container_new(name, tmp_path); - if (c == NULL) { - engine_free_log_prefix(); - return false; - } - - /* Mark that this container is being created */ - partial_fd = create_partial(c); - if (partial_fd < 0) { - lxc_container_put(c); - engine_free_log_prefix(); - return false; - } - - if (!lcr_create_spec(c, oci_spec)) { - goto out_unlock; - } - - bret = true; -out_unlock: - if (partial_fd >= 0) { - close(partial_fd); - remove_partial(c); - } - if (!bret) { - if (!c->destroy(c)) { - WARN("Unable to clean lxc resources"); - } - } - lxc_container_put(c); - engine_free_log_prefix(); - return bret; -} - -static bool lcr_start_check_config(const char *lcrpath, const char *name) -{ - char config[PATH_MAX] = { 0 }; - int nret = 0; - - if (access(lcrpath, O_RDONLY) != 0) { - ERROR("You lack permission to access %s", lcrpath); - return false; - } - - nret = snprintf(config, sizeof(config), "%s/%s/config", lcrpath, name); - if (nret < 0 || (size_t)nret >= sizeof(config)) { - SYSERROR("Failed to allocated memory"); - return false; - } - - if (access(config, F_OK) != 0) { - ERROR("File %s does not exist", config); - return false; - } - return true; -} - -static bool wait_start_pid(pid_t pid, int rfd, const char *name, const char *path) -{ - int ret; - ssize_t size_read = 0; - char buffer[BUFSIZ] = { 0 }; - - ret = lcr_wait_for_pid(pid); - if (ret == 0) { - return true; - } - - ERROR("Start container failed\n"); - // set default error - lcr_set_error_message(LCR_ERR_RUNTIME, "runtime error"); - - INFO("begin to stop container\n"); - if (!lcr_kill(name, path, SIGKILL)) { - ERROR("Failed to stop container"); - } - - size_read = read(rfd, buffer, sizeof(buffer) - 1); - if (size_read > 0) { - ERROR("Runtime error: %s", buffer); - lcr_set_error_message(LCR_ERR_RUNTIME, "runtime error: %s", buffer); - } - return false; -} - -bool lcr_start(const struct lcr_start_request *request) -{ - int pipefd[2] = { -1, -1 }; - bool ret = false; - pid_t pid = 0; - const char *path = NULL; - if (request == NULL) { - return false; - } - path = request->lcrpath ? request->lcrpath : LCRPATH; - - clear_error_message(&g_lcr_error); - if (request->name == NULL) { - ERROR("Missing container name"); - return false; - } - engine_set_log_prefix(request->name); - - if (!lcr_start_check_config(path, request->name)) { - goto out_free; - } - - if (pipe(pipefd) != 0) { - ERROR("Failed to create pipe\n"); - goto out_free; - } - - pid = fork(); - if (pid == (pid_t) - 1) { - ERROR("Failed to fork()\n"); - close(pipefd[0]); - close(pipefd[1]); - goto out_free; - } - - if (pid == (pid_t)0) { - // child process, dup2 pipefd[1] to stderr - close(pipefd[0]); - dup2(pipefd[1], 2); - - execute_lxc_start(request->name, path, request); - } - - close(pipefd[1]); - ret = wait_start_pid(pid, pipefd[0], request->name, path); - close(pipefd[0]); - -out_free: - engine_free_log_prefix(); - return ret; -} - -static bool lcr_check_container_running(struct lxc_container *c, const char *name) -{ - if (!is_container_exists(c)) { - ERROR("No such container"); - lcr_set_error_message(LCR_ERR_RUNTIME, "No such container:%s or the configuration files has been corrupted", - name); - return false; - } - - if (!is_container_can_control(c)) { - ERROR("Insufficent privileges to control"); - return false; - } - - if (!c->is_running(c)) { - ERROR("Container is not running"); - lcr_set_error_message(LCR_ERR_RUNTIME, "Container is not running:%s", name); - return false; - } - return true; -} - -bool lcr_kill(const char *name, const char *lcrpath, uint32_t signal) -{ - struct lxc_container *c = NULL; - const char *path = lcrpath ? lcrpath : LCRPATH; - bool ret = false; - int sret = 0; - pid_t pid = 0; - - clear_error_message(&g_lcr_error); - if (name == NULL) { - ERROR("Missing container name"); - return false; - } - - engine_set_log_prefix(name); - if (signal >= NSIG) { - ERROR("'%u' isn't a valid signal number", signal); - engine_free_log_prefix(); - return false; - } - - c = lxc_container_new(name, path); - if (c == NULL) { - ERROR("Failed to stop container."); - engine_free_log_prefix(); - return false; - } - - if (!lcr_check_container_running(c, name)) { - goto out_put; - } - - pid = c->init_pid(c); - if (pid < 0) { - ERROR("Failed to get init pid"); - goto out_put; - } - - sret = kill(pid, (int)signal); - if (sret < 0) { - if (errno == ESRCH) { - WARN("Can not kill process (pid=%d) with signal %d for container: no such process", pid, signal); - ret = true; - goto out_put; - } - ERROR("Can not kill process (pid=%d) with signal %d for container", pid, signal); - goto out_put; - } - - ret = true; - -out_put: - lxc_container_put(c); - engine_free_log_prefix(); - return ret; -} - -bool lcr_delete(const char *name, const char *lcrpath) -{ - struct lxc_container *c = NULL; - const char *path = lcrpath ? lcrpath : LCRPATH; - bool ret = true; - - clear_error_message(&g_lcr_error); - if (name == NULL) { - ERROR("Missing container name"); - return false; - } - engine_set_log_prefix(name); - c = lxc_container_new(name, path); - if (c == NULL) { - ERROR("Failed to delete container."); - engine_free_log_prefix(); - return false; - } - - if (!is_container_can_control(c)) { - ERROR("Insufficent privileges to control"); - ret = false; - goto out_put; - } - - if (!is_container_exists(c)) { - ERROR("No such container"); - lcr_set_error_message(LCR_ERR_RUNTIME, "No such container:%s or the configuration files has been corrupted", - name); - ret = false; - (void)c->destroy(c); - goto out_put; - } - - if (c->is_running(c)) { - ERROR("Container %s is running, Stop the container before remove", name); - lcr_set_error_message(LCR_ERR_RUNTIME, "Container %s is running, Stop the container before remove", name); - ret = false; - goto out_put; - } - - ret = c->destroy(c); - if (!ret) { - if (c->error_string != NULL) { - lcr_set_error_message(LCR_ERR_RUNTIME, "%s", c->error_string); - } - } - -out_put: - lxc_container_put(c); - engine_free_log_prefix(); - return ret; -} - -bool lcr_exec(const struct lcr_exec_request *request, int *exit_code) -{ - const char *name = NULL; - struct lxc_container *c = NULL; - const char *tmp_path = NULL; - bool bret = false; - - clear_error_message(&g_lcr_error); - - if (request == NULL || exit_code == NULL) { - ERROR("Invalid input arguments"); - return bret; - } - - name = request->name; - tmp_path = request->lcrpath ? request->lcrpath : LCRPATH; - - if (name == NULL) { - ERROR("Missing container name"); - return bret; - } - - engine_set_log_prefix(name); - - if (geteuid()) { - if (access(tmp_path, O_RDONLY) < 0) { - ERROR("You lack access to %s", tmp_path); - goto out; - } - } - - c = lxc_container_new(name, tmp_path); - if (c == NULL) { - ERROR("Failed to delete container."); - goto out; - } - - if (!lcr_check_container_running(c, name)) { - goto out_put; - } - - lxc_container_put(c); - - /* do attach to wait exit code */ - bret = do_attach(name, tmp_path, request, exit_code); - goto out; - -out_put: - lxc_container_put(c); -out: - engine_free_log_prefix(); - return bret; -} - -bool lcr_clean(const char *name, const char *lcrpath, const char *logpath, const char *loglevel, pid_t pid) -{ - struct lxc_container *c = NULL; - const char *tmp_path = lcrpath ? lcrpath : LCRPATH; - bool bret = true; - - clear_error_message(&g_lcr_error); - - if (name == NULL) { - ERROR("Missing container name"); - return false; - } - engine_set_log_prefix(name); - - if (geteuid()) { - if (access(tmp_path, O_RDONLY) < 0) { - ERROR("You lack access to %s", tmp_path); - engine_free_log_prefix(); - return false; - } - } - - c = lxc_container_new(name, tmp_path); - if (c == NULL) { - ERROR("Failed to delete container."); - engine_free_log_prefix(); - return false; - } - - /* if container do not exist, just return true. */ - if (!is_container_exists(c)) { - WARN("No such container: %s", name); - bret = true; - goto out_put; - } - - if (!is_container_can_control(c)) { - ERROR("Insufficent privileges to control"); - bret = false; - goto out_put; - } - - if (!c->clean_container_resource(c, pid)) { - ERROR("Error: Failed to clean container %s resource\n", name); - bret = false; - goto out_put; - } - -out_put: - lxc_container_put(c); - - engine_free_log_prefix(); - return bret; -} - -bool lcr_state(const char *name, const char *lcrpath, struct lcr_container_state *lcs) -{ - struct lxc_container *c = NULL; - const char *tmp_path = lcrpath ? lcrpath : LCRPATH; - bool bret = true; - - if (name == NULL) { - ERROR("Missing container name"); - return false; - } - engine_set_log_prefix(name); - c = lxc_container_new(name, tmp_path); - if (c == NULL) { - ERROR("Failure to retrieve state infomation on %s", tmp_path); - engine_free_log_prefix(); - return false; - } - - if (!is_container_exists(c)) { - ERROR("No such container: %s", name); - bret = false; - goto out_put; - } - - if (!is_container_can_control(c)) { - ERROR("Insufficent privileges to control"); - bret = false; - goto out_put; - } - - do_lcr_state(c, lcs); -out_put: - lxc_container_put(c); - engine_free_log_prefix(); - return bret; -} - -bool lcr_get_container_pids(const char *name, const char *lcrpath, pid_t **pids, size_t *pids_len) -{ - struct lxc_container *c = NULL; - const char *tmp_path = lcrpath ? lcrpath : LCRPATH; - bool bret = true; - - if (name == NULL) { - ERROR("Missing container name"); - return false; - } - engine_set_log_prefix(name); - c = lxc_container_new(name, tmp_path); - if (c == NULL) { - ERROR("Failure to retrieve state infomation on %s", tmp_path); - engine_free_log_prefix(); - return false; - } - - if (!is_container_exists(c)) { - ERROR("No such container"); - bret = false; - goto out_put; - } - - if (!c->get_container_pids(c, pids, pids_len)) { - ERROR("Error: Failed to get container %s pids\n", name); - bret = false; - goto out_put; - } - -out_put: - lxc_container_put(c); - engine_free_log_prefix(); - return bret; -} - -void lcr_container_state_free(struct lcr_container_state *lcs) -{ - free(lcs->name); - lcs->name = NULL; - free(lcs->state); - lcs->state = NULL; -} - -bool lcr_pause(const char *name, const char *lcrpath) -{ - struct lxc_container *c = NULL; - const char *tmp_path = lcrpath ? lcrpath : LCRPATH; - bool bret = true; - - clear_error_message(&g_lcr_error); - - if (name == NULL) { - ERROR("Missing container name"); - return false; - } - - engine_set_log_prefix(name); - c = lxc_container_new(name, tmp_path); - if (c == NULL) { - ERROR("Failed to pause container"); - engine_free_log_prefix(); - return false; - } - - if (!is_container_exists(c)) { - ERROR("No such container"); - bret = false; - goto out_put; - } - - if (!is_container_can_control(c)) { - ERROR("Insufficent privleges to contol"); - bret = false; - goto out_put; - } - - if (!c->freeze(c)) { - ERROR("Failed to pause"); - bret = false; - goto out_put; - } - -out_put: - lxc_container_put(c); - engine_free_log_prefix(); - return bret; -} - -bool lcr_resume(const char *name, const char *lcrpath) -{ - struct lxc_container *c = NULL; - const char *tmp_path = lcrpath ? lcrpath : LCRPATH; - bool bret = false; - - clear_error_message(&g_lcr_error); - if (name == NULL) { - ERROR("Missing container name"); - return false; - } - engine_set_log_prefix(name); - c = lxc_container_new(name, tmp_path); - if (c == NULL) { - ERROR("Failed to resume container"); - goto out; - } - - if (!is_container_exists(c)) { - ERROR("No such container"); - goto out_put; - } - - if (!is_container_can_control(c)) { - ERROR("Insufficent privleges to contol"); - goto out_put; - } - - if (!c->unfreeze(c)) { - ERROR("Failed to resume"); - goto out_put; - } - - bret = true; - -out_put: - lxc_container_put(c); -out: - engine_free_log_prefix(); - return bret; -} - -bool lcr_resize(const char *name, const char *lcrpath, unsigned int height, unsigned int width) -{ - struct lxc_container *c = NULL; - const char *tmp_path = lcrpath ? lcrpath : LCRPATH; - bool bret = true; - - clear_error_message(&g_lcr_error); - - if (name == NULL) { - ERROR("Missing container name"); - return false; - } - - engine_set_log_prefix(name); - c = lxc_container_new(name, tmp_path); - if (c == NULL) { - ERROR("Failed to pause container"); - engine_free_log_prefix(); - return false; - } - - if (!is_container_exists(c)) { - ERROR("No such container"); - bret = false; - goto out_put; - } - - if (!is_container_can_control(c)) { - ERROR("Insufficent privleges to contol"); - bret = false; - goto out_put; - } - - if (!lcr_check_container_running(c, name)) { - bret = false; - goto out_put; - } - - if (!c->set_terminal_winch(c, height, width)) { - ERROR("Failed to pause"); - bret = false; - goto out_put; - } - -out_put: - lxc_container_put(c); - engine_free_log_prefix(); - return bret; -} - -bool lcr_exec_resize(const char *name, const char *lcrpath, const char *suffix, unsigned int height, unsigned int width) -{ - struct lxc_container *c = NULL; - const char *tmp_path = lcrpath ? lcrpath : LCRPATH; - bool bret = true; - - clear_error_message(&g_lcr_error); - - if (name == NULL) { - ERROR("Missing container name"); - return false; - } - - engine_set_log_prefix(name); - c = lxc_container_new(name, tmp_path); - if (c == NULL) { - ERROR("Failed to pause container"); - engine_free_log_prefix(); - return false; - } - - if (!is_container_exists(c)) { - ERROR("No such container"); - bret = false; - goto out_put; - } - - if (!is_container_can_control(c)) { - ERROR("Insufficent privleges to contol"); - bret = false; - goto out_put; - } - - if (!lcr_check_container_running(c, name)) { - bret = false; - goto out_put; - } - - if (!c->set_exec_terminal_winch(c, suffix, height, width)) { - ERROR("Failed to resize exec terminal"); - bret = false; - goto out_put; - } - -out_put: - lxc_container_put(c); - engine_free_log_prefix(); - return bret; -} - -bool lcr_console(const char *name, const char *lcrpath, const char *in_fifo, const char *out_fifo, const char *err_fifo) -{ - struct lxc_container *c = NULL; - const char *tmp_path = lcrpath ? lcrpath : LCRPATH; - bool bresult = true; - - clear_error_message(&g_lcr_error); - if (name == NULL) { - ERROR("Missing container name"); - return false; - } - engine_set_log_prefix(name); - - c = lxc_container_new(name, tmp_path); - if (c == NULL) { - ERROR("Failed to create container."); - bresult = false; - goto out; - } - - if (!is_container_exists(c)) { - ERROR("No such container"); - bresult = false; - goto out_put; - } - - if (!is_container_can_control(c)) { - ERROR("Insufficent privleges to contol"); - lcr_set_error_message(LCR_ERR_RUNTIME, "Insufficent privleges to contol"); - bresult = false; - goto out_put; - } - - if (!c->is_running(c)) { - ERROR("It's not running"); - lcr_set_error_message(LCR_ERR_RUNTIME, "You cannot attach to a stopped container, start it first"); - bresult = false; - goto out_put; - } - - bresult = c->add_terminal_fifos(c, in_fifo, out_fifo, err_fifo); - -out_put: - lxc_container_put(c); -out: - engine_free_log_prefix(); - return bresult; -} - -static char *lcr_get_config_item(struct lxc_container *c, const char *key, bool running) -{ - char *cret = NULL; - size_t len = 0; - int nret = 0; - - if (key == NULL) { - ERROR("Key cannot be NULL"); - return cret; - } - - if (running) { - if (!c->is_running(c)) { - ERROR("It's not running"); - goto out; - } - cret = c->get_running_config_item(c, key); - goto out; - } - - nret = c->get_config_item(c, key, NULL, 0); - if (nret <= 0) { - ERROR("get config item length failed"); - goto out; - } - - len = (size_t)(nret); - if (len > SIZE_MAX / sizeof(char) - 1) { - ERROR("Config item length is too long!"); - goto out; - } - - cret = lcr_util_common_calloc_s((len + 1) * sizeof(char)); - if (cret == NULL) { - ERROR("Out of memory"); - goto out; - } - - if ((size_t)c->get_config_item(c, key, cret, (int)len + 1) != len) { - free(cret); - cret = NULL; - } - -out: - return cret; -} - -void lcr_free_console_config(struct lcr_console_config *config) -{ - free(config->log_path); - config->log_path = NULL; - free(config->log_file_size); - config->log_file_size = NULL; - config->log_rotate = 0; -} - -static bool lcr_get_console_config_items(struct lxc_container *c, struct lcr_console_config *config) -{ - bool ret = true; - char *item = NULL; - unsigned int trotate = 0; - - config->log_path = lcr_get_config_item(c, "lxc.console.logfile", false); - if (config->log_path == NULL) { - DEBUG("Log path is NULL"); - } - config->log_file_size = lcr_get_config_item(c, "lxc.console.size", false); - if (config->log_file_size == 0) { - DEBUG("Log file size is 0"); - } - - item = lcr_get_config_item(c, "lxc.console.rotate", false); - if (item == NULL) { - DEBUG("Log rotate is NULL"); - } else { - if (lcr_util_safe_uint(item, &trotate) == 0) { - config->log_rotate = trotate; - } else { - ERROR("trans to uint failed"); - ret = false; - } - free(item); - } - return ret; -} - -bool lcr_get_console_config(const char *name, const char *lcrpath, struct lcr_console_config *config) -{ - bool ret = true; - struct lxc_container *c = NULL; - const char *tmp_path = lcrpath ? lcrpath : LCRPATH; - - clear_error_message(&g_lcr_error); - if (name == NULL || lcrpath == NULL || config == NULL) { - ERROR("Parameter is NULL"); - return false; - } - engine_set_log_prefix(name); - c = lxc_container_new(name, tmp_path); - if (c == NULL) { - ERROR("Failed to create container."); - engine_free_log_prefix(); - return false; - } - - if (!is_container_exists(c)) { - ERROR("No such container"); - lcr_set_error_message(LCR_ERR_RUNTIME, "No such container:%s or the configuration files has been corrupted", - name); - ret = false; - goto out_put; - } - if (!is_container_can_control(c)) { - ERROR("Insufficent privleges to contol"); - goto out_put; - } - - ret = lcr_get_console_config_items(c, config); - if (!ret) { - lcr_free_console_config(config); - } - -out_put: - lxc_container_put(c); - engine_free_log_prefix(); - return ret; -} - -bool lcr_update(const char *name, const char *lcrpath, const struct lcr_cgroup_resources *cr) -{ - struct lxc_container *c = NULL; - bool bret = false; - const char *tmp_path = NULL; - - clear_error_message(&g_lcr_error); - if (name == NULL || cr == NULL) { - ERROR("Invalid input"); - return false; - } - engine_set_log_prefix(name); - - tmp_path = lcrpath ? lcrpath : LCRPATH; - if (access(tmp_path, O_RDONLY) < 0) { - ERROR("You lack permission to access %s", tmp_path); - engine_free_log_prefix(); - return false; - } - - c = lxc_container_new(name, tmp_path); - if (c == NULL) { - ERROR("Failed to new container."); - goto out_free; - } - - if (!is_container_exists(c)) { - ERROR("No such container"); - goto out_put; - } - - if (!is_container_can_control(c)) { - ERROR("Insufficent privileges to control"); - goto out_put; - } - - if (c->is_running(c) && cr->kernel_memory_limit) { - ERROR("Can not update kernel memory to a running container, please stop it first"); - goto out_put; - } - - if (!do_update(c, name, tmp_path, (struct lcr_cgroup_resources *)cr)) { - goto out_put; - } - - bret = true; - -out_put: - lxc_container_put(c); - -out_free: - engine_free_log_prefix(); - if (!bret) { - lcr_try_set_error_message(LCR_ERR_RUNTIME, "Runtime error when updating cgroup"); - } - return bret; -} - -const char *lcr_get_errmsg() -{ - if (g_lcr_error.errcode == LCR_SUCCESS) { - return errno_to_error_message(LCR_SUCCESS); - } - if (g_lcr_error.errcode == LCR_ERR_MEMOUT) { - return errno_to_error_message(LCR_ERR_MEMOUT); - } - if (g_lcr_error.errcode == LCR_ERR_FORMAT) { - return errno_to_error_message(LCR_ERR_FORMAT); - } - return (const char *)g_lcr_error.errmsg; -} - -void lcr_free_errmsg() -{ - clear_error_message(&g_lcr_error); -} - -int lcr_log_init(const char *name, const char *file, const char *priority, const char *prefix, int quiet, - const char *lcrpath) -{ - char *full_path = NULL; - char *pre_name = "fifo:"; - size_t pre_len = 0; - struct engine_log_config lconf = { 0 }; - struct lxc_log lxc_log_conf = { 0 }; - - pre_len = strlen(pre_name); - lconf.name = "engine"; - if (file == NULL || strncmp(file, pre_name, pre_len) != 0) { - lconf.file = NULL; - lconf.driver = "stdout"; - lconf.priority = priority ? priority : "ERROR"; - } else { - /* File has prefix "fifo:", */ - full_path = lcr_util_string_split_prefix(pre_len, file); - lconf.file = full_path; - lconf.driver = "fifo"; - lconf.priority = priority; - } - if (engine_log_enable(&lconf)) { - fprintf(stderr, "Failed to init log"); - goto out; - } - if (full_path != NULL) { - free(full_path); - } - - lxc_log_conf.name = name; - lxc_log_conf.lxcpath = lcrpath; - lxc_log_conf.file = file; - lxc_log_conf.level = priority; - lxc_log_conf.prefix = prefix; - lxc_log_conf.quiet = quiet > 0 ? true : false; - return lxc_log_init(&lxc_log_conf); -out: - free(full_path); - return -1; -} - diff --git a/src/lcrcontainer.h b/src/lcrcontainer.h deleted file mode 100644 index 2132a33..0000000 --- a/src/lcrcontainer.h +++ /dev/null @@ -1,298 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide container definition - ******************************************************************************/ -/* - * liblcrapi - */ - -#ifndef __LCR_CONTAINER_H -#define __LCR_CONTAINER_H -#include -#include -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -/* define console log config */ - -struct lcr_console_config { - char *log_path; - unsigned int log_rotate; - char *log_file_size; -}; - -/* - * Store lcr container info - */ -struct lcr_container_info { - /* Name of container. */ - char *name; - /* State of container. */ - char *state; - /* Interface of container. */ - char *interface; - char *ipv4; - char *ipv6; - pid_t init; - double ram; - double swap; - bool running; -}; - -struct blkio_stats { - uint64_t read; - uint64_t write; - uint64_t total; -}; - -/* - * Store lcr container state - */ -struct lcr_container_state { - /* Name of container */ - char *name; - /* State of container */ - char *state; - /* The process ID of the init container */ - pid_t init; - /* Current pids */ - uint64_t pids_current; - /* CPU usage */ - uint64_t cpu_use_nanos; - uint64_t cpu_use_user; - uint64_t cpu_use_sys; - /* BlkIO usage */ - struct blkio_stats io_service_bytes; - struct blkio_stats io_serviced; - /* Memory usage */ - uint64_t mem_used; - uint64_t mem_limit; - /* Kernel Memory usage */ - uint64_t kmem_used; - uint64_t kmem_limit; -}; - -typedef enum { - lcr_msg_state, - lcr_msg_priority, - lcr_msg_exit_code, -} lcr_msg_type_t; - -struct lcr_msg { - lcr_msg_type_t type; - char name[NAME_MAX + 1]; - int value; - int pid; -}; - -struct lcr_cgroup_resources { - uint64_t blkio_weight; - uint64_t cpu_shares; - uint64_t cpu_period; - uint64_t cpu_quota; - char *cpuset_cpus; - char *cpuset_mems; - uint64_t memory_limit; - uint64_t memory_swap; - uint64_t memory_reservation; - uint64_t kernel_memory_limit; -}; - -/* - * Get one container info for a given lcrpath. - * return struct of container info, or NULL on error. - */ -struct lcr_container_info *lcr_container_info_get(const char *name, const char *lcrpath); - -/* - * Free lcr_container_info returned lcr_container_info_get - */ -void lcr_container_info_free(struct lcr_container_info *info); - -/* - * Get a complete list of all containers for a given lcrpath. - * return Number of containers, or -1 on error. - */ -int lcr_list_all_containers(const char *lcrpath, struct lcr_container_info **info_arr); - -/* - * Free lcr_container_info array returned by lcr_list_{active,all}_containers - */ -void lcr_containers_info_free(struct lcr_container_info **info_arr, size_t size); - -/* - * Create a container - * param name : container name - * param lcrpath: container path - * param rootfs : the path of rootfs used for the container - * param oci_config_data : json string of oci config data - */ -bool lcr_create(const char *name, const char *lcrpath, void *oci_config); - -/* - * Start a container - * param name : container name, required. - * param lcrpath : container path, set to NULL if you want use default lcrpath. - * param logpath : log file path. - * param loglevel : log level. - * param pidfile : container pidfile path, set to NULL if you don't need. - * param daemonize : daemonize the container. - * console_fifos[] : path of the console fifos,[0]:input, [1]:output.used internal by iSulad - * console_logpath :path of console log file, - * set to NULL if want to use the default configure(base on the config file) - set to PATH(for example "/home/XX/XX.log"), LXC will save the console to this file - * share_ns : array of container's name or pid which want to share namespace with them - * start_timeout : seconds for waiting on a container to start before it is killed - * container_pidfile : container's pidfile - * param argv : array of arguments to pass to init. - * uid : user to run container - * gid : user in which group - * additional_gids : Add additional groups to join - */ -struct lcr_start_request { - const char *name; - const char *lcrpath; - - const char *logpath; - const char *loglevel; - - bool daemonize; - bool tty; - bool open_stdin; - const char **console_fifos; - uint32_t start_timeout; - const char *container_pidfile; - const char *exit_fifo; -}; -bool lcr_start(const struct lcr_start_request *request); - -/* - * Stop a container - * param name : container name, required. - * param lcrpath : container path, set to NULL if you want use default lcrpath. - * param signal : signal to send to the container. - */ -bool lcr_kill(const char *name, const char *lcrpath, uint32_t signal); - -/* - * Delete a container - * param name : container name, required. - * param lcrpath : container path, set to NULL if you want use default lcrpath. - * param force : force to delete container - */ -bool lcr_delete(const char *name, const char *lcrpath); - -bool lcr_clean(const char *name, const char *lcrpath, const char *logpath, const char *loglevel, pid_t pid); - -/* - * Get state of the container - * param name : container name, required. - * param lcrpath : container path, set to NULL if you want use default lcrpath. - * param lcs : returned contaiener state - */ -bool lcr_state(const char *name, const char *lcrpath, struct lcr_container_state *lcs); - -/* - * Pause a container - * param name : container name, required. - * param lcrpath : container path, set to NULL if you want use default lcrpath. - */ -bool lcr_pause(const char *name, const char *lcrpath); - -/* - * Resume a container - * param name : container name, required. - * param lcrpath : container path, set to NULL if you want use default lcrpath. - */ -bool lcr_resume(const char *name, const char *lcrpath); - -/* - * Free lcr_container_state returned by lcr_state - */ -void lcr_container_state_free(struct lcr_container_state *lcs); - -/* - * console function - * param name : name of container - * param lcrpath : container path, set to NULL if you want use default lcrpath. - * param in_fifo : fifo names of input FIFO - * param out_fifo : fifo names of output FIFO - * Returns false if the console FIFOs add failed, true if success - */ -bool lcr_console(const char *name, const char *lcrpath, const char *in_fifo, const char *out_fifo, - const char *err_fifo); - -/* - * get container console configs - * param name : name of container - * param lcrpath : container path, set to NULL if you want use default lcrpath. - * param config : use to store container console configs, cannot be NULL - */ -bool lcr_get_console_config(const char *name, const char *lcrpath, struct lcr_console_config *config); - -void lcr_free_console_config(struct lcr_console_config *config); - -int lcr_log_init(const char *name, const char *file, const char *priority, - const char *prefix, int quiet, const char *lcrpath); - -struct lcr_exec_request { - const char *name; - const char *lcrpath; - - const char *logpath; - const char *loglevel; - - const char **console_fifos; - - const char *user; - - const char **env; - size_t env_len; - const char **args; - size_t args_len; - - int64_t timeout; - - const char *suffix; - - bool tty; - bool open_stdin; -}; -/* - * Execute process inside a container - */ -bool lcr_exec(const struct lcr_exec_request *request, int *exit_code); - -bool lcr_update(const char *name, const char *lcrpath, const struct lcr_cgroup_resources *cr); - -const char *lcr_get_errmsg(); - -void lcr_free_errmsg(); - -bool lcr_get_container_pids(const char *name, const char *lcrpath, pid_t **pids, size_t *pids_len); - -bool lcr_resize(const char *name, const char *lcrpath, unsigned int height, unsigned int width); -bool lcr_exec_resize(const char *name, const char *lcrpath, const char *suffix, unsigned int height, - unsigned int width); -#ifdef __cplusplus -} -#endif - -#endif /* __LCR_CONTAINER_H */ diff --git a/src/lcrcontainer_execute.c b/src/lcrcontainer_execute.c deleted file mode 100644 index 69b69ab..0000000 --- a/src/lcrcontainer_execute.c +++ /dev/null @@ -1,750 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide container definition - ******************************************************************************/ -/* - * liblcrapi - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include - -#include "constants.h" -#include "lcrcontainer_execute.h" -#include "utils.h" -#include "log.h" -#include "error.h" -#include "oci_runtime_spec.h" -#include "lcrcontainer_extend.h" - -// Cgroup Item Definition -#define CGROUP_BLKIO_WEIGHT "blkio.weight" -#define CGROUP_CPU_SHARES "cpu.shares" -#define CGROUP_CPU_PERIOD "cpu.cfs_period_us" -#define CGROUP_CPU_QUOTA "cpu.cfs_quota_us" -#define CGROUP_CPUSET_CPUS "cpuset.cpus" -#define CGROUP_CPUSET_MEMS "cpuset.mems" -#define CGROUP_MEMORY_LIMIT "memory.limit_in_bytes" -#define CGROUP_MEMORY_SWAP "memory.memsw.limit_in_bytes" -#define CGROUP_MEMORY_RESERVATION "memory.soft_limit_in_bytes" - -#define REPORT_SET_CGROUP_ERROR(item, value) \ - do { \ - SYSERROR("Error updating cgroup %s to %s", (item), (value)); \ - lcr_set_error_message(LCR_ERR_RUNTIME, "Error updating cgroup %s to %s: %s", (item), (value), \ - strerror(errno)); \ - } while (0) - -static inline void add_array_elem(char **array, size_t total, size_t *pos, const char *elem) -{ - if (*pos + 1 >= total - 1) { - return; - } - array[*pos] = lcr_util_strdup_s(elem); - *pos += 1; -} - -static inline void add_array_kv(char **array, size_t total, size_t *pos, const char *k, const char *v) -{ - if (k == NULL || v == NULL) { - return; - } - add_array_elem(array, total, pos, k); - add_array_elem(array, total, pos, v); -} - -static uint64_t stat_get_ull(struct lxc_container *c, const char *item) -{ - char buf[80] = { 0 }; - int len = 0; - uint64_t val = 0; - - len = c->get_cgroup_item(c, item, buf, sizeof(buf)); - if (len <= 0) { - DEBUG("unable to read cgroup item %s", item); - return 0; - } - - val = strtoull(buf, NULL, 0); - return val; -} - -static bool update_resources_cpuset_mems(struct lxc_container *c, const struct lcr_cgroup_resources *cr) -{ - bool ret = false; - - if (cr->cpuset_mems != NULL && strcmp(cr->cpuset_mems, "") != 0) { - if (!c->set_cgroup_item(c, CGROUP_CPUSET_MEMS, cr->cpuset_mems)) { - REPORT_SET_CGROUP_ERROR(CGROUP_CPUSET_MEMS, cr->cpuset_mems); - goto err_out; - } - } - ret = true; -err_out: - return ret; -} - -static bool update_resources_cpuset(struct lxc_container *c, const struct lcr_cgroup_resources *cr) -{ - bool ret = false; - if (cr->cpuset_cpus != NULL && strcmp(cr->cpuset_cpus, "") != 0) { - if (!c->set_cgroup_item(c, CGROUP_CPUSET_CPUS, cr->cpuset_cpus)) { - REPORT_SET_CGROUP_ERROR(CGROUP_CPUSET_CPUS, cr->cpuset_cpus); - goto err_out; - } - } - - ret = true; -err_out: - return ret; -} - -static int update_resources_cpu_shares(struct lxc_container *c, const struct lcr_cgroup_resources *cr) -{ - int ret = 0; - char numstr[128] = { 0 }; /* max buffer */ - - if (cr->cpu_shares != 0) { - int num = snprintf(numstr, sizeof(numstr), "%llu", (unsigned long long)(cr->cpu_shares)); - if (num < 0 || (size_t)num >= sizeof(numstr)) { - ret = -1; - goto out; - } - - if (!c->set_cgroup_item(c, CGROUP_CPU_SHARES, numstr)) { - REPORT_SET_CGROUP_ERROR(CGROUP_CPU_SHARES, numstr); - ret = -1; - goto out; - } - } - -out: - return ret; -} - -static int update_resources_cpu_period(struct lxc_container *c, const struct lcr_cgroup_resources *cr) -{ - int ret = 0; - char numstr[128] = { 0 }; /* max buffer */ - - if (cr->cpu_period != 0) { - int num = snprintf(numstr, sizeof(numstr), "%llu", (unsigned long long)(cr->cpu_period)); - if (num < 0 || (size_t)num >= sizeof(numstr)) { - ret = -1; - goto out; - } - - if (!c->set_cgroup_item(c, CGROUP_CPU_PERIOD, numstr)) { - REPORT_SET_CGROUP_ERROR(CGROUP_CPU_PERIOD, numstr); - ret = -1; - goto out; - } - } - -out: - return ret; -} - -static int update_resources_cpu_quota(struct lxc_container *c, const struct lcr_cgroup_resources *cr) -{ - int ret = 0; - char numstr[128] = { 0 }; /* max buffer */ - - if (cr->cpu_quota != 0) { - int num = snprintf(numstr, sizeof(numstr), "%llu", (unsigned long long)(cr->cpu_quota)); - if (num < 0 || (size_t)num >= sizeof(numstr)) { - ret = -1; - goto out; - } - - if (!c->set_cgroup_item(c, CGROUP_CPU_QUOTA, numstr)) { - REPORT_SET_CGROUP_ERROR(CGROUP_CPU_QUOTA, numstr); - ret = -1; - goto out; - } - } - -out: - return ret; -} - -static bool update_resources_cpu(struct lxc_container *c, const struct lcr_cgroup_resources *cr) -{ - bool ret = false; - - if (update_resources_cpu_shares(c, cr) != 0) { - goto err_out; - } - - if (update_resources_cpu_period(c, cr) != 0) { - goto err_out; - } - - if (update_resources_cpu_quota(c, cr) != 0) { - goto err_out; - } - - if (!update_resources_cpuset(c, cr)) { - goto err_out; - } - - if (!update_resources_cpuset_mems(c, cr)) { - goto err_out; - } - - ret = true; -err_out: - return ret; -} - -static int update_resources_memory_limit(struct lxc_container *c, const struct lcr_cgroup_resources *cr) -{ - int ret = 0; - char numstr[128] = { 0 }; /* max buffer */ - - if (cr->memory_limit != 0) { - int num = snprintf(numstr, sizeof(numstr), "%llu", (unsigned long long)(cr->memory_limit)); - if (num < 0 || (size_t)num >= sizeof(numstr)) { - ret = -1; - goto out; - } - - if (!c->set_cgroup_item(c, CGROUP_MEMORY_LIMIT, numstr)) { - REPORT_SET_CGROUP_ERROR(CGROUP_MEMORY_LIMIT, numstr); - ret = -1; - goto out; - } - } - -out: - return ret; -} - -static int update_resources_memory_swap(struct lxc_container *c, const struct lcr_cgroup_resources *cr) -{ - int ret = 0; - char numstr[128] = { 0 }; /* max buffer */ - - if (cr->memory_swap != 0) { - int num = snprintf(numstr, sizeof(numstr), "%llu", (unsigned long long)(cr->memory_swap)); - if (num < 0 || (size_t)num >= sizeof(numstr)) { - ret = -1; - goto out; - } - - if (!c->set_cgroup_item(c, CGROUP_MEMORY_SWAP, numstr)) { - REPORT_SET_CGROUP_ERROR(CGROUP_MEMORY_SWAP, numstr); - ret = -1; - goto out; - } - } - -out: - return ret; -} - -static int update_resources_memory_reservation(struct lxc_container *c, const struct lcr_cgroup_resources *cr) -{ - int ret = 0; - char numstr[128] = { 0 }; /* max buffer */ - - if (cr->memory_reservation != 0) { - int num = snprintf(numstr, sizeof(numstr), "%llu", (unsigned long long)(cr->memory_reservation)); - if (num < 0 || (size_t)num >= sizeof(numstr)) { - ret = -1; - goto out; - } - - if (!c->set_cgroup_item(c, CGROUP_MEMORY_RESERVATION, numstr)) { - REPORT_SET_CGROUP_ERROR(CGROUP_MEMORY_RESERVATION, numstr); - ret = -1; - goto out; - } - } - -out: - return ret; -} - -static bool update_resources_mem(struct lxc_container *c, struct lcr_cgroup_resources *cr) -{ - bool ret = false; - - // If the memory update is set to -1 we should also set swap to -1, it means unlimited memory. - if (cr->memory_limit == -1) { - cr->memory_swap = -1; - } - - if (cr->memory_limit != 0 && cr->memory_swap != 0) { - uint64_t cur_mem_limit = stat_get_ull(c, "memory.limit_in_bytes"); - if (cr->memory_swap == -1 || cur_mem_limit < cr->memory_swap) { - if (update_resources_memory_swap(c, cr) != 0) { - goto err_out; - } - if (update_resources_memory_limit(c, cr) != 0) { - goto err_out; - } - } else { - if (update_resources_memory_limit(c, cr) != 0) { - goto err_out; - } - if (update_resources_memory_swap(c, cr) != 0) { - goto err_out; - } - } - } else { - if (update_resources_memory_limit(c, cr) != 0) { - goto err_out; - } - if (update_resources_memory_swap(c, cr) != 0) { - goto err_out; - } - } - - if (update_resources_memory_reservation(c, cr) != 0) { - goto err_out; - } - - ret = true; -err_out: - return ret; -} - -static int update_resources_blkio_weight(struct lxc_container *c, const struct lcr_cgroup_resources *cr) -{ - int ret = 0; - char numstr[128] = { 0 }; /* max buffer */ - - if (cr->blkio_weight != 0) { - int num = snprintf(numstr, sizeof(numstr), "%llu", (unsigned long long)(cr->blkio_weight)); - if (num < 0 || (size_t)num >= sizeof(numstr)) { - ret = -1; - goto out; - } - - if (!c->set_cgroup_item(c, CGROUP_BLKIO_WEIGHT, numstr)) { - REPORT_SET_CGROUP_ERROR(CGROUP_BLKIO_WEIGHT, numstr); - ret = -1; - goto out; - } - } - -out: - return ret; -} - -static bool update_resources(struct lxc_container *c, struct lcr_cgroup_resources *cr) -{ - bool ret = false; - - if (c == NULL || cr == NULL) { - return false; - } - - if (update_resources_blkio_weight(c, cr) != 0) { - goto err_out; - } - - if (!update_resources_cpu(c, cr)) { - goto err_out; - } - if (!update_resources_mem(c, cr)) { - goto err_out; - } - - ret = true; -err_out: - return ret; -} - -bool do_update(struct lxc_container *c, const char *name, const char *lcrpath, struct lcr_cgroup_resources *cr) -{ - bool bret = false; - - // If container is not running, update config file is enough, - // resources will be updated when the container is started again. - // If container is running (including paused), we need to update configs - // to the real world. - if (c->is_running(c)) { - if (!update_resources(c, cr) && c->is_running(c)) { - ERROR("Filed to update cgroup resources"); - goto out_free; - } - } - - bret = true; - -out_free: - if (bret) { - clear_error_message(&g_lcr_error); - } - return bret; -} - -static inline bool is_blk_stat_read(const char *value) -{ - return strcmp(value, "Read") == 0; -} - -static inline bool is_blk_stat_write(const char *value) -{ - return strcmp(value, "Write") == 0; -} - -static inline bool is_blk_stat_total(const char *value) -{ - return strcmp(value, "Total") == 0; -} - -static void stat_get_blk_stats(struct lxc_container *c, const char *item, struct blkio_stats *stats) -{ - char buf[BUFSIZE] = { 0 }; - int i = 0; - size_t len = 0; - char **lines = NULL; - char **cols = NULL; - - len = (size_t)c->get_cgroup_item(c, item, buf, sizeof(buf)); - if (len == 0 || len >= sizeof(buf)) { - DEBUG("unable to read cgroup item %s", item); - return; - } - - lines = lcr_string_split_and_trim(buf, '\n'); - if (lines == NULL) { - return; - } - - (void)memset(stats, 0, sizeof(struct blkio_stats)); - - for (i = 0; lines[i]; i++) { - cols = lcr_string_split_and_trim(lines[i], ' '); - if (cols == NULL) { - goto err_out; - } - if (is_blk_stat_read(cols[1])) { - stats->read += strtoull(cols[2], NULL, 0); - } else if (is_blk_stat_write(cols[1])) { - stats->write += strtoull(cols[2], NULL, 0); - } - if (is_blk_stat_total(cols[0])) { - stats->total = strtoull(cols[1], NULL, 0); - } - - lcr_free_array((void **)cols); - } -err_out: - lcr_free_array((void **)lines); - return; -} - -static uint64_t stat_match_get_ull(struct lxc_container *c, const char *item, const char *match, int column) -{ - char buf[BUFSIZE] = { 0 }; - int i = 0; - int j = 0; - int len = 0; - uint64_t val = 0; - char **lines = NULL; - char **cols = NULL; - size_t matchlen = 0; - - len = c->get_cgroup_item(c, item, buf, sizeof(buf)); - if (len <= 0) { - DEBUG("unable to read cgroup item %s", item); - goto err_out; - } - - lines = lcr_string_split_and_trim(buf, '\n'); - if (lines == NULL) { - goto err_out; - } - - matchlen = strlen(match); - for (i = 0; lines[i]; i++) { - if (strncmp(lines[i], match, matchlen) != 0) { - continue; - } - - cols = lcr_string_split_and_trim(lines[i], ' '); - if (cols == NULL) { - goto err1; - } - for (j = 0; cols[j]; j++) { - if (j == column) { - val = strtoull(cols[j], NULL, 0); - break; - } - } - lcr_free_array((void **)cols); - break; - } -err1: - lcr_free_array((void **)lines); -err_out: - return val; -} - -void do_lcr_state(struct lxc_container *c, struct lcr_container_state *lcs) -{ - const char *state = NULL; - - clear_error_message(&g_lcr_error); - (void)memset(lcs, 0x00, sizeof(struct lcr_container_state)); - - lcs->name = lcr_util_strdup_s(c->name); - - state = c->state(c); - lcs->state = state ? lcr_util_strdup_s(state) : lcr_util_strdup_s("-"); - - if (c->is_running(c)) { - lcs->init = c->init_pid(c); - } else { - lcs->init = -1; - } - - lcs->cpu_use_nanos = stat_get_ull(c, "cpuacct.usage"); - lcs->pids_current = stat_get_ull(c, "pids.current"); - - lcs->cpu_use_user = stat_match_get_ull(c, "cpuacct.stat", "user", 1); - lcs->cpu_use_sys = stat_match_get_ull(c, "cpuacct.stat", "system", 1); - - // Try to read CFQ stats available on all CFQ enabled kernels first - stat_get_blk_stats(c, "blkio.io_serviced_recursive", &lcs->io_serviced); - if (lcs->io_serviced.read == 0 && lcs->io_serviced.write == 0 && lcs->io_serviced.total == 0) { - stat_get_blk_stats(c, "blkio.throttle.io_service_bytes", &lcs->io_service_bytes); - stat_get_blk_stats(c, "blkio.throttle.io_serviced", &lcs->io_serviced); - } else { - stat_get_blk_stats(c, "blkio.io_service_bytes_recursive", &lcs->io_service_bytes); - } - - lcs->mem_used = stat_get_ull(c, "memory.usage_in_bytes"); - lcs->mem_limit = stat_get_ull(c, "memory.limit_in_bytes"); - lcs->kmem_used = stat_get_ull(c, "memory.kmem.usage_in_bytes"); - lcs->kmem_limit = stat_get_ull(c, "memory.kmem.limit_in_bytes"); -} - -#define ExitSignalOffset 128 - -static void execute_lxc_attach(const char *name, const char *path, const struct lcr_exec_request *request) -{ - // should check the size of params when add new params. - char **params = NULL; - size_t i = 0; - size_t j = 0; - size_t args_len = PARAM_NUM; - - if (lcr_util_check_inherited(true, -1) != 0) { - COMMAND_ERROR("Close inherited fds failed"); - exit(EXIT_FAILURE); - } - - args_len = args_len + request->args_len + request->env_len; - - if (args_len > (SIZE_MAX / sizeof(char *))) { - exit(EXIT_FAILURE); - } - - params = lcr_util_common_calloc_s(args_len * sizeof(char *)); - if (params == NULL) { - COMMAND_ERROR("Out of memory"); - exit(EXIT_FAILURE); - } - add_array_elem(params, args_len, &i, "lxc-attach"); - add_array_elem(params, args_len, &i, "-n"); - add_array_elem(params, args_len, &i, name); - add_array_elem(params, args_len, &i, "-P"); - add_array_elem(params, args_len, &i, path); - add_array_elem(params, args_len, &i, "--clear-env"); - add_array_elem(params, args_len, &i, "--quiet"); - add_array_kv(params, args_len, &i, "--logfile", request->logpath); - add_array_kv(params, args_len, &i, "-l", request->loglevel); - add_array_kv(params, args_len, &i, "--in-fifo", request->console_fifos[0]); - add_array_kv(params, args_len, &i, "--out-fifo", request->console_fifos[1]); - add_array_kv(params, args_len, &i, "--err-fifo", request->console_fifos[2]); - for (j = 0; j < request->env_len; j++) { - add_array_elem(params, args_len, &i, "-v"); - add_array_elem(params, args_len, &i, request->env[j]); - } - - if (request->timeout != 0) { - char timeout_str[LCR_NUMSTRLEN64] = { 0 }; - add_array_elem(params, args_len, &i, "--timeout"); - int num = snprintf(timeout_str, LCR_NUMSTRLEN64, "%lld", (long long)request->timeout); - if (num < 0 || num >= LCR_NUMSTRLEN64) { - COMMAND_ERROR("Invaild attach timeout value :%lld", (long long)request->timeout); - free(params); - exit(EXIT_FAILURE); - } - add_array_elem(params, args_len, &i, timeout_str); - } - - if (request->user != NULL) { - add_array_elem(params, args_len, &i, "-u"); - add_array_elem(params, args_len, &i, request->user); - } - - add_array_kv(params, args_len, &i, "--suffix", request->suffix); - - if (!request->tty) { - add_array_elem(params, args_len, &i, "--disable-pty"); - } - if (request->open_stdin) { - add_array_elem(params, args_len, &i, "--open-stdin"); - } - - add_array_elem(params, args_len, &i, "--"); - for (j = 0; j < request->args_len; j++) { - add_array_elem(params, args_len, &i, request->args[j]); - } - - execvp("lxc-attach", params); - - COMMAND_ERROR("Failed to exec lxc-attach: %s", strerror(errno)); - free(params); - exit(EXIT_FAILURE); -} - -static int do_attach_get_exit_code(int status) -{ - int exit_code = 0; - - if (WIFEXITED(status)) { - exit_code = WEXITSTATUS(status); - } else { - exit_code = -1; - } - - if (WIFSIGNALED(status)) { - int signal; - signal = WTERMSIG(status); - exit_code = ExitSignalOffset + signal; - } - return exit_code; -} - -bool do_attach(const char *name, const char *path, const struct lcr_exec_request *request, int *exit_code) -{ - bool ret = false; - pid_t pid = 0; - ssize_t size_read = 0; - char buffer[BUFSIZ] = { 0 }; - int pipefd[2] = { -1, -1 }; - int status = 0; - - if (pipe(pipefd) != 0) { - ERROR("Failed to create pipe\n"); - return false; - } - - pid = fork(); - if (pid == (pid_t) - 1) { - ERROR("Failed to fork()\n"); - close(pipefd[0]); - close(pipefd[1]); - goto out; - } - - if (pid == (pid_t)0) { - if (lcr_util_null_stdfds() < 0) { - COMMAND_ERROR("Failed to close fds"); - exit(EXIT_FAILURE); - } - setsid(); - - // child process, dup2 pipefd[1] to stderr - close(pipefd[0]); - dup2(pipefd[1], 2); - - execute_lxc_attach(name, path, request); - } - - close(pipefd[1]); - - status = lcr_wait_for_pid_status(pid); - if (status < 0) { - ERROR("Failed to wait lxc-attach"); - goto close_out; - } - - *exit_code = do_attach_get_exit_code(status); - - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - size_read = read(pipefd[0], buffer, BUFSIZ); - /* if we read errmsg means the runtime failed to exec */ - if (size_read > 0) { - ERROR("Runtime error: %s", buffer); - lcr_set_error_message(LCR_ERR_RUNTIME, "runtime error: %s", buffer); - goto close_out; - } - } - ret = true; - -close_out: - close(pipefd[0]); -out: - return ret; -} - -void execute_lxc_start(const char *name, const char *path, const struct lcr_start_request *request) -{ - // should check the size of params when add new params. - char *params[PARAM_NUM] = { NULL }; - size_t i = 0; - - if (lcr_util_check_inherited(true, -1) != 0) { - COMMAND_ERROR("Close inherited fds failed"); - } - - add_array_elem(params, PARAM_NUM, &i, "lxc-start"); - add_array_elem(params, PARAM_NUM, &i, "-n"); - add_array_elem(params, PARAM_NUM, &i, name); - add_array_elem(params, PARAM_NUM, &i, "-P"); - add_array_elem(params, PARAM_NUM, &i, path); - add_array_elem(params, PARAM_NUM, &i, "--quiet"); - add_array_kv(params, PARAM_NUM, &i, "--logfile", request->logpath); - add_array_kv(params, PARAM_NUM, &i, "-l", request->loglevel); - add_array_kv(params, PARAM_NUM, &i, "--in-fifo", request->console_fifos[0]); - add_array_kv(params, PARAM_NUM, &i, "--out-fifo", request->console_fifos[1]); - add_array_kv(params, PARAM_NUM, &i, "--err-fifo", request->console_fifos[2]); - if (!request->tty) { - add_array_elem(params, PARAM_NUM, &i, "--disable-pty"); - } - if (request->open_stdin) { - add_array_elem(params, PARAM_NUM, &i, "--open-stdin"); - } - add_array_elem(params, PARAM_NUM, &i, request->daemonize ? "-d" : "-F"); - add_array_kv(params, PARAM_NUM, &i, "--container-pidfile", request->container_pidfile); - add_array_kv(params, PARAM_NUM, &i, "--exit-fifo", request->exit_fifo); - - if (request->start_timeout != 0) { - char start_timeout_str[LCR_NUMSTRLEN64] = { 0 }; - add_array_elem(params, PARAM_NUM, &i, "--start-timeout"); - int num = snprintf(start_timeout_str, LCR_NUMSTRLEN64, "%u", request->start_timeout); - if (num < 0 || num >= LCR_NUMSTRLEN64) { - COMMAND_ERROR("Invaild start timeout value: %u", request->start_timeout); - exit(EXIT_FAILURE); - } - add_array_elem(params, PARAM_NUM, &i, start_timeout_str); - } - - execvp("lxc-start", params); - - COMMAND_ERROR("Failed to exec lxc-start\n"); - exit(EXIT_FAILURE); -} diff --git a/src/lcrcontainer_execute.h b/src/lcrcontainer_execute.h deleted file mode 100644 index 8e7738d..0000000 --- a/src/lcrcontainer_execute.h +++ /dev/null @@ -1,36 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide container definition - ******************************************************************************/ -#ifndef __LCR_CONTAINER_EXECUTE_H -#define __LCR_CONTAINER_EXECUTE_H - -#include "lcrcontainer.h" - -#ifdef __cplusplus -extern "C" { -#endif - -bool do_update(struct lxc_container *c, const char *name, const char *lcrpath, struct lcr_cgroup_resources *cr); - -void do_lcr_state(struct lxc_container *c, struct lcr_container_state *lcs); - -bool do_attach(const char *name, const char *path, const struct lcr_exec_request *request, int *exit_code); - -void execute_lxc_start(const char *name, const char *path, const struct lcr_start_request *request); - -#ifdef __cplusplus -} -#endif - -#endif /* __LCR_CONTAINER_EXECUTE_H */ diff --git a/src/lcrcontainer_extend.c b/src/lcrcontainer_extend.c deleted file mode 100644 index c0e001a..0000000 --- a/src/lcrcontainer_extend.c +++ /dev/null @@ -1,1081 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide container definition - ******************************************************************************/ -/* - * liblcrapi - */ - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include - -#include - -#include "constants.h" -#include "error.h" -#include "lcrcontainer.h" -#include "lcrcontainer_extend.h" -#include "utils.h" -#include "log.h" -#include "conf.h" -#include "oci_runtime_hooks.h" - -static struct lxc_container *lcr_new_container(const char *name, const char *path) -{ - struct lxc_container *c = lxc_container_new(name, path); - if (c == NULL) { - ERROR("Failed to delete container."); - return NULL; - } - - if (!c->is_defined(c)) { - ERROR("No such container"); - lcr_set_error_message(LCR_ERR_RUNTIME, "No such container:%s or the configuration files has been corrupted", - name); - goto out_put; - } - - if (!c->may_control(c)) { - ERROR("Insufficent privileges to control"); - goto out_put; - } - return c; -out_put: - lxc_container_put(c); - return NULL; -} - -static int realloc_annotations(oci_runtime_spec *oci_spec, size_t new_lens) -{ - size_t new_size = 0; - unsigned long old_size = 0; - char **fkey = NULL; - char **fval = NULL; - int nret = 0; - - if (new_lens < 1) { - return 0; - } - - if (!oci_spec->annotations) { - oci_spec->annotations = lcr_util_common_calloc_s(sizeof(json_map_string_string)); - if (!oci_spec->annotations) { - ERROR("Out of memory"); - nret = -1; - goto out; - } - } - - if (new_lens > SIZE_MAX / sizeof(char *) - oci_spec->annotations->len) { - ERROR("Too many annotations!"); - nret = -1; - goto out; - } - new_size = (oci_spec->annotations->len + new_lens) * sizeof(char *); - old_size = oci_spec->annotations->len * sizeof(char *); - nret = lcr_mem_realloc((void **)&fkey, new_size, oci_spec->annotations->keys, old_size); - if (nret) { - ERROR("Failed to realloc memory for files limit variables"); - nret = -1; - goto out; - } - oci_spec->annotations->keys = fkey; - - nret = lcr_mem_realloc((void **)&fval, new_size, oci_spec->annotations->values, old_size); - if (nret) { - ERROR("Failed to realloc memory for files limit variables"); - nret = -1; - goto out; - } - oci_spec->annotations->values = fval; - oci_spec->annotations->len += new_lens; - -out: - return nret; -} - -static int make_annotations(oci_runtime_spec *container, const struct lxc_container *c, int fpos) -{ - int ret = -1; - int nret; - char default_path[PATH_MAX] = { 0 }; - char *realpath = NULL; - json_map_string_string *anno = container->annotations; - - if (fpos == -1) { - if (realloc_annotations(container, 1)) { - ERROR("Realloc annotations failed"); - goto out; - } - fpos = (int)(anno->len - 1); - anno->keys[fpos] = lcr_util_strdup_s("log.console.file"); - anno->values[fpos] = NULL; - } - - if (!anno->values[fpos]) { - nret = snprintf(default_path, PATH_MAX, "%s/%s/%s", c->config_path, c->name, "console.log"); - if (nret < 0 || nret >= PATH_MAX) { - ERROR("create default path: %s failed", default_path); - goto out; - } - if (anno->values[fpos]) { - free(anno->values[fpos]); - } - anno->values[fpos] = lcr_util_strdup_s(default_path); - } - if (strcmp("none", anno->values[fpos]) == 0) { - DEBUG("Disable console log."); - ret = 0; - goto out; - } - if (lcr_util_ensure_path(&realpath, anno->values[fpos])) { - ERROR("Invalid log path: %s, error: %s.", anno->values[fpos], strerror(errno)); - goto out; - } - ret = 0; -out: - free(realpath); - return ret; -} - -static inline bool is_annotations_key_console_file(const char *key) -{ - return strcmp(key, "log.console.file") == 0; -} - -static int check_annotations(oci_runtime_spec *container, const struct lxc_container *c) -{ - size_t i; - int fpos = -1; - bool ret = false; - - if (c == NULL) { - return 0; - } - - if (!container->annotations) { - SAFE_MALLOC(container->annotations, sizeof(json_map_string_string), ret); - if (!ret) { - goto out; - } - } else { - for (i = 0; i < container->annotations->len; i++) { - if (is_annotations_key_console_file(container->annotations->keys[i])) { - fpos = (int)i; - } - } - } - - if (make_annotations(container, c, fpos)) { - goto out; - } - ret = true; -out: - return ret ? 0 : -1; -} - -static int trans_rootfs_linux(struct lcr_list *lcr_conf, oci_runtime_spec *container, - char **seccomp) -{ - int ret = -1; - struct lcr_list *node = NULL; - - /* lxc.rootfs - * lxc.rootfs.options - */ - if (container->root || container->linux) { - node = trans_oci_root(container->root, container->linux); - if (node == NULL) { - ERROR("Failed to translate rootfs configure"); - goto out; - } - lcr_list_merge(lcr_conf, node); - } - - /* lxc.idmap */ - if (container->linux) { - node = trans_oci_linux(container->linux, seccomp); - if (node == NULL) { - ERROR("Failed to translate linux configure"); - goto out; - } - lcr_list_merge(lcr_conf, node); - } - - ret = 0; -out: - return ret; -} - -static int trans_hostname_hooks_process_mounts(struct lcr_list *lcr_conf, const oci_runtime_spec *container) -{ - int ret = -1; - - /* lxc.uts.name */ - struct lcr_list *node = trans_oci_hostname(container->hostname); - if (node == NULL) { - ERROR("Failed to translate hostname"); - goto out; - } - lcr_list_add_tail(lcr_conf, node); - - /* lxc.init_{u|g}id - * lxc.init_cmd - * lxc.environment - * lxc.cap.{drop/keep} - * lxc.limit.* - * lxc.aa_profile - * lxc.selinux.context - */ - node = trans_oci_process(container->process); - if (node == NULL) { - ERROR("Failed to translate hooks"); - goto out; - } - lcr_list_merge(lcr_conf, node); - - /* lxc.mount.entry */ - node = trans_oci_mounts(container); - if (node == NULL) { - ERROR("Failed to translate mount entry configure"); - goto out; - } - lcr_list_merge(lcr_conf, node); - - ret = 0; -out: - return ret; -} - -static bool do_stop_and_wait(struct lxc_container *c, long timeout, bool force) -{ - pid_t pid; - int sret = 0; - bool ret = true; - - pid = c->init_pid(c); - if (pid < 1) { - ERROR("Container is not running"); - return false; - } - - if (!force) { - sret = kill(pid, SIGTERM); - if (sret < 0) { - if (errno == ESRCH) { - return true; - } - } - ret = c->wait(c, "STOPPED", (int)timeout); - if (ret) { - return true; - } - } - - sret = kill(pid, SIGKILL); - if (sret < 0) { - if (errno == ESRCH) { - return true; - } - } - ret = c->wait(c, "STOPPED", -1); - if (!ret) { - ERROR("Failed to stop container %s", c->name); - } - return ret; -} - -static bool do_stop(struct lxc_container *c, long timeout, bool force) -{ - bool ret = true; - - if (force && timeout) { - ERROR("-k should not use with -T"); - return false; - } - - if (!force && timeout < -1) { - ERROR("Timeout should be >= -1"); - return false; - } - - if (!c->is_defined(c)) { - ERROR("No such container"); - ret = false; - goto out; - } - - if (!c->may_control(c)) { - ERROR("Insufficent privleges to contol"); - ret = false; - goto out; - } - - if (!c->is_running(c)) { - DEBUG("%s is already stopped", c->name); - goto out; - } - - ret = do_stop_and_wait(c, timeout, force); - -out: - return ret; -} - -static int lcr_spec_write_seccomp_line(int fd, const char *seccomp) -{ - size_t len; - char *line = NULL; - int ret = -1; - int nret; - - if (strlen(seccomp) > SIZE_MAX - strlen("lxc.seccomp.profile") - 3 - 1) { - ERROR("the length of lxc.seccomp is too long!"); - goto cleanup; - } - - len = strlen("lxc.seccomp.profile") + 3 + strlen(seccomp) + 1; - - line = lcr_util_common_calloc_s(len * sizeof(char)); - if (line == NULL) { - ERROR("Out of memory"); - goto cleanup; - } - - nret = snprintf(line, len, "%s = %s", "lxc.seccomp.profile", seccomp); - if (nret < 0 || (size_t)nret >= len) { - ERROR("Sprintf failed"); - goto cleanup; - } - if ((size_t)nret > len - 1) { - nret = (int)(len - 1); - } - line[nret] = '\n'; - if (write(fd, line, len) == -1) { - SYSERROR("Write failed"); - goto cleanup; - } - ret = 0; -cleanup: - free(line); - return ret; -} - -static char *lcr_save_seccomp_file(const char *bundle, const char *seccomp_conf) -{ - char seccomp[PATH_MAX] = { 0 }; - char *real_seccomp = NULL; - int fd = -1; - int nret; - ssize_t written_cnt; - - nret = snprintf(seccomp, sizeof(seccomp), "%s/seccomp", bundle); - if (nret < 0 || (size_t)nret >= sizeof(seccomp)) { - goto cleanup; - } - - nret = lcr_util_ensure_path(&real_seccomp, seccomp); - if (nret < 0) { - ERROR("Failed to ensure path %s", seccomp); - goto cleanup; - } - - fd = lcr_util_open(real_seccomp, O_CREAT | O_TRUNC | O_CLOEXEC | O_WRONLY, CONFIG_FILE_MODE); - if (fd == -1) { - SYSERROR("Create file %s failed", real_seccomp); - goto cleanup; - } - - written_cnt = write(fd, seccomp_conf, strlen(seccomp_conf)); - close(fd); - if (written_cnt == -1) { - SYSERROR("write seccomp_conf failed"); - goto cleanup; - } - return real_seccomp; -cleanup: - free(real_seccomp); - return NULL; -} - -static struct lcr_container_info *info_new(struct lcr_container_info **info, size_t *size) -{ - struct lcr_container_info *m = NULL; - struct lcr_container_info *n = NULL; - size_t length = 0; - int nret = 0; - - if (*size > SIZE_MAX / sizeof(struct lcr_container_info) - 1) { - return NULL; - } - - length = (*size + 1) * sizeof(struct lcr_container_info); - - nret = lcr_mem_realloc((void **)&n, length, (void *)(*info), (*size) * sizeof(struct lcr_container_info)); - if (nret < 0) { - return NULL; - } - - *info = n; - m = *info + *size; - (*size)++; - - // *INDENT-OFF* - *m = (struct lcr_container_info) { - .name = NULL, .state = NULL, .interface = NULL, .ipv4 = NULL, .ipv6 = NULL, .ram = 0.0, .swap = 0.0, .init = -1 - }; - // *INDENT-ON* - return m; -} - -static void free_arr(char **array, size_t size) -{ - size_t i; - for (i = 0; i < size; i++) { - free(array[i]); - array[i] = NULL; - } - free(array); -} - -/* - * Get a complete list of active containers for a given lcrpath. - * return Number of containers, or -1 on error. - **/ -int lcr_list_active_containers(const char *lcrpath, struct lcr_container_info **info_arr) -{ - char **c = NULL; - int n = 0; - int nret = -1; - size_t info_size = 0; - const char *path = lcrpath ? lcrpath : LCRPATH; - - n = list_active_containers(path, &c, NULL); - if (n == -1) { - n = 0; - } - - nret = lcr_containers_info_get(path, info_arr, &info_size, c, n); - if ((info_arr == NULL) && nret == 0) { - return -1; - } else if ((info_arr == NULL) || nret == -1) { - lcr_containers_info_free(info_arr, info_size); - return -1; - } - - return (int)info_size; -} - -bool lcr_delete_with_force(const char *name, const char *lcrpath, bool force) -{ - struct lxc_container *c = NULL; - const char *path = lcrpath ? lcrpath : LCRPATH; - bool ret = false; - pid_t pid = 0; - - clear_error_message(&g_lcr_error); - if (name == NULL) { - ERROR("Missing container name"); - return false; - } - engine_set_log_prefix(name); - c = lcr_new_container(name, path); - if (c == NULL) { - engine_free_log_prefix(); - return false; - } - - if (c->is_running(c)) { - if (!force) { - ERROR("Container %s is running, Stop the container before remove", name); - lcr_set_error_message(LCR_ERR_RUNTIME, "Container %s is running, Stop the container before remove", name); - goto out_put; - } else { - pid = c->init_pid(c); - if (pid < 1) { - ERROR("Container is not running"); - goto clean_delete; - } - - ret = do_stop(c, 0, true); - if (!ret) { - ERROR("Failed to stop container %s", name); - goto out_put; - } - } - } - -clean_delete: - ret = lcr_clean(name, path, NULL, NULL, pid); - if (!ret) { - ERROR("Failed to clean resource"); - } - ret = lcr_delete(name, path); - if (!ret) { - ERROR("Failed to delete container"); - } - -out_put: - lxc_container_put(c); - engine_free_log_prefix(); - return ret; -} - -void lcr_free_config(struct lcr_list *lcr_conf) -{ - struct lcr_list *it = NULL; - struct lcr_list *next = NULL; - - if (lcr_conf == NULL) { - return; - } - - lcr_list_for_each_safe(it, lcr_conf, next) { - lcr_list_del(it); - free_lcr_list_node(it); - } -} - -int lcr_containers_info_get(const char *lcrpath, struct lcr_container_info **info, size_t *size, char **containers, - int num) -{ - struct lcr_container_info *in = NULL; - struct lxc_container *c = NULL; - int i; - int nret = -1; - - if ((lcrpath == NULL) || num == 0) { - goto err_out; - } - - for (i = 0; i < num; i++) { - const char *st = NULL; - const char *name = containers[i]; - bool run_flag = true; - if (name == NULL) { - continue; - } - - c = lxc_container_without_config_new(name, lcrpath); - if (c == NULL) { - continue; - } - - if (!c->is_defined(c)) { - goto put_container; - } - - st = c->state(c); - if (st == NULL) { - st = "UNKNOWN"; - } - run_flag = (strcmp(st, "STOPPED") != 0); - - /* Now it makes sense to allocate memory */ - in = info_new(info, size); - if (in == NULL) { - goto put_container; - } - in->running = run_flag; - in->name = lcr_util_strdup_s(name); - in->state = lcr_util_strdup_s(st); - if (run_flag) { - in->init = c->init_pid(c); - } -put_container: - lxc_container_put(c); - } - nret = 0; -err_out: - free_arr(containers, (size_t)num); - return nret; -} - -/* - * Transform container JSON into oci_runtime_spec struct - */ -bool container_parse(const char *oci_filename, const char *oci_json_data, oci_runtime_spec **container) -{ - struct parser_context ctx = { OPT_PARSE_STRICT, stderr }; - parser_error err = NULL; - bool ret = true; - - if (oci_json_data == NULL) { - *container = oci_runtime_spec_parse_file(oci_filename, &ctx, &err); - } else { - *container = oci_runtime_spec_parse_data(oci_json_data, &ctx, &err); - } - - if (*container == NULL) { - ERROR("Failed to get OCI spec: %s", err); - ret = false; - goto out_free; - } -out_free: - free(err); - return ret; -} - -static int merge_annotations(const oci_runtime_spec *container, struct lcr_list *lcr_conf) -{ - int ret = 0; - struct lcr_list *tmp = NULL; - - if (container->annotations != NULL) { - tmp = trans_annotations(container->annotations); - if (tmp == NULL) { - ERROR("Failed to translate annotations configure"); - ret = -1; - goto out; - } - lcr_list_merge(lcr_conf, tmp); - } - -out: - return ret; -} - -static int merge_needed_lxc_conf(struct lcr_list *lcr_conf) -{ - int ret = 0; - - struct lcr_list *tmp = get_needed_lxc_conf(); - if (tmp == NULL) { - ERROR("Failed to append other lxc configure"); - ret = -1; - goto out; - } - lcr_list_merge(lcr_conf, tmp); - -out: - return ret; -} - -struct lcr_list *lcr_oci2lcr(const struct lxc_container *c, oci_runtime_spec *container, - char **seccomp) -{ - struct lcr_list *lcr_conf = NULL; - - lcr_conf = lcr_util_common_calloc_s(sizeof(*lcr_conf)); - if (lcr_conf == NULL) { - goto out_free; - } - lcr_list_init(lcr_conf); - - if (check_annotations(container, c)) { - ERROR("Check annotations failed"); - goto out_free; - } - - if (trans_rootfs_linux(lcr_conf, container, seccomp)) { - goto out_free; - } - - if (trans_hostname_hooks_process_mounts(lcr_conf, container)) { - goto out_free; - } - - /* annotations.files.limit */ - if (merge_annotations(container, lcr_conf) != 0) { - goto out_free; - } - - /* Append other lxc configurations */ - if (merge_needed_lxc_conf(lcr_conf) != 0) { - goto out_free; - } - - return lcr_conf; - -out_free: - lcr_free_config(lcr_conf); - free(lcr_conf); - - return NULL; -} - - -static int lcr_open_config_file(const char *bundle) -{ - char config[PATH_MAX] = { 0 }; - char *real_config = NULL; - int fd = -1; - int nret; - - nret = snprintf(config, sizeof(config), "%s/config", bundle); - if (nret < 0 || (size_t)nret >= sizeof(config)) { - goto out; - } - - nret = lcr_util_ensure_path(&real_config, config); - if (nret < 0) { - ERROR("Failed to ensure path %s", config); - goto out; - } - - fd = lcr_util_open(real_config, O_CREAT | O_TRUNC | O_CLOEXEC | O_WRONLY, CONFIG_FILE_MODE); - if (fd == -1) { - ERROR("Create file %s failed, %s", real_config, strerror(errno)); - lcr_set_error_message(LCR_ERR_RUNTIME, "Create file %s failed, %s", real_config, strerror(errno)); - goto out; - } -out: - free(real_config); - return fd; -} - -// escape_string_encode unzip some escape characters -static char *escape_string_encode(const char *src) -{ - size_t src_end = 0; - size_t dst_end = 0; - size_t len = 0; - char *dst = NULL; - - if (src == NULL) { - return NULL; - } - - len = strlen(src); - if (len == 0) { - return NULL; - } - - dst = lcr_util_common_calloc_s(2 * len + 1); - if (dst == NULL) { - ERROR("Out of memory"); - return NULL; - } - - while (src_end < len) { - switch (src[src_end++]) { - case '\r': - dst[dst_end++] = '\\'; - dst[dst_end++] = 'r'; - break; - case '\n': - dst[dst_end++] = '\\'; - dst[dst_end++] = 'n'; - break; - case '\f': - dst[dst_end++] = '\\'; - dst[dst_end++] = 'f'; - break; - case '\b': - dst[dst_end++] = '\\'; - dst[dst_end++] = 'b'; - break; - case '\t': - dst[dst_end++] = '\\'; - dst[dst_end++] = 't'; - break; - case '\\': - dst[dst_end++] = '\\'; - dst[dst_end++] = '\\'; - break; - // default do not encode - default: - dst[dst_end++] = src[src_end - 1]; - break; - } - } - - return dst; -} - -static int lcr_spec_write_config(int fd, const struct lcr_list *lcr_conf) -{ - struct lcr_list *it = NULL; - size_t len; - char *line = NULL; - char *line_encode = NULL; - int ret = -1; - - lcr_list_for_each(it, lcr_conf) { - lcr_config_item_t *item = it->elem; - int nret; - if (item != NULL) { - if (strlen(item->value) > ((SIZE_MAX - strlen(item->name)) - 4)) { - goto cleanup; - } - len = strlen(item->name) + 3 + strlen(item->value) + 1; - line = lcr_util_common_calloc_s(len); - if (line == NULL) { - ERROR("Out of memory"); - goto cleanup; - } - - nret = snprintf(line, len, "%s = %s", item->name, item->value); - if (nret < 0 || (size_t)nret >= len) { - ERROR("Sprintf failed"); - goto cleanup; - } - - line_encode = escape_string_encode(line); - if (line_encode == NULL) { - ERROR("String encode failed"); - goto cleanup; - } - - nret = strlen(line_encode); - - line_encode[nret] = '\n'; - if (write(fd, line_encode, nret + 1) == -1) { - SYSERROR("Write failed"); - goto cleanup; - } - free(line); - line = NULL; - free(line_encode); - line_encode = NULL; - } - } - ret = 0; -cleanup: - free(line); - free(line_encode); - return ret; -} - -char *lcr_get_bundle(const char *lcrpath, const char *name) -{ - size_t len = 0; - int nret = 0; - char *bundle = NULL; - struct stat s; - - if (strlen(name) > ((SIZE_MAX - strlen(lcrpath)) - 2)) { - goto cleanup; - } - - /* bundle = lcrpath + '/' + name + '\0' */ - len = strlen(lcrpath) + strlen(name) + 2; - bundle = lcr_util_common_calloc_s(len); - if (bundle == NULL) { - ERROR("Out of memory"); - goto cleanup; - } - - nret = snprintf(bundle, len, "%s/%s", lcrpath, name); - if (nret < 0 || (size_t)nret >= len) { - ERROR("Print bundle string failed"); - goto cleanup; - } - - if (stat(bundle, &s) != 0) { - switch (errno) { - case EACCES: - ERROR("You lack permission to access %s", bundle); - break; - case ENOENT: - ERROR("Bundle %s does not exist", bundle); - break; - default: - ERROR("Access %s failed: %s\n", bundle, strerror(errno)); - } - goto cleanup; - } - return bundle; -cleanup: - free(bundle); - return NULL; -} - -bool lcr_save_spec(const char *name, const char *lcrpath, const struct lcr_list *lcr_conf, const char *seccomp_conf) -{ - bool bret = false; - const char *path = lcrpath ? lcrpath : LCRPATH; - char *bundle = NULL; - char *seccomp = NULL; - int fd = -1; - int nret = 0; - - if (name == NULL) { - ERROR("Missing container name"); - return bret; - } - - bundle = lcr_get_bundle(path, name); - if (bundle == NULL) { - goto out_free; - } - - if (seccomp_conf != NULL) { - seccomp = lcr_save_seccomp_file(bundle, seccomp_conf); - if (seccomp == NULL) { - goto out_free; - } - } - - fd = lcr_open_config_file(bundle); - if (fd == -1) { - goto out_free; - } - - if (lcr_spec_write_config(fd, lcr_conf)) { - goto out_free; - } - - if (seccomp_conf != NULL) { - nret = lcr_spec_write_seccomp_line(fd, seccomp); - if (nret) { - goto out_free; - } - } - - bret = true; - -out_free: - free(bundle); - free(seccomp); - if (fd != -1) { - close(fd); - } - - return bret; -} - -static int lcr_write_file(const char *path, const char *data, size_t len) -{ - char *real_path = NULL; - int fd = -1; - int ret = -1; - - if (path == NULL || strlen(path) == 0 || data == NULL || len == 0) { - return -1; - } - - if (lcr_util_ensure_path(&real_path, path) < 0) { - ERROR("Failed to ensure path %s", path); - goto out_free; - } - - fd = lcr_util_open(real_path, O_CREAT | O_TRUNC | O_CLOEXEC | O_WRONLY, CONFIG_FILE_MODE); - if (fd == -1) { - ERROR("Create file %s failed", real_path); - lcr_set_error_message(LCR_ERR_RUNTIME, "Create file %s failed", real_path); - goto out_free; - } - - if (write(fd, data, len) == -1) { - ERROR("write data to %s failed: %s", real_path, strerror(errno)); - goto out_free; - } - - ret = 0; - -out_free: - if (fd != -1) { - close(fd); - } - free(real_path); - return ret; -} - - -static bool lcr_write_ocihooks(const char *path, const oci_runtime_spec_hooks *hooks) -{ - bool ret = false; - struct parser_context ctx = { OPT_PARSE_STRICT, stderr }; - parser_error err = NULL; - - char *json_hooks = oci_runtime_spec_hooks_generate_json(hooks, &ctx, &err); - if (json_hooks == NULL) { - ERROR("Failed to generate json: %s", err); - goto out_free; - } - - if (lcr_write_file(path, json_hooks, strlen(json_hooks)) == -1) { - ERROR("write json hooks failed: %s", strerror(errno)); - goto out_free; - } - - ret = true; - -out_free: - free(err); - free(json_hooks); - - return ret; -} - -static bool lcr_save_ocihooks(const char *name, const char *lcrpath, const oci_runtime_spec_hooks *hooks) -{ - const char *path = lcrpath ? lcrpath : LCRPATH; - char ocihook[PATH_MAX] = { 0 }; - char *bundle = NULL; - bool bret = false; - int nret = 0; - - if (name == NULL) { - ERROR("Missing name"); - return false; - } - - bundle = lcr_get_bundle(path, name); - if (bundle == NULL) { - return false; - } - - nret = snprintf(ocihook, sizeof(ocihook), "%s/%s", bundle, OCIHOOKSFILE); - if (nret < 0 || (size_t)nret >= sizeof(ocihook)) { - ERROR("Failed to print string"); - goto out_free; - } - - bret = lcr_write_ocihooks(ocihook, hooks); - -out_free: - free(bundle); - return bret; -} - -bool translate_spec(const struct lxc_container *c, oci_runtime_spec *container) -{ - bool ret = false; - struct lcr_list *lcr_conf = NULL; - char *seccomp_conf = NULL; - - INFO("Translate new specification file"); - - lcr_conf = lcr_oci2lcr(c, container, &seccomp_conf); - if (lcr_conf == NULL) { - ERROR("Translate configuration failed"); - goto out_free_conf; - } - - if (container->hooks != NULL && !lcr_save_ocihooks(c->name, c->config_path, container->hooks)) { - ERROR("Failed to save %s", OCIHOOKSFILE); - goto out_free_conf; - } - - if (!lcr_save_spec(c->name, c->config_path, lcr_conf, seccomp_conf)) { - ERROR("Failed to save configuration"); - goto out_free_conf; - } - - ret = true; - -out_free_conf: - lcr_free_config(lcr_conf); - free(lcr_conf); - - free(seccomp_conf); - return ret; -} - diff --git a/src/lcrcontainer_extend.h b/src/lcrcontainer_extend.h deleted file mode 100644 index e67e340..0000000 --- a/src/lcrcontainer_extend.h +++ /dev/null @@ -1,87 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide container definition - ******************************************************************************/ -#ifndef __LCR_CONTAINER_EXTEND_H -#define __LCR_CONTAINER_EXTEND_H - -#include - -#include "oci_runtime_spec.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* defined in `lcr_list.h` */ -struct lcr_list; - -#define SAFE_MALLOC(P, size, ret) \ - do { \ - (P) = lcr_util_common_calloc_s((size)); \ - if ((P) == NULL) { \ - ERROR("Out of memory"); \ - (ret) = false; \ - } \ - } while (0); - -/* - * Get a complete list of active containers for a given lcrpath. - * return Number of containers, or -1 on error. - */ -int lcr_list_active_containers(const char *lcrpath, struct lcr_container_info **info_arr); - -/* - * Delete a container - * param name : container name, required. - * param lcrpath : container path, set to NULL if you want use default lcrpath. - * param force : force to delete container - */ -bool lcr_delete_with_force(const char *name, const char *lcrpath, bool force); - -/* - * Free lcr_conf - */ -void lcr_free_config(struct lcr_list *lcr_conf); - -bool container_parse(const char *oci_filename, const char *oci_json_data, oci_runtime_spec **container); - -/* - * Translate oci specification to lcr configuration. - * You should pass oci_filename or oci_spec to this function. - * return: a linked list - */ -struct lcr_list *lcr_oci2lcr(const struct lxc_container *c, oci_runtime_spec *container, - char **seccomp); - -/* - * Create a new specification file - * param name : container name, required. - * param lcrpath : container path, set to NULL if you want use default lcrpath. - * param lcr_conf : generate specification according to lcr_conf list - * param seccomp_conf : seccomp_conf will be wrote into seccomp file, set it to NULL if you don't need - */ -bool lcr_save_spec(const char *name, const char *lcrpath, const struct lcr_list *lcr_conf, const char *seccomp_conf); - -int lcr_containers_info_get(const char *lcrpath, struct lcr_container_info **info, size_t *size, char **containers, - int num); - -char *lcr_get_bundle(const char *lcrpath, const char *name); - -bool translate_spec(const struct lxc_container *c, oci_runtime_spec *container); - -#ifdef __cplusplus -} -#endif - -#endif /* __LCR_CONTAINER_EXTEND_H */ diff --git a/src/log.c b/src/log.c deleted file mode 100644 index f3b1249..0000000 --- a/src/log.c +++ /dev/null @@ -1,386 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved. - * engine 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: wujing - * Create: 2019-4-08 - * Description: provide container log functions - ******************************************************************************/ -#define _GNU_SOURCE -#define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "utils.h" -#include "log.h" - -const char * const g_engine_log_prio_name[] = { - "FATAL", "ALERT", "CRIT", "ERROR", "WARN", "NOTICE", "INFO", "DEBUG", "TRACE" -}; - -#define MAX_MSG_LENGTH 4096 -#define MAX_LOG_PREFIX_LENGTH 15 - -static __thread char *g_engine_log_prefix = NULL; - -static char *g_engine_log_module = NULL; -static int g_engine_log_level = ENGINE_LOG_DEBUG; -static int g_engine_log_driver = LOG_DRIVER_STDOUT; -int g_engine_log_fd = -1; - -/* engine set log prefix */ -void engine_set_log_prefix(const char *prefix) -{ - if (prefix == NULL) { - return; - } - - free(g_engine_log_prefix); - g_engine_log_prefix = lcr_util_strdup_s(prefix); -} - -/* engine free log prefix */ -void engine_free_log_prefix(void) -{ - free(g_engine_log_prefix); - g_engine_log_prefix = NULL; -} - -static ssize_t write_nointr(int fd, const void *buf, size_t count); - -static void do_fifo_log(const struct engine_log_object_metadata *metadata, const char *timestamp, - const char *msg); - -static void do_stderr_log(const struct engine_log_object_metadata *metadata, const char *timestamp, - const char *msg); - -/* engine change str logdriver to enum */ -static int engine_change_str_logdriver_to_enum(const char *driver) -{ - if (driver == NULL) { - return LOG_DRIVER_NOSET; - } - if (strcasecmp(driver, "stdout") == 0) { - return LOG_DRIVER_STDOUT; - } - if (strcasecmp(driver, "fifo") == 0) { - return LOG_DRIVER_FIFO; - } - - return -1; -} - -#define LOG_FIFO_SIZE (1024 * 1024) - -/* open fifo */ -static int open_fifo(const char *fifo_path) -{ - int nret; - int fifo_fd = -1; - - nret = mknod(fifo_path, S_IFIFO | S_IRUSR | S_IWUSR, (dev_t)0); - if (nret && errno != EEXIST) { - COMMAND_ERROR("Mknod failed: %s", strerror(errno)); - return nret; - } - - fifo_fd = lcr_util_open(fifo_path, O_RDWR | O_NONBLOCK, 0); - if (fifo_fd == -1) { - COMMAND_ERROR("Open fifo %s failed: %s", fifo_path, strerror(errno)); - return -1; - } - - if (fcntl(fifo_fd, F_SETPIPE_SZ, LOG_FIFO_SIZE) == -1) { - COMMAND_ERROR("Set fifo buffer size failed: %s", strerror(errno)); - close(fifo_fd); - return -1; - } - - return fifo_fd; -} - -/* init log driver */ -static int init_log_driver(const struct engine_log_config *log) -{ - int i, driver; - - for (i = ENGINE_LOG_FATAL; i < ENGINE_LOG_MAX; i++) { - if (strcasecmp(g_engine_log_prio_name[i], log->priority) == 0) { - g_engine_log_level = i; - break; - } - } - - if (i == ENGINE_LOG_MAX) { - COMMAND_ERROR("Unable to parse logging level:%s", log->priority); - return -1; - } - - driver = engine_change_str_logdriver_to_enum(log->driver); - if (driver < 0) { - COMMAND_ERROR("Invalid log driver: %s", log->driver); - return -1; - } - g_engine_log_driver = driver; - return 0; -} - -static inline bool check_log_config_args(const struct engine_log_config *log) -{ - return (log == NULL || log->name == NULL || log->priority == NULL); -} - -static int do_check_log_configs(const struct engine_log_config *log) -{ - bool invalid_arg = false; - - if (check_log_config_args(log)) { - COMMAND_ERROR("Invalid arguments"); - return -1; - } - - invalid_arg = ((log->file == NULL) && (g_engine_log_driver == LOG_DRIVER_FIFO)); - if (invalid_arg) { - COMMAND_ERROR("Must set log file for driver %s", log->driver); - return -1; - } - return 0; -} - -/* log enable */ -int engine_log_enable(const struct engine_log_config *log) -{ - int nret = 0; - char *full_path = NULL; - - if (g_engine_log_fd != -1) { - COMMAND_ERROR("engine log already initialized"); - return 0; - } - - nret = do_check_log_configs(log); - if (nret != 0) { - return -1; - } - - nret = init_log_driver(log); - if (nret != 0) { - return -1; - } - - free(g_engine_log_module); - g_engine_log_module = lcr_util_strdup_s(log->name); - - full_path = lcr_util_strdup_s(log->file); - - nret = lcr_util_build_dir(full_path); - if (nret != 0) { - COMMAND_ERROR("failed to create dir for log file"); - goto out; - } - - g_engine_log_fd = open_fifo(full_path); - if (g_engine_log_fd == -1) { - nret = -1; - } - -out: - if (nret != 0) { - if (g_engine_log_driver == LOG_DRIVER_FIFO) { - g_engine_log_driver = LOG_DRIVER_NOSET; - } - } - free(full_path); - - return nret; -} - -static int do_log_by_driver(const struct engine_log_object_metadata *metadata, const char *msg, - const char *date_time) -{ - switch (g_engine_log_driver) { - case LOG_DRIVER_STDOUT: - do_stderr_log(metadata, date_time, msg); - break; - case LOG_DRIVER_FIFO: - if (g_engine_log_fd == -1) { - COMMAND_ERROR("Do not set log file\n"); - return -1; - } - do_fifo_log(metadata, date_time, msg); - break; - case LOG_DRIVER_NOSET: - break; - default: - COMMAND_ERROR("Invalid log driver\n"); - return -1; - } - return 0; -} - -static char *parse_timespec_to_human() -{ - struct timespec timestamp; - struct tm ptm = {0}; - char date_time[ENGINE_LOG_TIME_STR_MAX_LEN] = { 0 }; - int nret; -#define SEC_TO_NSEC 1000000 -#define FIRST_YEAR_OF_GMT 1900 - - if (clock_gettime(CLOCK_REALTIME, ×tamp) == -1) { - COMMAND_ERROR("Failed to get real time"); - return 0; - } - - if (localtime_r(&(timestamp.tv_sec), &ptm) == NULL) { - SYSERROR("Transfer timespec failed"); - return NULL; - } - - nret = snprintf(date_time, ENGINE_LOG_TIME_STR_MAX_LEN, "%04d%02d%02d%02d%02d%02d.%03ld", - ptm.tm_year + FIRST_YEAR_OF_GMT, ptm.tm_mon + 1, ptm.tm_mday, ptm.tm_hour, ptm.tm_min, ptm.tm_sec, - timestamp.tv_nsec / SEC_TO_NSEC); - - if (nret < 0 || nret >= ENGINE_LOG_TIME_STR_MAX_LEN) { - COMMAND_ERROR("Sprintf failed"); - return NULL; - } - - return lcr_util_strdup_s(date_time); -} - -/* use to add log to driver */ -int engine_log(const struct engine_log_object_metadata *metadata, const char *format, ...) -{ - int rc; - char msg[MAX_MSG_LENGTH] = { 0 }; - va_list args; - char *date_time = NULL; - int ret = 0; - - va_start(args, format); - rc = vsnprintf(msg, MAX_MSG_LENGTH, format, args); - va_end(args); - if (rc < 0) { - rc = snprintf(msg, MAX_MSG_LENGTH, "%s", "!!LONG LONG A LOG!!"); - if (rc < 0) { - return 0; - } - } - - date_time = parse_timespec_to_human(); - if (date_time == NULL) { - goto out; - } - - ret = do_log_by_driver(metadata, msg, date_time); - -out: - free(date_time); - return ret; -} - -static void do_write_log_into_file(int log_fd, char *log_msg, size_t max_len, size_t write_size) -{ - size_t size = 0; - - size = write_size; - if (size > (max_len - 1)) { - size = max_len - 1; - } - - log_msg[size] = '\n'; - - if (write_nointr(log_fd, log_msg, (size + 1)) == -1) { - COMMAND_ERROR("write log into logfile failed"); - } -} - -/* log append logfile */ -static void do_fifo_log(const struct engine_log_object_metadata *metadata, const char *timestamp, - const char *msg) -{ - char log_buffer[ENGINE_LOG_BUFFER_SIZE] = { 0 }; - int log_fd = -1; - int nret; - size_t size; - char *tmp_prefix = NULL; - - if (metadata->level > g_engine_log_level) { - return; - } - log_fd = g_engine_log_fd; - if (log_fd == -1) { - return; - } - - tmp_prefix = g_engine_log_prefix ? g_engine_log_prefix : g_engine_log_module; - if (tmp_prefix != NULL && strlen(tmp_prefix) > MAX_LOG_PREFIX_LENGTH) { - tmp_prefix = tmp_prefix + (strlen(tmp_prefix) - MAX_LOG_PREFIX_LENGTH); - } - nret = snprintf(log_buffer, sizeof(log_buffer), "%15s %s %-8s %s:%s:%d - %s", tmp_prefix ? tmp_prefix : "", - timestamp, g_engine_log_prio_name[metadata->level], metadata->file, - metadata->func, metadata->line, msg); - - if (nret < 0) { - nret = snprintf(log_buffer, sizeof(log_buffer), "%15s %s %-8s %s:%s:%d - %s", - tmp_prefix ? tmp_prefix : "", timestamp, g_engine_log_prio_name[metadata->level], - metadata->file, metadata->func, metadata->line, "Large log message"); - if (nret < 0) { - return; - } - } - size = (size_t)nret; - - do_write_log_into_file(log_fd, log_buffer, sizeof(log_buffer), size); -} - -/* log append stderr */ -static void do_stderr_log(const struct engine_log_object_metadata *metadata, const char *timestamp, - const char *msg) -{ - char *tmp_prefix = NULL; - if (metadata->level > g_engine_log_level) { - return; - } - - tmp_prefix = g_engine_log_prefix ? g_engine_log_prefix : g_engine_log_module; - if (tmp_prefix != NULL && strlen(tmp_prefix) > MAX_LOG_PREFIX_LENGTH) { - tmp_prefix = tmp_prefix + (strlen(tmp_prefix) - MAX_LOG_PREFIX_LENGTH); - } - COMMAND_ERROR("%15s %s %-8s ", tmp_prefix ? tmp_prefix : "", timestamp, g_engine_log_prio_name[metadata->level]); - COMMAND_ERROR("%s:%s:%d - ", metadata->file, metadata->func, metadata->line); - COMMAND_ERROR("%s\n", msg); -} - -/* write nointr */ -static ssize_t write_nointr(int fd, const void *buf, size_t count) -{ - ssize_t nret; - for (;;) { - nret = write(fd, buf, count); - if (nret < 0 && errno == EINTR) { - continue; - } else { - break; - } - } - return nret; -} - diff --git a/src/log.h b/src/log.h deleted file mode 100644 index 14e0c9a..0000000 --- a/src/log.h +++ /dev/null @@ -1,124 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved. - * engine 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: wujing - * Create: 2019-4-08 - * Description: provide container log functions - ******************************************************************************/ -#ifndef __ENGINE_LOG_H -#define __ENGINE_LOG_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef O_CLOEXEC -#define O_CLOEXEC 02000000 -#endif - -#define ENGINE_LOG_BUFFER_SIZE 4096 - -#define ENGINE_LOG_TIME_STR_MAX_LEN 21 - -enum engine_log_drivers { - LOG_DRIVER_STDOUT, - LOG_DRIVER_FIFO, - LOG_DRIVER_NOSET, -}; - -enum engine_log_level { - ENGINE_LOG_FATAL = 0, - ENGINE_LOG_ALERT, - ENGINE_LOG_CRIT, - ENGINE_LOG_ERROR, - ENGINE_LOG_WARN, - ENGINE_LOG_NOTICE, - ENGINE_LOG_INFO, - ENGINE_LOG_DEBUG, - ENGINE_LOG_TRACE, - ENGINE_LOG_MAX -}; - -struct engine_log_config { - const char *name; - const char *file; - const char *priority; - const char *prefix; - const char *driver; -}; - -/* brief logging event object */ -struct engine_log_object_metadata { - /* location information of the logging item */ - const char *file; - const char *func; - int line; - - int level; -}; - -int engine_log_enable(const struct engine_log_config *log); - -void engine_set_log_prefix(const char *prefix); - -void engine_free_log_prefix(void); - -int engine_log(const struct engine_log_object_metadata *metadata, const char *format, ...); - -#define COMMON_LOG(loglevel, format, ...) \ - do { \ - struct engine_log_object_metadata meta = { \ - .file = __FILENAME__, .func = __func__, .line = __LINE__, .level = loglevel, \ - }; \ - (void)engine_log(&meta, format, ##__VA_ARGS__); \ - } while (0) - -#define DEBUG(format, ...) \ - COMMON_LOG(ENGINE_LOG_DEBUG, format, ##__VA_ARGS__) - -#define INFO(format, ...) \ - COMMON_LOG(ENGINE_LOG_INFO, format, ##__VA_ARGS__) - -#define NOTICE(format, ...) \ - COMMON_LOG(ENGINE_LOG_NOTICE, format, ##__VA_ARGS__) - -#define WARN(format, ...) \ - COMMON_LOG(ENGINE_LOG_WARN, format, ##__VA_ARGS__) - -#define ERROR(format, ...) \ - COMMON_LOG(ENGINE_LOG_ERROR, format, ##__VA_ARGS__) - -#define CRIT(format, ...) \ - COMMON_LOG(ENGINE_LOG_CRIT, format, ##__VA_ARGS__) - -#define ALERT(format, ...) \ - COMMON_LOG(ENGINE_LOG_ALERT, format, ##__VA_ARGS__) - -#define FATAL(format, ...) \ - COMMON_LOG(ENGINE_LOG_FATAL, format, ##__VA_ARGS__) - -#define SYSERROR(format, ...) \ - do { \ - ERROR("%s - " format, strerror(errno), ##__VA_ARGS__); \ - } while (0) - -#define COMMAND_ERROR(fmt, args...) \ - do { \ - (void)fprintf(stderr, fmt "\n", ##args); \ - } while (0) - -#ifdef __cplusplus -} -#endif - -#endif /* __ENGINE_LOG_H */ diff --git a/src/utils.c b/src/utils.c deleted file mode 100644 index 5efe381..0000000 --- a/src/utils.c +++ /dev/null @@ -1,1252 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide container utils functions - ******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "constants.h" -#include "utils.h" -#include "log.h" - -#define ISSLASH(C) ((C) == '/') -#define IS_ABSOLUTE_FILE_NAME(F) (ISSLASH((F)[0])) -#define IS_RELATIVE_FILE_NAME(F) (!IS_ABSOLUTE_FILE_NAME(F)) - -static bool do_clean_path_continue(const char *endpos, const char *stpos, const char *respath, char **dst) -{ - if (endpos - stpos == 1 && stpos[0] == '.') { - return true; - } else if (endpos - stpos == 2 && stpos[0] == '.' && stpos[1] == '.') { - char *dest = *dst; - if (dest <= respath + 1) { - return true; - } - for (--dest; dest > respath && !ISSLASH(dest[-1]); --dest) { - continue; - } - *dst = dest; - return true; - } - return false; -} - -static int do_clean_path(const char *respath, const char *limit_respath, const char *stpos, char **dst) -{ - char *dest = *dst; - const char *endpos = stpos; - - for (; *stpos; stpos = endpos) { - while (ISSLASH(*stpos)) { - ++stpos; - } - - for (endpos = stpos; *endpos && !ISSLASH(*endpos); ++endpos) { - } - - if (endpos - stpos == 0) { - break; - } else if (do_clean_path_continue(endpos, stpos, respath, &dest)) { - continue; - } - - if (!ISSLASH(dest[-1])) { - *dest++ = '/'; - } - - if (dest + (endpos - stpos) >= limit_respath) { - ERROR("Path is too long"); - if (dest > respath + 1) { - dest--; - } - *dest = '\0'; - return -1; - } - - (void)memcpy(dest, stpos, (size_t)(endpos - stpos)); - dest += endpos - stpos; - *dest = '\0'; - } - *dst = dest; - return 0; -} - -static char *cleanpath(const char *path, char *realpath, size_t realpath_len) -{ - char *respath = NULL; - char *dest = NULL; - const char *stpos = NULL; - const char *limit_respath = NULL; - - if (path == NULL || path[0] == '\0' || realpath == NULL || (realpath_len < PATH_MAX)) { - return NULL; - } - - respath = realpath; - - (void)memset(respath, 0, realpath_len); - limit_respath = respath + PATH_MAX; - - if (!IS_ABSOLUTE_FILE_NAME(path)) { - if (!getcwd(respath, PATH_MAX)) { - ERROR("Failed to getcwd"); - respath[0] = '\0'; - goto error; - } - dest = strchr(respath, '\0'); - if (dest == NULL) { - ERROR("Failed to get the end of respath"); - goto error; - } - if (strlen(path) >= (PATH_MAX - 1) - strlen(respath)) { - ERROR("%s path too long", path); - goto error; - } - (void)strcat(respath, path); - stpos = path; - } else { - dest = respath; - *dest++ = '/'; - stpos = path; - } - - if (do_clean_path(respath, limit_respath, stpos, &dest)) { - goto error; - } - - if (dest > respath + 1 && ISSLASH(dest[-1])) { - --dest; - } - *dest = '\0'; - - return respath; - -error: - return NULL; -} - -/* wait for pid */ -int lcr_wait_for_pid(pid_t pid) -{ - int st; - int nret = 0; - -again: - nret = waitpid(pid, &st, 0); - if (nret == -1) { - if (errno == EINTR) { - goto again; - } - return -1; - } - if (nret != pid) { - goto again; - } - if (!WIFEXITED(st) || WEXITSTATUS(st) != 0) { - return -1; - } - return 0; -} - -/* wait for pid status */ -int lcr_wait_for_pid_status(pid_t pid) -{ - int st; - int nret = 0; -rep: - nret = waitpid(pid, &st, 0); - if (nret == -1) { - if (errno == EINTR) { - goto rep; - } - return -1; - } - - if (nret != pid) { - goto rep; - } - return st; -} - -static char *do_string_join(const char *sep, const char **parts, size_t parts_len, size_t result_len) -{ - size_t iter; - - char *res_string = calloc(result_len + 1, 1); - if (res_string == NULL) { - return NULL; - } - for (iter = 0; iter < parts_len - 1; iter++) { - (void)strcat(res_string, parts[iter]); - (void)strcat(res_string, sep); - } - (void)strcat(res_string, parts[parts_len - 1]); - return res_string; -} - -char *lcr_util_string_join(const char *sep, const char **parts, size_t len) -{ - size_t sep_len; - size_t result_len; - size_t iter; - - if (len == 0 || parts == NULL || sep == NULL) { - return NULL; - } - - sep_len = strlen(sep); - - if ((sep_len != 0) && (sep_len != 1) && (len > SIZE_MAX / sep_len + 1)) { - return NULL; - } - result_len = (len - 1) * sep_len; - for (iter = 0; iter < len; iter++) { - if (parts[iter] == NULL || result_len >= SIZE_MAX - strlen(parts[iter])) { - return NULL; - } - result_len += strlen(parts[iter]); - } - - return do_string_join(sep, parts, len, result_len); -} - -/* lcr shrink array */ -static char **lcr_shrink_array(char **orig_array, size_t new_size) -{ - char **res_array = NULL; - size_t i; - - if (new_size == 0) { - return orig_array; - } - - if (new_size > SIZE_MAX / sizeof(char *)) { - return orig_array; - } - res_array = (char **)lcr_util_common_calloc_s(new_size * sizeof(char *)); - if (res_array == NULL) { - return orig_array; - } - - for (i = 0; i < new_size; i++) { - res_array[i] = orig_array[i]; - } - free(orig_array); - return res_array; -} - -/* lcr string split and trim */ -char **lcr_string_split_and_trim(const char *orig_str, char _sep) -{ - char *token = NULL; - char *str = NULL; - char *reserve_ptr = NULL; - char deli[2] = { _sep, '\0' }; - char **res_array = NULL; - size_t capacity = 0; - size_t count = 0; - int r, tmp_errno; - - if (orig_str == NULL) { - return calloc(1, sizeof(char *)); - } - - str = lcr_util_strdup_s(orig_str); - - token = strtok_r(str, deli, &reserve_ptr); - while (token != NULL) { - while (token[0] == ' ' || token[0] == '\t') { - token++; - } - size_t len = strlen(token); - while (len > 0 && (token[len - 1] == ' ' || token[len - 1] == '\t')) { - token[len - 1] = '\0'; - len--; - } - r = lcr_grow_array((void ***)&res_array, &capacity, count + 1, 16); - if (r < 0) { - goto error_out; - } - res_array[count] = lcr_util_strdup_s(token); - count++; - token = strtok_r(NULL, deli, &reserve_ptr); - } - free(str); - - return lcr_shrink_array(res_array, count + 1); - -error_out: - tmp_errno = errno; - lcr_free_array((void **)res_array); - free(str); - errno = tmp_errno; - return NULL; -} - -/* lcr free array */ -void lcr_free_array(void **orig_array) -{ - void **p = NULL; - for (p = orig_array; p && *p; p++) { - free(*p); - *p = NULL; - } - free((void *)orig_array); -} - -/* lcr grow array */ -int lcr_grow_array(void ***orig_array, size_t *orig_capacity, size_t size, size_t increment) -{ - size_t add_capacity; - void **add_array = NULL; - - if (orig_array == NULL || orig_capacity == NULL || size == SIZE_MAX) { - return -1; - } - - if ((*orig_array) == NULL || (*orig_capacity) == 0) { - free(*orig_array); - *orig_array = NULL; - *orig_capacity = 0; - } - - add_capacity = *orig_capacity; - while (size + 1 > add_capacity) { - if (add_capacity > SIZE_MAX - increment) { - return -1; - } - add_capacity += increment; - } - if (add_capacity != *orig_capacity) { - if (add_capacity > SIZE_MAX / sizeof(void *)) { - return -1; - } - add_array = lcr_util_common_calloc_s(add_capacity * sizeof(void *)); - if (add_array == NULL) { - return -1; - } - if (*orig_array) { - (void)memcpy(add_array, *orig_array, *orig_capacity * sizeof(void *)); - free((void *)*orig_array); - } - - *orig_array = add_array; - *orig_capacity = add_capacity; - } - - return 0; -} - -/* lcr array len */ -size_t lcr_array_len(void **orig_array) -{ - void **p = NULL; - size_t length = 0; - - for (p = orig_array; p && *p; p++) { - length++; - } - - return length; -} - -/* util common malloc s */ -void *lcr_util_common_calloc_s(size_t size) -{ - if (size == 0) { - return NULL; - } - - return calloc(1, size); -} - -int lcr_mem_realloc(void **newptr, size_t newsize, void *oldptr, size_t oldsize) -{ - void *addr = NULL; - - if (newptr == NULL) { - return -1; - } - - if (oldsize >= newsize || newsize == 0) { - goto err_out; - } - - addr = lcr_util_common_calloc_s(newsize); - if (addr == NULL) { - goto err_out; - } - - if (oldptr != NULL) { - (void)memcpy(addr, oldptr, oldsize); - free(oldptr); - } - - *newptr = addr; - return 0; - -err_out: - return -1; -} - - -static inline bool is_invalid_error_str(const char *err_str, const char *numstr) -{ - return err_str == NULL || err_str == numstr || *err_str != '\0'; -} - -int lcr_util_safe_strtod(const char *numstr, double *converted) -{ - char *err_str = NULL; - double ld; - - if (numstr == NULL || converted == NULL) { - return -EINVAL; - } - - errno = 0; - ld = strtod(numstr, &err_str); - if (errno > 0) { - return -errno; - } - - if (is_invalid_error_str(err_str, numstr)) { - return -EINVAL; - } - - *converted = ld; - return 0; -} - -/* util safe uint */ -int lcr_util_safe_uint(const char *numstr, unsigned int *converted) -{ - char *err_str = NULL; - unsigned long int ui; - - if (numstr == NULL || converted == NULL) { - return -EINVAL; - } - - errno = 0; - ui = strtoul(numstr, &err_str, 0); - if (errno > 0) { - return -errno; - } - - if (is_invalid_error_str(err_str, numstr)) { - return -EINVAL; - } - - if (ui > UINT_MAX) { - return -ERANGE; - } - - *converted = (unsigned int)ui; - return 0; -} - -struct unit_map_def_lcr { - int64_t mltpl; - char *name; -}; - -static struct unit_map_def_lcr const g_lcr_unit_map[] = { - { .mltpl = 1, .name = "I" }, { .mltpl = 1, .name = "B" }, { .mltpl = 1, .name = "IB" }, - { .mltpl = SIZE_KB, .name = "K" }, { .mltpl = SIZE_KB, .name = "KI" }, { .mltpl = SIZE_KB, .name = "KB" }, - { .mltpl = SIZE_KB, .name = "KIB" }, { .mltpl = SIZE_MB, .name = "M" }, { .mltpl = SIZE_MB, .name = "MI" }, - { .mltpl = SIZE_MB, .name = "MB" }, { .mltpl = SIZE_MB, .name = "MIB" }, { .mltpl = SIZE_GB, .name = "G" }, - { .mltpl = SIZE_GB, .name = "GI" }, { .mltpl = SIZE_GB, .name = "GB" }, { .mltpl = SIZE_GB, .name = "GIB" }, - { .mltpl = SIZE_TB, .name = "T" }, { .mltpl = SIZE_TB, .name = "TI" }, { .mltpl = SIZE_TB, .name = "TB" }, - { .mltpl = SIZE_TB, .name = "TIB" }, { .mltpl = SIZE_PB, .name = "P" }, { .mltpl = SIZE_PB, .name = "PI" }, - { .mltpl = SIZE_PB, .name = "PB" }, { .mltpl = SIZE_PB, .name = "PIB" } -}; - -static size_t const g_lcr_unit_map_len = sizeof(g_lcr_unit_map) / sizeof(g_lcr_unit_map[0]); - -/* parse unit multiple */ -static int parse_unit_multiple(const char *unit, int64_t *mltpl) -{ - size_t i; - if (unit[0] == '\0') { - *mltpl = 1; - return 0; - } - - for (i = 0; i < g_lcr_unit_map_len; i++) { - if (strcasecmp(unit, g_lcr_unit_map[i].name) == 0) { - *mltpl = g_lcr_unit_map[i].mltpl; - return 0; - } - } - return -EINVAL; -} - -static int util_parse_size_int_and_float(const char *numstr, int64_t mlt, int64_t *converted) -{ - long long int_size = 0; - double float_size = 0; - long long int_real = 0; - long long float_real = 0; - int nret; - - char *dot = strchr(numstr, '.'); - if (dot != NULL) { - char tmp; - // interger.float - if (dot == numstr || *(dot + 1) == '\0') { - return -EINVAL; - } - // replace 123.456 to 120.456 - tmp = *(dot - 1); - *(dot - 1) = '0'; - // parsing 0.456 - nret = lcr_util_safe_strtod(dot - 1, &float_size); - // recover 120.456 to 123.456 - *(dot - 1) = tmp; - if (nret < 0) { - return nret; - } - float_real = (int64_t)float_size; - if (mlt > 0) { - if (INT64_MAX / mlt < (int64_t)float_size) { - return -ERANGE; - } - float_real = (int64_t)(float_size * mlt); - } - *dot = '\0'; - } - nret = lcr_util_safe_llong(numstr, &int_size); - if (nret < 0) { - return nret; - } - int_real = int_size; - if (mlt > 0) { - if (INT64_MAX / mlt < int_size) { - return -ERANGE; - } - int_real = int_size * mlt; - } - if (INT64_MAX - int_real < float_real) { - return -ERANGE; - } - - *converted = int_real + float_real; - return 0; -} - -/* parse byte size string */ -int lcr_parse_byte_size_string(const char *s, int64_t *converted) -{ - int ret; - int64_t mltpl = 0; - char *dup = NULL; - char *pmlt = NULL; - - if (converted == NULL || s == NULL || s[0] == '\0' || !isdigit(s[0])) { - return -EINVAL; - } - - dup = lcr_util_strdup_s(s); - - pmlt = dup; - while (*pmlt != '\0' && (isdigit(*pmlt) || *pmlt == '.')) { - pmlt++; - } - - ret = parse_unit_multiple(pmlt, &mltpl); - if (ret) { - free(dup); - return ret; - } - - // replace the first multiple arg to '\0' - *pmlt = '\0'; - ret = util_parse_size_int_and_float(dup, mltpl, converted); - free(dup); - return ret; -} - -/* - * if path do not exist, this function will create it. - */ -int lcr_util_ensure_path(char **confpath, const char *path) -{ - int err = -1; - int fd; - char real_path[PATH_MAX + 1] = { 0 }; - - if (confpath == NULL || path == NULL) { - return -1; - } - - fd = lcr_util_open(path, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, DEFAULT_SECURE_FILE_MODE); - if (fd < 0 && errno != EEXIST) { - ERROR("failed to open '%s'", path); - goto err; - } - if (fd >= 0) { - close(fd); - } - - if (strlen(path) > PATH_MAX || realpath(path, real_path) == NULL) { - ERROR("Failed to get real path: %s", path); - goto err; - } - - *confpath = lcr_util_strdup_s(real_path); - - err = EXIT_SUCCESS; - -err: - return err; -} - -/* util dir exists */ -bool lcr_util_dir_exists(const char *path) -{ - struct stat s; - int nret; - - if (path == NULL) { - return false; - } - - nret = stat(path, &s); - if (nret < 0) { - return false; - } - - return S_ISDIR(s.st_mode); -} - -static inline bool is_dot(const char *value) -{ - return strcmp(value, ".") == 0; -} - -static inline bool is_double_dot(const char *value) -{ - return strcmp(value, "..") == 0; -} - - -/* util rmdir one */ -static void util_rmdir_one(const char *dirpath, const struct dirent *pdirent, int recursive_depth, int *failure) -{ - struct stat fstat; - int nret; - char fname[PATH_MAX] = { 0 }; - - if (is_dot(pdirent->d_name) || is_double_dot(pdirent->d_name)) { - return; - } - - nret = snprintf(fname, PATH_MAX, "%s/%s", dirpath, pdirent->d_name); - if (nret < 0 || nret >= PATH_MAX) { - ERROR("Pathname too long"); - *failure = 1; - return; - } - - nret = lstat(fname, &fstat); - if (nret) { - ERROR("Failed to stat %s", fname); - *failure = 1; - return; - } - - if (S_ISDIR(fstat.st_mode)) { - if (lcr_util_recursive_rmdir(fname, (recursive_depth + 1)) < 0) { - *failure = 1; - } - } else { - if (unlink(fname) < 0) { - ERROR("Failed to delete %s", fname); - *failure = 1; - } - } -} - -/* util recursive rmdir */ -int lcr_util_recursive_rmdir(const char *dirpath, int recursive_depth) -{ - struct dirent *pdirent = NULL; - DIR *directory = NULL; - int nret; - int failure = 0; - - if ((recursive_depth + 1) > MAX_PATH_DEPTH) { - ERROR("Reach max path depth: %s", dirpath); - failure = 1; - goto err_out; - } - - if (!lcr_util_dir_exists(dirpath)) { /* dir not exists */ - goto err_out; - } - - directory = opendir(dirpath); - if (directory == NULL) { - ERROR("Failed to open %s", dirpath); - failure = 1; - goto err_out; - } - - pdirent = readdir(directory); - while (pdirent != NULL) { - util_rmdir_one(dirpath, pdirent, recursive_depth, &failure); - pdirent = readdir(directory); - } - - if (rmdir(dirpath) < 0) { - ERROR("Failed to delete %s", dirpath); - failure = 1; - } - - nret = closedir(directory); - if (nret) { - ERROR("Failed to close directory %s", dirpath); - failure = 1; - } - -err_out: - return failure ? -1 : 0; -} - -/* util string replace one */ -static ssize_t lcr_util_string_replace_one(const char *needle, const char *replace, const char *haystack, char **result) -{ - char *res_string = *result; - char *p = NULL; - char *next_p = NULL; - ssize_t length = 0; - size_t replace_len, nl_len, part_len; - - replace_len = strlen(replace); - nl_len = strlen(needle); - - for (next_p = (char *)haystack, p = strstr(next_p, needle); p != NULL; next_p = p, p = strstr(next_p, needle)) { - part_len = (size_t)(p - next_p); - if ((res_string != NULL) && part_len > 0) { - (void)memcpy(&res_string[length], next_p, part_len); - } - length += (ssize_t)part_len; - if ((res_string != NULL) && replace_len > 0) { - (void)memcpy(&res_string[length], replace, replace_len); - } - length += (ssize_t)replace_len; - p += nl_len; - } - part_len = strlen(next_p); - if ((res_string != NULL) && part_len > 0) { - (void)memcpy(&res_string[length], next_p, part_len); - } - length += (ssize_t)part_len; - return length; -} - -/* util string replace */ -char *lcr_util_string_replace(const char *needle, const char *replace, const char *haystack) -{ - ssize_t length = -1; - ssize_t reserve_len = -1; - char *res_string = NULL; - - if ((needle == NULL) || (replace == NULL) || (haystack == NULL)) { - ERROR("Invalid NULL pointer"); - return NULL; - } - - while (length == -1 || res_string == NULL) { - if (length != -1) { - res_string = calloc(1, (size_t)length + 1); - if (res_string == NULL) { - return NULL; - } - reserve_len = length; - } - length = lcr_util_string_replace_one(needle, replace, haystack, &res_string); - if (length < 0) { - free(res_string); - return NULL; - } - } - - if (reserve_len != length) { - free(res_string); - return NULL; - } - if (res_string[length] != '\0') { - free(res_string); - return NULL; - } - - return res_string; -} - -int lcr_util_open(const char *filename, int flags, mode_t mode) -{ - char rpath[PATH_MAX] = { 0x00 }; - - if (cleanpath(filename, rpath, sizeof(rpath)) == NULL) { - return -1; - } - if (mode) { - return open(rpath, flags | O_CLOEXEC, mode); - } else { - return open(rpath, flags | O_CLOEXEC); - } -} - -int lcr_util_safe_int(const char *num_str, int *converted) -{ - char *err_str = NULL; - signed long int li; - - if (num_str == NULL || converted == NULL) { - return -EINVAL; - } - - errno = 0; - li = strtol(num_str, &err_str, 0); - if (errno > 0) { - return -errno; - } - - if (is_invalid_error_str(err_str, num_str)) { - return -EINVAL; - } - - if (li > INT_MAX || li < INT_MIN) { - return -ERANGE; - } - - *converted = (int)li; - return 0; -} - -/* util check inherited */ -static bool util_dir_skip_current(const struct dirent *pdirent) -{ - if (is_dot(pdirent->d_name)) { - return true; - } - - if (is_double_dot(pdirent->d_name)) { - return true; - } - return false; -} - -static bool util_is_std_fileno(int fd) -{ - return fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO; -} - -int lcr_util_check_inherited(bool closeall, int fd_to_ignore) -{ - struct dirent *pdirent = NULL; - int fd = -1; - int fddir = -1; - DIR *directory = NULL; - -restart: - if (directory != NULL) { - closedir(directory); - } - directory = opendir("/proc/self/fd"); - if (directory == NULL) { - WARN("Failed to open directory: %m."); - return -1; - } - - fddir = dirfd(directory); - pdirent = readdir(directory); - for (; pdirent != NULL; pdirent = readdir(directory)) { - if (util_dir_skip_current(pdirent)) { - continue; - } - - if (lcr_util_safe_int(pdirent->d_name, &fd) < 0) { - continue; - } - - if (util_is_std_fileno(fd) || fd == fddir || fd == fd_to_ignore) { - continue; - } - - if (closeall) { - if (fd >= 0) { - close(fd); - fd = -1; - } - goto restart; - } - } - - closedir(directory); - return 0; -} - -/* util string append */ -char *lcr_util_string_append(const char *post, const char *pre) -{ - char *res_string = NULL; - size_t length = 0; - - if (post == NULL && pre == NULL) { - return NULL; - } - if (pre == NULL) { - return lcr_util_strdup_s(post); - } - if (post == NULL) { - return lcr_util_strdup_s(pre); - } - if (strlen(post) > ((SIZE_MAX - strlen(pre)) - 1)) { - ERROR("String is too long to be appended"); - return NULL; - } - length = strlen(post) + strlen(pre) + 1; - res_string = lcr_util_common_calloc_s(length); - if (res_string == NULL) { - return NULL; - } - (void)strcat(res_string, pre); - (void)strcat(res_string, post); - - return res_string; -} - -/* util string split prefix */ -char *lcr_util_string_split_prefix(size_t prefix_len, const char *file) -{ - size_t file_len = 0; - size_t len = 0; - char *path = NULL; - - if (file == NULL) { - return NULL; - } - - file_len = strlen(file); - if (file_len < prefix_len) { - return NULL; - } - len = strlen(file) - prefix_len; - if (len > SIZE_MAX / sizeof(char) - 1) { - return NULL; - } - path = lcr_util_common_calloc_s((len + 1) * sizeof(char)); - if (path == NULL) { - return NULL; - } - (void)strncpy(path, file + prefix_len, len); - path[len] = '\0'; - - return path; -} - -static void set_char_to_terminator(char *p) -{ - *p = '\0'; -} -/* - * @name is absolute path of this file. - * make all directory in this absolute path. - * */ -int lcr_util_build_dir(const char *name) -{ - char *n = NULL; // because we'll be modifying it - char *p = NULL; - char *e = NULL; - int nret; - - if (name == NULL) { - return -1; - } - - n = lcr_util_strdup_s(name); - e = &(n[strlen(n)]); - for (p = n + 1; p < e; p++) { - if (*p != '/') { - continue; - } - set_char_to_terminator(p); - if (access(n, F_OK)) { - nret = mkdir(n, DEFAULT_SECURE_DIRECTORY_MODE); - if (nret && (errno != EEXIST || !lcr_util_dir_exists(n))) { - ERROR("failed to create directory '%s'.", n); - free(n); - return -1; - } - } - *p = '/'; - } - free(n); - return 0; -} - -/* util write nointr */ -ssize_t lcr_util_write_nointr(int fd, const void *buf, size_t count) -{ - ssize_t nret; - - if (buf == NULL) { - return -1; - } - - for (;;) { - nret = write(fd, buf, count); - if (nret < 0 && errno == EINTR) { - continue; - } else if (nret < 0 && errno == EAGAIN) { - continue; - } else { - break; - } - } - return nret; -} - -/* util read nointr */ -ssize_t lcr_util_read_nointr(int fd, void *buf, size_t count) -{ - ssize_t nret; - - if (buf == NULL) { - return -1; - } - - for (;;) { - nret = read(fd, buf, count); - if (nret < 0 && errno == EINTR) { - continue; - } else { - break; - } - } - - return nret; -} - -/* util array len */ -size_t lcr_util_array_len(char **array) -{ - char **pos = NULL; - size_t len = 0; - - for (pos = array; pos && *pos; pos++) { - len++; - } - - return len; -} - -/* util safe llong */ -int lcr_util_safe_llong(const char *numstr, long long *converted) -{ - char *err_str = NULL; - long long ll; - - if (numstr == NULL || converted == NULL) { - return -EINVAL; - } - - errno = 0; - ll = strtoll(numstr, &err_str, 0); - if (errno > 0) { - return -errno; - } - - if (is_invalid_error_str(err_str, numstr)) { - return -EINVAL; - } - - *converted = (long long)ll; - return 0; -} - -char *lcr_util_strdup_s(const char *src) -{ - char *dst = NULL; - - if (src == NULL) { - return NULL; - } - - dst = strdup(src); - if (dst == NULL) { - abort(); - } - - return dst; -} - -static int open_devnull(void) -{ - int fd = open("/dev/null", O_RDWR); - if (fd < 0) { - SYSERROR("Can't open /dev/null"); - } - - return fd; -} - -static int set_stdfds(int fd) -{ - int ret = 0; - - if (fd < 0) { - return -1; - } - - ret = dup2(fd, STDIN_FILENO); - if (ret < 0) { - return -1; - } - - ret = dup2(fd, STDOUT_FILENO); - if (ret < 0) { - return -1; - } - - ret = dup2(fd, STDERR_FILENO); - if (ret < 0) { - return -1; - } - - return 0; -} - -int lcr_util_null_stdfds(void) -{ - int ret = -1; - int fd; - - fd = open_devnull(); - if (fd >= 0) { - ret = set_stdfds(fd); - close(fd); - } - - return ret; -} - -static void util_trim_newline(char *s) -{ - if (s == NULL) { - return; - } - size_t len = strlen(s); - while ((len > 1) && (s[len - 1] == '\n')) { - s[--len] = '\0'; - } -} - -static int append_new_content_to_file(FILE *fp, const char *content) -{ - int ret = 0; - size_t length = 0; - size_t content_len = 0; - char *line = NULL; - char *tmp_str = NULL; - bool need_append = true; - while (getline(&line, &length, fp) != -1) { - if (line == NULL) { - ERROR("Failed to read content from file ptr"); - ret = -1; - goto out; - } - util_trim_newline(line); - if (!strcmp(content, line)) { - need_append = false; - break; - } - } - if (need_append) { - if (strlen(content) > ((SIZE_MAX - strlen("\n")) - 1)) { - ret = -1; - goto out; - } - content_len = strlen(content) + strlen("\n") + 1; - tmp_str = lcr_util_common_calloc_s(content_len); - if (tmp_str == NULL) { - ERROR("Out of memory"); - ret = -1; - goto out; - } - int num = snprintf(tmp_str, content_len, "%s\n", content); - if (num < 0 || (size_t)num >= content_len) { - ERROR("Failed to print string"); - ret = -1; - goto out; - } - if (fwrite(tmp_str, 1, strlen(tmp_str), fp) == 0) { - ERROR("Failed to write content: '%s'", content); - ret = -1; - goto out; - } - } - -out: - free(tmp_str); - free(line); - return ret; -} - -int lcr_util_atomic_write_file(const char *filepath, const char *content) -{ - int fd; - int ret = 0; - FILE *fp = NULL; - struct flock lk; - - if (filepath == NULL || content == NULL) { - return -1; - } - fd = lcr_util_open(filepath, O_RDWR | O_CREAT | O_APPEND, DEFAULT_SECURE_FILE_MODE); - if (fd < 0) { - ERROR("Failed to open: %s", filepath); - return -1; - } - lk.l_type = F_WRLCK; - lk.l_whence = SEEK_SET; - lk.l_start = 0; - lk.l_len = 0; - if (fcntl(fd, F_SETLKW, &lk) == 0) { - fp = fdopen(fd, "a+"); - if (fp == NULL) { - ERROR("Failed to open fd: %d", fd); - ret = -1; - goto out; - } - ret = append_new_content_to_file(fp, content); - } -out: - if (fp != NULL) { - fclose(fp); - } - close(fd); - return ret; -} diff --git a/src/utils.h b/src/utils.h deleted file mode 100644 index 77493a4..0000000 --- a/src/utils.h +++ /dev/null @@ -1,196 +0,0 @@ -/****************************************************************************** - * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. - * lcr 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: wujing - * Create: 2018-11-08 - * Description: provide container utils functions - ******************************************************************************/ -#ifndef __LCR_UTILS_H -#define __LCR_UTILS_H - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef O_CLOEXEC -#define O_CLOEXEC 02000000 -#endif - -#define ECOMMON 1 -#define EINVALIDARGS 125 -#define ECMDNOTFOUND 127 - -#define LCR_NUMSTRLEN64 21 - -#define SPACE_MAGIC_STR "[#)" - -#define MAX_PATH_DEPTH 1024 - -#define SIZE_KB 1024LL -#define SIZE_MB (1024LL * SIZE_KB) -#define SIZE_GB (1024LL * SIZE_MB) -#define SIZE_TB (1024LL * SIZE_GB) -#define SIZE_PB (1024LL * SIZE_TB) - -#define BUFSIZE 4096 - -#ifndef SIGTRAP -#define SIGTRAP 5 -#endif - -#ifndef SIGIOT -#define SIGIOT 6 -#endif - -#ifndef SIGEMT -#define SIGEMT 7 -#endif - -#ifndef SIGBUS -#define SIGBUS 7 -#endif - -#ifndef SIGSTKFLT -#define SIGSTKFLT 16 -#endif - -#ifndef SIGCLD -#define SIGCLD 17 -#endif - -#ifndef SIGURG -#define SIGURG 23 -#endif - -#ifndef SIGXCPU -#define SIGXCPU 24 -#endif - -#ifndef SIGXFSZ -#define SIGXFSZ 25 -#endif - -#ifndef SIGVTALRM -#define SIGVTALRM 26 -#endif - -#ifndef SIGPROF -#define SIGPROF 27 -#endif - -#ifndef SIGWINCH -#define SIGWINCH 28 -#endif - -#ifndef SIGIO -#define SIGIO 29 -#endif - -#ifndef SIGPOLL -#define SIGPOLL 29 -#endif - -#ifndef SIGINFO -#define SIGINFO 29 -#endif - -#ifndef SIGLOST -#define SIGLOST 37 -#endif - -#ifndef SIGPWR -#define SIGPWR 30 -#endif - -#ifndef SIGUNUSED -#define SIGUNUSED 31 -#endif - -#ifndef SIGSYS -#define SIGSYS 31 -#endif - -#ifndef SIGRTMIN1 -#define SIGRTMIN1 34 -#endif - -#ifndef SIGRTMAX -#define SIGRTMAX 64 -#endif - -#define SIGNAL_MAP_DEFAULT \ - { \ - { SIGHUP, "HUP" }, { SIGINT, "INT" }, { SIGQUIT, "QUIT" }, { SIGILL, "ILL" }, { SIGABRT, "ABRT" }, \ - { SIGFPE, "FPE" }, { SIGKILL, "KILL" }, { SIGSEGV, "SEGV" }, { SIGPIPE, "PIPE" }, { SIGALRM, "ALRM" }, \ - { SIGTERM, "TERM" }, { SIGUSR1, "USR1" }, { SIGUSR2, "USR2" }, { SIGCHLD, "CHLD" }, \ - { SIGCONT, "CONT" }, { SIGSTOP, "STOP" }, { SIGTSTP, "TSTP" }, { SIGTTIN, "TTIN" }, \ - { SIGTTOU, "TTOU" }, { SIGTRAP, "TRAP" }, { SIGIOT, "IOT" }, { SIGEMT, "EMT" }, { SIGBUS, "BUS" }, \ - { SIGSTKFLT, "STKFLT" }, { SIGCLD, "CLD" }, { SIGURG, "URG" }, { SIGXCPU, "XCPU" }, \ - { SIGXFSZ, "XFSZ" }, { SIGVTALRM, "VTALRM" }, { SIGPROF, "PROF" }, { SIGWINCH, "WINCH" }, \ - { SIGIO, "IO" }, { SIGPOLL, "POLL" }, { SIGINFO, "INFO" }, { SIGLOST, "LOST" }, { SIGPWR, "PWR" }, \ - { SIGUNUSED, "UNUSED" }, { SIGSYS, "SYS" }, { SIGRTMIN, "RTMIN" }, { SIGRTMIN + 1, "RTMIN+1" }, \ - { SIGRTMIN + 2, "RTMIN+2" }, { SIGRTMIN + 3, "RTMIN+3" }, { SIGRTMIN + 4, "RTMIN+4" }, \ - { SIGRTMIN + 5, "RTMIN+5" }, { SIGRTMIN + 6, "RTMIN+6" }, { SIGRTMIN + 7, "RTMIN+7" }, \ - { SIGRTMIN + 8, "RTMIN+8" }, { SIGRTMIN + 9, "RTMIN+9" }, { SIGRTMIN + 10, "RTMIN+10" }, \ - { SIGRTMIN + 11, "RTMIN+11" }, { SIGRTMIN + 12, "RTMIN+12" }, { SIGRTMIN + 13, "RTMIN+13" }, \ - { SIGRTMIN + 14, "RTMIN+14" }, { SIGRTMIN + 15, "RTMIN+15" }, { SIGRTMAX - 14, "RTMAX-14" }, \ - { SIGRTMAX - 13, "RTMAX-13" }, { SIGRTMAX - 12, "RTMAX-12" }, { SIGRTMAX - 11, "RTMAX-11" }, \ - { SIGRTMAX - 10, "RTMAX-10" }, { SIGRTMAX - 9, "RTMAX-9" }, { SIGRTMAX - 8, "RTMAX-8" }, \ - { SIGRTMAX - 7, "RTMAX-7" }, { SIGRTMAX - 6, "RTMAX-6" }, { SIGRTMAX - 5, "RTMAX-5" }, \ - { SIGRTMAX - 4, "RTMAX-4" }, { SIGRTMAX - 3, "RTMAX-3" }, { SIGRTMAX - 2, "RTMAX-2" }, \ - { SIGRTMAX - 1, "RTMAX-1" }, { SIGRTMAX, "RTMAX" }, \ - } - -int lcr_wait_for_pid(pid_t pid); -int lcr_wait_for_pid_status(pid_t pid); -char *lcr_util_string_join(const char *sep, const char **parts, size_t len); -char **lcr_string_split_and_trim(const char *str, char _sep); -void lcr_free_array(void **array); -int lcr_grow_array(void ***array, size_t *capacity, size_t new_size, size_t capacity_increment); -size_t lcr_array_len(void **array); -int lcr_mem_realloc(void **newptr, size_t newsize, void *oldptr, size_t oldsize); -int lcr_util_safe_strtod(const char *numstr, double *converted); -int lcr_util_safe_uint(const char *numstr, unsigned int *converted); -int lcr_parse_byte_size_string(const char *s, int64_t *converted); -bool lcr_util_dir_exists(const char *path); -int lcr_util_ensure_path(char **confpath, const char *path); -int lcr_util_recursive_rmdir(const char *dirpath, int recursive_depth); -char *lcr_util_string_replace(const char *needle, const char *replacement, const char *haystack); -int lcr_util_open(const char *filename, int flags, mode_t mode); - -void *lcr_util_common_calloc_s(size_t size); -int lcr_util_safe_int(const char *numstr, int *converted); -int lcr_util_check_inherited(bool closeall, int fd_to_ignore); -char *lcr_util_string_append(const char *post, const char *pre); -char *lcr_util_string_split_prefix(size_t prefix_len, const char *file); - -int lcr_util_build_dir(const char *name); -ssize_t lcr_util_write_nointr(int fd, const void *buf, size_t count); -ssize_t lcr_util_read_nointr(int fd, void *buf, size_t count); - -size_t lcr_util_array_len(char **array); - -int lcr_util_safe_llong(const char *numstr, long long *converted); -char *lcr_util_strdup_s(const char *src); -int lcr_util_null_stdfds(void); - -int lcr_util_atomic_write_file(const char *filepath, const char *content); - -#ifdef __cplusplus -} -#endif - -#endif /* __LCR_UTILS_H */ diff --git a/tools/static_check b/tools/static_check deleted file mode 100755 index 641fff2..0000000 --- a/tools/static_check +++ /dev/null @@ -1,554 +0,0 @@ -####################################################################### -##- @Copyright (C) Huawei Technologies., Ltd. 2019. All rights reserved. -# - lcr 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. -##- @Description: generate cetification -##- @Author: wujing -##- @Create: 2019-04-25 -####################################################################### -#!/bin/bash -# -# This script is the implementation portal for the iSulad project Personal level build static check. -# set -euxo pipefail - -CURRENT_PATH=$(pwd) -CI_TOOLS_PROJECT="/root/workspace/ci_tools" -export LOCAL_INCLUDE="/root/workspace/ci_tools/rule/include" -export EULER_CODE_PATH="$(realpath ${CURRENT_PATH}/..)" -LINT_RULE_FILE="/root/workspace/ci_tools/rule/pclint" -PCLINT_TOOL="/usr/local/bin/flint" -CODESTYLE_TOOL="/usr/local/bin/cpplint.py" -CMETRICS_TOOL="/root/cmetrics/cmetrics.py" - -function usage() { - echo -e "\ -=================================================================================================\033[1;37m - _____ ______ ___ ______ ____ ______ ______ __ __ ______ ______ __ __ - / ___//_ __// | /_ __// _// ____/ / ____// / / // ____// ____// //_/ - \__ \ / / / /| | / / / / / / / / / /_/ // __/ / / / ,< - ___/ / / / / ___ | / / _/ / / /___ / /___ / __ // /___ / /___ / /| | - /____/ /_/ /_/ |_|/_/ /___/ \____/ \____//_/ /_//_____/ \____//_/ |_| \033[0m -=================================================================================================" - echo "Usage: $0 [options]" - echo "Personal level build static check script for iSulad project" - echo "Options:" - echo " -u, --update-ci-tools Update ci tools project and replace header files with latest ones" - echo " -p, --pclint Perform pclint code static check" - echo " -s, --codestyle Perform codestyle(codedex) code static check" - echo " -c, --detail-cmetrics Detail code statistics analysis" - echo " -m, --simple-cmetrics Simple code statistics analysis" - echo " -a, --all Perform all checks and statistics" - echo " -i, --incremental-check Perform incremental check" - echo " -f, --quick-format Incremental format code by astyle/clang-format" - echo " -k, --style-check Check code style by astyle" - echo " --cpp-check Use Cppcheck check code style" - echo " -h, --help Script help information" -} - -function err() { - echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $@" >&2 -} - -function update_ci_tools() { - cd ${CI_TOOLS_PROJECT} - git fetch origin - git diff > static_check_backup.patch - git checkout . - git rebase origin/next_docker - cd ${CURRENT_PATH} - for file in $(find . -regextype posix-extended -regex ".*\.(h)") - do - cp $file $LOCAL_INCLUDE/docker/iSulad - done -} - -PCLINT_MASKED_RULE="679|826|726|322|571" - -function pclint_check() { - echo -e "\ -=================================================================================================\033[1;35m - ____ ______ __ ____ _ __ ______ ______ __ __ ______ ______ __ __ - / __ \ / ____// / / _// | / //_ __/ / ____// / / // ____// ____// //_/ - / /_/ // / / / / / / |/ / / / / / / /_/ // __/ / / / ,< - / ____// /___ / /___ _/ / / /| / / / / /___ / __ // /___ / /___ / /| | - /_/ \____//_____//___//_/ |_/ /_/ \____//_/ /_//_____/ \____//_/ |_| \033[0m -=================================================================================================" - local start_time=$(date +%s) - local files - if [[ ${1} == "all" ]]; then - files=$(find ./src ./test -regextype posix-extended -regex ".*\.(c|cc)") - else - files=$(git diff --name-only HEAD | grep -E "*.c$") - fi - files=(${files// / }) - local total=${#files[@]} - local failure_num=0 - local index=1 - for file in ${files[@]} - do - ${PCLINT_TOOL} -i ${LINT_RULE_FILE} std_lcr.lnt $file 2>&1 | grep -E "Err|Warn|Info" | grep -vE ${PCLINT_MASKED_RULE} - if [[ $? -eq 0 ]];then - printf "[\033[1;36m%03d\033[0m\033[1;33m/\033[0m\033[1;34m%03d\033[0m]@%-80s \033[1;31m\033[5m%s\033[0m\n" \ - ${index} ${total} ${file} "[FAILED]" | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /' - failure_num=$((failure_num+1)) - else - printf "[\033[1;36m%03d\033[0m\033[1;33m/\033[0m\033[1;34m%03d\033[0m]@%-80s \033[1;32m%-5s\033[0m\n" \ - ${index} ${total} ${file} "[PASS]" | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /' - fi - index=$((index+1)) - done - printf "%0.s=" {1..96} - printf "\n" - local end_time=$(date +%s) - local duration=$((${end_time} - ${start_time})) - echo -e "\033[1;36mTotal files: ${total}\033[0m, \033[1;32msuccess: $((total-failure_num))\033[0m, \033[1;31mfailure: ${failure_num}\033[0m. \033[1;33mSpend time: ${duration} seconds\033[0m" - if [[ ${failure_num} -ne 0 ]]; then - exit -1 - fi -} - -CODESTYLE_MASKED_RULE=( - "Start-processing" - "Done-processing" - "Total-errors-found" - "\[build/header_guard\]-\[5\]" - "\[build/c++11\]-\[5\]" - "\[whitespace/indent\]-\[3\]" - "\[whitespace/braces\]-\[4\]" - "\[readability/condition\]-\[2\]" - "\[whitespace/braces\]-\[5\]" - "\[build/c\+\+11\]-\[5\]" - "\[build/include_order\]-\[4\]" - "\[readability/multiline_string\]-\[5\]" - "\[runtime/string\]-\[4\]" - "\[whitespace/semicolon\]-\[5\]" - "\[whitespace/comments\]-\[2\]" - "\[build/c\+\+11\]-\[3\]" - "\[whitespace/operators\]-\[4\]" - "\[runtime/threadsafe_fn\]-\[2\]" - "\[runtime/printf\]-\[4\]" - "\[readability/alt_tokens\]-\[2\]" -) -function codestyle_check() { - echo -e "\ -=================================================================================================\033[1;33m - ______ ____ ____ ____ _ __ ______ _____ ________ __ __ ______ - / ____// __ \ / __ \ / _// | / // ____// ___//_ __/\ \/ // / / ____/ - / / / / / // / / / / / / |/ // / __ \__ \ / / \ // / / __/ - / /___ / /_/ // /_/ /_/ / / /| // /_/ / ___/ / / / / // /___ / /___ - \____/ \____//_____//___//_/ |_/ \____/ /____/ /_/ /_//_____//_____/\033[0m -=================================================================================================" - local masked_rule=$(echo ${CODESTYLE_MASKED_RULE[@]} | sed -e "s/ /|/g" -e "s/-/ /g") - local start_time=$(date +%s) - local files - if [[ ${1} == "all" ]]; then - files=$(find ./src ./test -regextype posix-extended -regex ".*\.(h|c|cc)") - else - files=$(git diff --name-only HEAD | grep -E "*.h$|*.c$|*.cc$") - fi - files=(${files// / }) - local total=${#files[@]} - local failure_num=0 - local index=1 - for file in ${files[@]} - do - python3 ${CODESTYLE_TOOL} $file 2>&1 | grep -vE "${masked_rule}" - if [[ $? -eq 0 ]];then - printf "[\033[1;36m%03d\033[0m\033[1;33m/\033[0m\033[1;34m%03d\033[0m]@%-80s \033[1;31m\033[5m%s\033[0m\n" \ - ${index} ${total} ${file} "[FAILED]" | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /' - failure_num=$((failure_num+1)) - else - printf "[\033[1;36m%03d\033[0m\033[1;33m/\033[0m\033[1;34m%03d\033[0m]@%-80s \033[1;32m%-5s\033[0m\n" \ - ${index} ${total} ${file} "[PASS]" | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /' - fi - index=$((index+1)) - done - printf "%0.s=" {1..96} - printf "\n" - local end_time=$(date +%s) - local duration=$((${end_time} - ${start_time})) - echo -e "\033[1;36mTotal files: ${total}\033[0m, \033[1;32msuccess: $((total-failure_num))\033[0m, \033[1;31mfailure: ${failure_num}\033[0m. \033[1;33mSpend time: ${duration} seconds\033[0m" - if [[ ${failure_num} -ne 0 ]]; then - exit -1 - fi -} - -CPPCHRECK_RULE=( - "information" - "warning" - "performance" - "style" - # "unusedFunction" - # "all" -) -CPPCHRCK_LOG="${CURRENT_PATH}/cppcheck.log" - -function cpp_check() { - echo -e "\ -=================================================================================================\033[1;33m - ______ ____ ____ ______ __ __ ______ ______ __ __ - / ____// __ \ / __ \ / ____// / / // ____// ____// //_/ - / / / /_/ // /_/ / / / / /_/ // __/ / / / ,< - / /___ / ____// ____/ / /___ / __ // /___ / /___ / /| | - \____//_/ /_/ \____//_/ /_//_____/ \____//_/ |_|\033[0m -=================================================================================================" - echo "cpp check is in progress, please wait a few seconds..." - printf "%0.s*" {1..97} - printf "\n" - local check_rule=$(echo ${CPPCHRECK_RULE[@]} | sed -e "s/ /,/g") - local start_time=$(date +%s) - result=$(cppcheck --enable=${check_rule} -I ./src -i ./build -i ./isula_testcases -i ./CI ./ 2>&1 \ - | grep -vE "^Checking|done$|Cppcheck cannot find all the include files") - nums=$(echo "${result}" | wc -l) - echo "${result}" - local end_time=$(date +%s) - local duration=$((${end_time} - ${start_time})) - if [[ ${nums} -eq 0 ]] || [[ -z ${result} ]]; then - echo -e "\033[1;32mSuccess: clean code!\033[0m \033[1;33mSpend time: ${duration} seconds\033[0m" - else - printf "%0.s*" {1..97} - printf "\n" - echo -e "\033[1;31mFailure: There are ${nums} warnings that you need to handle\033[0m. \033[1;33mSpend time: ${duration} seconds\033[0m" - exit -1 - fi -} - -function clang_format() { - echo -e "\ -=================================================================================================\033[1;36m - ______ __ ___ _ __ ______ ______ ____ ____ __ ___ ___ ______ - / ____// / / | / | / // ____/ / ____// __ \ / __ \ / |/ // | /_ __/ - / / / / / /| | / |/ // / __ ______ / /_ / / / // /_/ // /|_/ // /| | / / - / /___ / /___ / ___ | / /| // /_/ //_____// __/ / /_/ // _, _// / / // ___ | / / - \____//_____//_/ |_|/_/ |_/ \____/ /_/ \____//_/ |_|/_/ /_//_/ |_|/_/ \033[0m] -=================================================================================================" - local start_time=$(date +%s) - local files=$(git diff --name-only HEAD | grep -E "*.h$|*.c$|*.cc$") - files=(${files// / }) - local total=${#files[@]} - local failure_num=0 - local index=1 - for file in ${files[@]} - do - clang-format -i ${file} - if [[ $? -ne 0 ]];then - printf "[\033[1;36m%03d\033[0m\033[1;33m/\033[0m\033[1;34m%03d\033[0m]@%-80s \033[1;31m\033[5m%s\033[0m\n" \ - ${index} ${total} ${file} "[FAILED]" | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /' - failure_num=$((failure_num+1)) - else - printf "[\033[1;36m%03d\033[0m\033[1;33m/\033[0m\033[1;34m%03d\033[0m]@%-80s \033[1;32m%-5s\033[0m\n" \ - ${index} ${total} ${file} "[PASS]" | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /' - fi - index=$((index+1)) - done - printf "%0.s=" {1..96} - printf "\n" - local end_time=$(date +%s) - local duration=$((${end_time} - ${start_time})) - echo -e "\033[1;36mTotal files: ${total}\033[0m, \033[1;32msuccess: $((total-failure_num))\033[0m, \033[1;31mfailure: ${failure_num}\033[0m. \033[1;33mSpend time: ${duration} seconds\033[0m" -} - -function do_astyle_fix() { - astyle --options=none --lineend=linux --mode=c \ - --style=kr \ - --add-braces \ - --indent=spaces=4 \ - --indent-preprocessor \ - --indent-col1-comments \ - --indent-switches \ - --indent-cases \ - --min-conditional-indent=0 \ - --max-instatement-indent=120 \ - --max-code-length=120 \ - --break-after-logical \ - --pad-oper \ - --pad-header \ - --unpad-paren \ - --pad-comma \ - --lineend=linux \ - --align-reference=name \ - --close-templates \ - --indent-preproc-define \ - --indent-cases \ - --indent-switches \ - --attach-namespaces \ - --attach-classes \ - --attach-extern-c \ - --attach-closing-while \ - --indent-col1-comments \ - --break-one-line-headers \ - --close-templates < "${1}" -} - -function astyle_fix() { - [[ -z "${1}" || ! -r "${1}" ]] && exit -1 - tmp="$(mktemp --tmpdir=$(dirname "${1}"))" - do_astyle_fix "${1}" > "${tmp}" - sed -i 's/\*const/\* const/g' "${tmp}" - mv "${tmp}" "${1}" -} - -function astyle_format() { - echo -e "\ -=================================================================================================\033[1;36m - ___ _____ ________ __ __ ______ ______ ____ ____ __ ___ ___ ______ - / | / ___//_ __/\ \/ // / / ____/ / ____// __ \ / __ \ / |/ // | /_ __/ - / /| | \__ \ / / \ // / / __/ ______ / /_ / / / // /_/ // /|_/ // /| | / / - / ___ | ___/ / / / / // /___ / /___/_____// __/ / /_/ // _, _// / / // ___ | / / - /_/ |_|/____/ /_/ /_//_____//_____/ /_/ \____//_/ |_|/_/ /_//_/ |_|/_/ \033[0m] -=================================================================================================" - local start_time=$(date +%s) - local files=$(find ./src ./test -regextype posix-extended -regex ".*\.(h|c|cc)") - files=(${files// / }) - local total=${#files[@]} - local failure_num=0 - local index=1 - for file in ${files[@]} - do - astyle_fix ${file} - if [[ $? -ne 0 ]];then - printf "[\033[1;36m%03d\033[0m\033[1;33m/\033[0m\033[1;34m%03d\033[0m]@%-80s \033[1;31m\033[5m%s\033[0m\n" \ - ${index} ${total} ${file} "[FAILED]" | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /' - failure_num=$((failure_num+1)) - else - printf "[\033[1;36m%03d\033[0m\033[1;33m/\033[0m\033[1;34m%03d\033[0m]@%-80s \033[1;32m%-5s\033[0m\n" \ - ${index} ${total} ${file} "[PASS]" | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /' - fi - index=$((index+1)) - done - printf "%0.s=" {1..96} - printf "\n" - local end_time=$(date +%s) - local duration=$((${end_time} - ${start_time})) - echo -e "\033[1;36mTotal files: ${total}\033[0m, \033[1;32msuccess: $((total-failure_num))\033[0m, \033[1;31mfailure: ${failure_num}\033[0m. \033[1;33mSpend time: ${duration} seconds\033[0m" -} - -function quick_format() { - if [[ $1 == "clang-format" ]]; then - clang_format - else - astyle_format - fi -} - -function do_astyle_check() { - [[ -z "$1" || ! -r "$1" ]] && return -1 - - do_astyle_fix "$1" | diff -pu --label="$1.orig" "$1" --label="$1" - - if [[ $? -ne 0 ]]; then - return -1 - fi -} - -function style_check() { -echo -e "\ -================================================================================================= - ███████╗████████╗██╗ ██╗██╗ ███████╗ ██████╗██╗ ██╗███████╗ ██████╗██╗ ██╗ - ██╔════╝╚══██╔══╝╚██╗ ██╔╝██║ ██╔════╝ ██╔════╝██║ ██║██╔════╝██╔════╝██║ ██╔╝ - ███████╗ ██║ ╚████╔╝ ██║ █████╗ ██║ ███████║█████╗ ██║ █████╔╝ - ╚════██║ ██║ ╚██╔╝ ██║ ██╔══╝ ██║ ██╔══██║██╔══╝ ██║ ██╔═██╗ - ███████║ ██║ ██║ ███████╗███████╗ ╚██████╗██║ ██║███████╗╚██████╗██║ ██╗ - ╚══════╝ ╚═╝ ╚═╝ ╚══════╝╚══════╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝ -=================================================================================================" - local start_time=$(date +%s) - local files - if [[ ${1} == "all" ]]; then - files=$(find ./src ./test -regextype posix-extended -regex ".*\.(h|c|cc)") - else - files=$(git diff --name-only HEAD | grep -E "*.h$|*.c$|*.cc$") - fi - files=(${files// / }) - local total=${#files[@]} - local failure_num=0 - local index=1 - for file in ${files[@]} - do - do_astyle_check ${file} - if [[ $? -ne 0 ]];then - printf "[\033[1;36m%03d\033[0m\033[1;33m/\033[0m\033[1;34m%03d\033[0m]@%-80s \033[1;31m\033[5m%s\033[0m\n" \ - ${index} ${total} ${file} "[FAILED]" | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /' - failure_num=$((failure_num+1)) - else - printf "[\033[1;36m%03d\033[0m\033[1;33m/\033[0m\033[1;34m%03d\033[0m]@%-80s \033[1;32m%-5s\033[0m\n" \ - ${index} ${total} ${file} "[PASS]" | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /' - fi - index=$((index+1)) - done - printf "%0.s=" {1..96} - printf "\n" - local end_time=$(date +%s) - local duration=$((${end_time} - ${start_time})) - echo -e "\033[1;36mTotal files: ${total}\033[0m, \033[1;32msuccess: $((total-failure_num))\033[0m, \033[1;31mfailure: ${failure_num}\033[0m. \033[1;33mSpend time: ${duration} seconds\033[0m" - if [[ ${failure_num} -ne 0 ]]; then - exit -1 - fi -} - -function cmetrics_check() { - echo -e "\ -=================================================================================================\033[1;36m - ______ __ ___ ______ ______ ____ ____ ______ _____ ______ __ __ ______ ______ __ __ - / ____// |/ // ____//_ __// __ \ / _// ____// ___/ / ____// / / // ____// ____// //_/ - / / / /|_/ // __/ / / / /_/ / / / / / \__ \ / / / /_/ // __/ / / / ,< - / /___ / / / // /___ / / / _, _/_/ / / /___ ___/ / / /___ / __ // /___ / /___ / /| | - \____//_/ /_//_____/ /_/ /_/ |_|/___/ \____/ /____/ \____//_/ /_//_____/ \____//_/ |_|\033[0m -=================================================================================================" - if [[ ${1} == "simple" ]]; then - printf "%0.s*" {1..97} - printf "\n" - result=$(python3 ${CMETRICS_TOOL} -fp ./src) - echo "${result}" - printf "%0.s*" {1..97} - printf "\n" - CyclomaticComplexityPerMethod=$(echo "${result}" | grep '\[\*\] Cyclomatic Complexity per Method' | awk '{print $NF}') - if [[ $(echo "${CyclomaticComplexityPerMethod} > 5" | bc) -eq 1 ]]; then - echo -e "\033[1;31mFailure: cyclomatic complexity per method(${CyclomaticComplexityPerMethod}) greater then 5\033[0m." - exit 1 - else - echo -e "\033[1;32mSuccess: cyclomatic complexity per method(${CyclomaticComplexityPerMethod}) less then 5\033[0m." - exit 0 - fi - fi - - local start_time=$(date +%s) - local files - if [[ ${1} == "all" ]]; then - files=$(find ./src ./test -regextype posix-extended -regex ".*\.(h|c|cc)") - else - files=$(git diff --name-only HEAD | grep -E "*.h$|*.c$|*.cc$") - fi - files=(${files// / }) - local total=${#files[@]} - local failure_num=0 - local index=1 - if [[ ${total} -eq 0 ]]; then - return 0 - fi - for file in ${files[@]} - do - result=$(python3 ${CMETRICS_TOOL} -fp ${file}) - CyclomaticComplexityperMethod=$(echo "${result}" | grep "\[\*\] Cyclomatic Complexity per Method:" | awk '{print $NF}') - CyclomaticComplexityperMethod=${CyclomaticComplexityperMethod:-0} - MaximumCyclomaticComplexity=$(echo "${result}" | grep "\[\*\] Maximum Cyclomatic Complexity:" | awk '{print $NF}') - MaximumCyclomaticComplexity=${MaximumCyclomaticComplexity:-0} - MaximumDepth=$(echo "${result}" | grep "\[\*\] Maximum Depth:" | awk '{print $NF}') - MaximumDepth=${MaximumDepth:-0} - RawLines=$(echo "${result}" | grep "\[\*\] Raw Lines:" | awk '{print $NF}') - RawLines=${RawLines:-0} - if [[ ${MaximumCyclomaticComplexity} -gt 10 ]] || [[ $(echo "${CyclomaticComplexityperMethod} > 5" | bc) -eq 1 ]] || \ - [[ ${MaximumDepth} -gt 5 ]] || [[ ${RawLines} -gt 2000 ]]; then - printf "[\033[1;36m%03d\033[0m\033[1;33m/\033[0m\033[1;34m%03d\033[0m]@%-80s \033[1;31m\033[5m%s\033[0m\n" \ - ${index} ${total} ${file} "[FAILED]" | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /' - failure_num=$((failure_num+1)) - else - printf "[\033[1;36m%03d\033[0m\033[1;33m/\033[0m\033[1;34m%03d\033[0m]@%-80s \033[1;32m%-5s\033[0m\n" \ - ${index} ${total} ${file} "[PASS]" | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /' - fi - printf "%s\n%s\n%s\n %-1.3f | %3d | %2d | %4d\n%s\n" \ -"-------------------------------------------------------------------------------------------------" \ -" Cyclomatic Complexity per Method | Maximum Cyclomatic Complexity | Maximum Depth | Raw Lines " \ -"-------------------------------------------------------------------------------------------------" \ - ${CyclomaticComplexityperMethod} ${MaximumCyclomaticComplexity} ${MaximumDepth} ${RawLines} \ -"-------------------------------------------------------------------------------------------------" - index=$((index+1)) - done - printf "%0.s=" {1..97} - printf "\n" - local end_time=$(date +%s) - local duration=$((${end_time} - ${start_time})) - echo -e "\033[1;36mTotal files: ${total}\033[0m, \033[1;32msuccess: $((total-failure_num))\033[0m, \033[1;31mfailure: ${failure_num}\033[0m. \033[1;33mSpend time: ${duration} seconds\033[0m" - printf "%0.s*" {1..97} - printf "\n" - if [[ ${1} == "all" ]]; then - result=$(python3 ${CMETRICS_TOOL} -fp ./src) - else - result=$(python3 ${CMETRICS_TOOL} -fp ${files[@]}) - fi - echo "${result}" - printf "%0.s*" {1..96} - printf "\n" - CyclomaticComplexityPerMethod=$(echo "${result}" | grep '\[\*\] Cyclomatic Complexity per Method' | awk '{print $NF}') - if [[ $(echo "${CyclomaticComplexityPerMethod} > 5" | bc) -eq 1 ]]; then - echo -e "\033[1;31mFailure: cyclomatic complexity per method(${CyclomaticComplexityPerMethod}) greater then 5\033[0m." - exit 1 - else - echo -e "\033[1;32mSuccess: cyclomatic complexity per method(${CyclomaticComplexityPerMethod}) less then 5\033[0m." - exit 0 - fi -} - -function incremental_check() { - style_check "incremental" - if [[ $? -ne 0 ]]; then - exit -1 - fi - pclint_check "incremental" - if [[ $? -ne 0 ]]; then - exit -1 - fi - codestyle_check "incremental" - if [[ $? -ne 0 ]]; then - exit -1 - fi - cpp_check - if [[ $? -ne 0 ]]; then - return -1 - fi - - cmetrics_check "incremental" -} - -function static_check_all() { - style_check "all" - if [[ $? -ne 0 ]]; then - return -1 - fi - pclint_check "all" - if [[ $? -ne 0 ]]; then - return -1 - fi - codestyle_check "all" - if [[ $? -ne 0 ]]; then - return -1 - fi - cpp_check - if [[ $? -ne 0 ]]; then - return -1 - fi - - cmetrics_check "simple" -} - -if [[ $# -eq 0 ]];then - usage - exit 0 -fi - -args=`getopt -o upscmiaf:kh --long update-ci-tools,pclint,codestyle,detail-cmetrics,simple-cmetrics,incremental-check,all,quick-format:,style-check,cpp-check,help -- "$@"` -if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi -eval set -- "$args" - -while true; do - case "$1" in - -u|--update-ci-tools) update_ci_tools || (err "failed to update ci tools project" && exit -1); shift ;; - -p|--pclint) pclint_check "all" || (err "failed to perfrom pclint code static check" && exit -1); shift ;; - -s|--codestyle) codestyle_check "all" || (err "failed to perfrom codestyle(codedex) code static check" && exit -1); shift ;; - -c|--detail-cmetrics) cmetrics_check "all" || (err "failed to perform detail checks and statistics" && exit -1); shift ;; - -m|--simple-cmetrics) cmetrics_check "simple" || (err "failed to perform simple checks and statistics" && exit -1); shift ;; - -i|--incremental-check) incremental_check || (err "failed to perform incremental check" && exit -1); shift ;; - -a|--all) static_check_all || (err "failed to perform all checks and statistics" && exit -1); shift ;; - -f|--quick-format) quick_format $2 || (err "failed to format code" && exit -1); shift 2 ;; - -k|--style-check) style_check "all" || (err "failed to check code style" && exit -1); shift ;; - --cpp-check) cpp_check || (err "failed to check code style" && exit -1); shift ;; - -h|--help) usage ; exit 0 ;; - --) shift ; break ;; - *) err "invalid parameter" ; exit -1 ;; - esac -done - diff --git a/update-version.bash b/update-version.bash index 77a6434..76697b8 100755 --- a/update-version.bash +++ b/update-version.bash @@ -1,16 +1,25 @@ ####################################################################### -##- @Copyright (C) Huawei Technologies., Ltd. 2019. All rights reserved. -# - lcr 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. -##- @Description: generate cetification -##- @Author: wujing -##- @Create: 2019-04-25 +# lcr: utils library for iSula +# +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# +# Authors: +# Haozi007 +# +# 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.1 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, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# ####################################################################### #!/bin/bash # -- Gitee