!21 change format of source code

Merge pull request !21 from haozi007/master
This commit is contained in:
openeuler-ci-bot 2020-05-26 20:52:24 +08:00 committed by Gitee
commit fa88fb1744
50 changed files with 113 additions and 16879 deletions

View File

@ -0,0 +1,80 @@
From 74c5abe35a931aca850d5619faecbd62e75d9fb2 Mon Sep 17 00:00:00 2001
From: haozi007 <liuhao27@huawei.com>
Date: Tue, 26 May 2020 20:04:13 +0800
Subject: [PATCH] fix wrong license
Signed-off-by: haozi007 <liuhao27@huawei.com>
---
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 <liuhao27@huawei.com>
+#
+# 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

View File

@ -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)

View File

@ -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 LicenseVersion 2
Mulan Permissive Software LicenseVersion 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 ITS 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 LicenseVersion 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.

View File

@ -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.

View File

@ -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")

View File

@ -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()

View File

@ -1 +0,0 @@
#cmakedefine VERSION "@LCR_VERSION@"

File diff suppressed because it is too large Load Diff

BIN
lcr-2.0.2.tar.gz Normal file

Binary file not shown.

View File

@ -1,12 +0,0 @@
prefix=@CMAKE_INSTALL_PREFIX@
libdir=@CMAKE_INSTALL_PREFIX@/lib
localstatedir=@CMAKE_INSTALL_PREFIX@/var
includedir=@CMAKE_INSTALL_PREFIX@/include
Name: liblcr
Description: light-weighted container runtime library
Version: @LCR_VERSION@
URL: liblcr
Libs: -L@CMAKE_INSTALL_PREFIX@/lib -llcr
Cflags: -I@CMAKE_INSTALL_PREFIX@/include

View File

@ -1,29 +1,34 @@
%global _version 2.0.0
%global _release 20200418.180709.gitaabdb4e4
%global _version 2.0.2
%global _release 20200526.193309.gitfdf57813
%global _inner_name isula_libutils
Name: lcr
Version: %{_version}
Release: %{_release}
URL: lcr
Source: lcr-2.0.tar.gz
Source: lcr-2.0.2.tar.gz
Summary: Lightweight Container Runtime
Group: Applications/System
License: Mulan PSL v2
License: LGPLv2.1+
BuildRoot: %{_tmppath}/lcr-%{version}
Patch9000: 0001-fix-wrong-license.patch
BuildRequires: cmake
BuildRequires: lxc
BuildRequires: lxc-devel
BuildRequires: yajl yajl-devel
BuildRequires: python3
Requires: lxc
BuildRequires: zlib-devel yajl-devel gtest-devel
Requires: lxc yajl zlib
ExclusiveArch: x86_64 aarch64
%ifarch x86_64
Provides: liblcr.so()(64bit)
Provides: libisula_libutils.so()(64bit)
%endif
%ifarch aarch64
Provides: liblcr.so()(64bit)
Provides: libisula_libutils.so()(64bit)
%endif
%description
@ -35,10 +40,19 @@ kernel.
This package provides the lightweight container tools and library to control
lxc-based containers.
%package devel
Summary: Huawei container runtime, json and log C Library
Group: Libraries
ExclusiveArch: x86_64 aarch64
Requires: %{name} = %{version}-%{release}
%description devel
the %{name}-libs package contains libraries for running iSula applications.
%global debug_package %{nil}
%prep
%setup -c -n lcr-%{version}
%autosetup -n lcr -Sgit -p1
%build
mkdir -p build
@ -54,6 +68,12 @@ install -m 0644 ./src/liblcr.so %{buildroot}/%{_libdir}/liblcr.so
install -m 0644 ./conf/lcr.pc %{buildroot}/%{_libdir}/pkgconfig/lcr.pc
install -m 0644 ../src/lcrcontainer.h %{buildroot}/%{_includedir}/lcr/lcrcontainer.h
install -m 0644 ./src/libisula_libutils.so %{buildroot}/%{_libdir}/libisula_libutils.so
install -d $RPM_BUILD_ROOT/%{_includedir}/%{_inner_name}
install -m 0644 ../build/json/*.h %{buildroot}/%{_includedir}/%{_inner_name}/
install -m 0644 ../src/json/*.h %{buildroot}/%{_includedir}/%{_inner_name}/
install -m 0644 ../third_party/log.h %{buildroot}/%{_includedir}/%{_inner_name}/log.h
find %{buildroot} -type f -name '*.la' -exec rm -f {} ';'
find %{buildroot} -name '*.a' -exec rm -f {} ';'
find %{buildroot} -name '*.cmake' -exec rm -f {} ';'
@ -71,7 +91,12 @@ rm -rf %{buildroot}
%defattr(-,root,root,-)
%{_libdir}/*
%{_libdir}/pkgconfig/lcr.pc
%files devel
%defattr(-,root,root,-)
%{_includedir}/lcr/lcrcontainer.h
%{_includedir}/%{_inner_name}/*.h
%changelog
* Fri Apr 14 2017 Hui Wang <hw.huiwang@huawei.com> - 0.0.1

View File

@ -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)

View File

@ -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 <stdio.h>
#include <string.h>
#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 = 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 = 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;
}

View File

@ -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 <stdlib.h>
#include <strings.h>
#include <stdarg.h>
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

2590
src/conf.c

File diff suppressed because it is too large Load Diff

View File

@ -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*/

View File

@ -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

View File

@ -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 <stdarg.h>
#include <stdlib.h>
// 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 = 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 = 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 = 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;
}

View File

@ -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

View File

@ -1,2 +0,0 @@
# generate .c and .h files for json
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/schema)

View File

@ -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 <stdlib.h>
#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;
}

View File

@ -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

View File

@ -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()

View File

@ -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"
}
}
}

View File

@ -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"
}
}
}
}

View File

@ -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"
]
}
}
}

View File

@ -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"
]
}

View File

@ -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"
]
}

View File

@ -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"
}
}
}

View File

@ -1,3 +0,0 @@
# get current directory sources files
message("-- do nothing ")

File diff suppressed because it is too large Load Diff

View File

@ -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 <giuseppe@scrivano.org>
# 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 <http://www.gnu.org/licenses/>.
#
# 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 <stdlib.h>
# include <stdbool.h>
# include <stdio.h>
# include <string.h>
# include <stdint.h>
# include <yajl/yajl_tree.h>
# include <yajl/yajl_gen.h>
# 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
'''

View File

@ -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 <giuseppe@scrivano.org>
# 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 <http://www.gnu.org/licenses/>.
#
# 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()

View File

@ -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 <giuseppe@scrivano.org>
# 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 <http://www.gnu.org/licenses/>.
#
# 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 <sys/types.h>\n")
header.write("#include <stdint.h>\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")

View File

@ -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 <giuseppe@scrivano.org>
# 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 <http://www.gnu.org/licenses/>.
#
# 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)

View File

@ -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 <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stdint.h>
#include <config.h>
#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;
}

View File

@ -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 <stddef.h>
#include <stdio.h>
char *fread_file(FILE *stream, size_t *length);
char *read_file(const char *path, size_t *length);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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 <limits.h>
#include <stdint.h>
#include <stdbool.h>
#include <sys/types.h>
#include <lxc/lxccontainer.h>
#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 */

View File

@ -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 <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <signal.h>
#include <string.h>
#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] = 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 = util_strdup_s(c->name);
state = c->state(c);
lcs->state = state ? util_strdup_s(state) : 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 (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 = 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 (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 = 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 (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);
}

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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 <lxc/lxccontainer.h>
#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) = 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 */

386
src/log.c
View File

@ -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 <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <inttypes.h>
#include <time.h>
#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 = 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 = 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 = util_strdup_s(log->name);
full_path = util_strdup_s(log->file);
nret = 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, &timestamp) == -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 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;
}

124
src/log.h
View File

@ -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 <stdbool.h>
#include <errno.h>
#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 */

File diff suppressed because it is too large Load Diff

View File

@ -1,211 +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 <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
#include <stdio.h>
#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" }, \
}
bool file_exists(const char *path);
bool dir_exists(const char *path);
int wait_for_pid(pid_t pid);
int wait_for_pid_status(pid_t pid);
char *util_string_join(const char *sep, const char **parts, size_t len);
int util_mkdir_p(const char *dir, mode_t mode);
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 mem_realloc(void **newptr, size_t newsize, void *oldptr, size_t oldsize);
bool util_valid_cmd_arg(const char *arg);
int util_safe_ullong(const char *numstr, unsigned long long *converted);
int util_safe_strtod(const char *numstr, double *converted);
int util_safe_uint(const char *numstr, unsigned int *converted);
int parse_byte_size_string(const char *s, int64_t *converted);
bool util_dir_exists(const char *path);
int util_ensure_path(char **confpath, const char *path);
int util_recursive_rmdir(const char *dirpath, int recursive_depth);
char *util_string_replace(const char *needle, const char *replacement, const char *haystack);
int util_open(const char *filename, int flags, mode_t mode);
FILE *util_fopen(const char *filename, const char *mode);
void *util_common_calloc_s(size_t size);
int util_safe_int(const char *numstr, int *converted);
int util_check_inherited(bool closeall, int fd_to_ignore);
char *util_string_append(const char *post, const char *pre);
char *util_string_split_prefix(size_t prefix_len, const char *file);
int util_build_dir(const char *name);
ssize_t util_write_nointr(int fd, const void *buf, size_t count);
ssize_t util_read_nointr(int fd, void *buf, size_t count);
void util_free_array(char **array);
int util_sig_parse(const char *signame);
bool util_valid_signal(int sig);
size_t util_array_len(char **array);
const char *str_skip_str(const char *str, const char *skip);
int util_array_append(char ***array, const char *element);
int util_safe_llong(const char *numstr, long long *converted);
char *util_strdup_s(const char *src);
int util_null_stdfds(void);
bool util_copy_file(const char *src_file, const char *dst_file, mode_t mode);
bool util_write_file(const char *filepath, const char *content, size_t len, bool add_newline, mode_t mode);
int util_atomic_write_file(const char *filepath, const char *content);
#ifdef __cplusplus
}
#endif
#endif /* __LCR_UTILS_H */

View File

@ -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