Package init
This commit is contained in:
parent
7ceac72768
commit
3b37e6bfaa
@ -5,7 +5,7 @@ include(cmake/set_build_flags.cmake)
|
|||||||
|
|
||||||
option(VERSION "set lcr version" ON)
|
option(VERSION "set lcr version" ON)
|
||||||
if (VERSION STREQUAL "ON")
|
if (VERSION STREQUAL "ON")
|
||||||
set(LCR_VERSION "1.0.15")
|
set(LCR_VERSION "1.0.17")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(DEBUG "set lcr gcc option" ON)
|
option(DEBUG "set lcr gcc option" ON)
|
||||||
|
|||||||
@ -10,14 +10,6 @@ iSulad follows the kernel coding conventions. You can find a detailed introducti
|
|||||||
|
|
||||||
- https://www.kernel.org/doc/html/v4.10/process/coding-style.html
|
- https://www.kernel.org/doc/html/v4.10/process/coding-style.html
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
Without considering distribution specific details a simple
|
|
||||||
|
|
||||||
mkdir -p build && cd ./build && cmake .. && make && sudo make install
|
|
||||||
|
|
||||||
is usually sufficient.
|
|
||||||
|
|
||||||
## Licensing
|
## Licensing
|
||||||
|
|
||||||
lcr is licensed under the Mulan PSL v1.
|
lcr is licensed under the Mulan PSL v1.
|
||||||
|
|||||||
@ -6,7 +6,7 @@ includedir=@CMAKE_INSTALL_PREFIX@/include
|
|||||||
Name: liblcr
|
Name: liblcr
|
||||||
Description: light-weighted container runtime library
|
Description: light-weighted container runtime library
|
||||||
Version: @LCR_VERSION@
|
Version: @LCR_VERSION@
|
||||||
URL: http://code.huawei.com/containers/liblcr
|
URL: liblcr
|
||||||
Libs: -L@CMAKE_INSTALL_PREFIX@/lib -llcr
|
Libs: -L@CMAKE_INSTALL_PREFIX@/lib -llcr
|
||||||
Cflags: -I@CMAKE_INSTALL_PREFIX@/include
|
Cflags: -I@CMAKE_INSTALL_PREFIX@/include
|
||||||
|
|
||||||
|
|||||||
6
lcr.spec
6
lcr.spec
@ -1,9 +1,9 @@
|
|||||||
%global _version 1.0.15
|
%global _version 1.0.17
|
||||||
%global _release 20190612.105034.gitefd3b7ac
|
%global _release 20191222.223702.gita44996d6
|
||||||
Name: lcr
|
Name: lcr
|
||||||
Version: %{_version}
|
Version: %{_version}
|
||||||
Release: %{_release}
|
Release: %{_release}
|
||||||
URL: http://code.huawei.com/containers/lcr
|
URL: lcr
|
||||||
Source: lcr-1.0.tar.gz
|
Source: lcr-1.0.tar.gz
|
||||||
Summary: Lightweight Container Runtime
|
Summary: Lightweight Container Runtime
|
||||||
Group: Applications/System
|
Group: Applications/System
|
||||||
|
|||||||
@ -54,7 +54,6 @@ if (CMAKE_TOOLCHAIN_FILE)
|
|||||||
target_link_libraries(liblcr ${EXTRAL_LINK_LIBS})
|
target_link_libraries(liblcr ${EXTRAL_LINK_LIBS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(cmd)
|
|
||||||
if (LCR_GCOV)
|
if (LCR_GCOV)
|
||||||
target_link_libraries(liblcr -lgcov)
|
target_link_libraries(liblcr -lgcov)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@ -1,22 +0,0 @@
|
|||||||
# get lcr source files
|
|
||||||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} cmdsrcs)
|
|
||||||
|
|
||||||
# set lcr binary
|
|
||||||
add_executable(lcr ${cmdsrcs})
|
|
||||||
target_link_libraries(lcr liblcr)
|
|
||||||
|
|
||||||
# set lcr include headers
|
|
||||||
target_include_directories(lcr
|
|
||||||
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
PUBLIC ${CMAKE_SOURCE_DIR}/src/json
|
|
||||||
PUBLIC ${CMAKE_SOURCE_DIR}/src/json/schema/src
|
|
||||||
PUBLIC ${CMAKE_BINARY_DIR}/json
|
|
||||||
PUBLIC ${CMAKE_BINARY_DIR}/conf
|
|
||||||
)
|
|
||||||
if (LCR_GCOV)
|
|
||||||
target_link_libraries(lcr -lgcov)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# install all files
|
|
||||||
install(TARGETS lcr
|
|
||||||
RUNTIME DESTINATION bin PERMISSIONS OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE)
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container arguments functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "commands.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "securec.h"
|
|
||||||
|
|
||||||
/* lcr arguments init */
|
|
||||||
void lcr_arguments_init(struct lcr_arguments *args)
|
|
||||||
{
|
|
||||||
args->name = NULL;
|
|
||||||
args->log_file = NULL;
|
|
||||||
args->log_priority = NULL;
|
|
||||||
args->quiet = 0;
|
|
||||||
args->lcrpath = NULL;
|
|
||||||
args->create_rootfs = NULL;
|
|
||||||
args->create_dist = NULL;
|
|
||||||
args->spec_bundle = NULL;
|
|
||||||
args->spec_translate = NULL;
|
|
||||||
args->spec_dist = NULL;
|
|
||||||
args->list_quiet = false;
|
|
||||||
args->list_running = false;
|
|
||||||
args->list_stopped = false;
|
|
||||||
args->list_active = false;
|
|
||||||
args->start_daemonize = true;
|
|
||||||
args->start_pidfile = NULL;
|
|
||||||
args->console_logpath = NULL;
|
|
||||||
args->console_fifos[0] = NULL;
|
|
||||||
args->console_fifos[1] = NULL;
|
|
||||||
args->delete_force = false;
|
|
||||||
args->argc = 0;
|
|
||||||
args->argv = NULL;
|
|
||||||
args->ociconfig = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* print common help */
|
|
||||||
void print_common_help()
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
struct lcr_arguments cmd_common_args = {};
|
|
||||||
struct command_option options[] = {
|
|
||||||
COMMON_OPTIONS(cmd_common_args)
|
|
||||||
};
|
|
||||||
len = sizeof(options) / sizeof(options[0]);
|
|
||||||
qsort(options, len, sizeof(options[0]), compare_options);
|
|
||||||
fprintf(stdout, "COMMON OPTIONS :\n");
|
|
||||||
print_options((int)len, options);
|
|
||||||
}
|
|
||||||
@ -1,99 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container arguments definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __LCR_ARGUMENTS_H
|
|
||||||
#define __LCR_ARGUMENTS_H
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
struct lcr_arguments;
|
|
||||||
|
|
||||||
struct args_cgroup_resources {
|
|
||||||
char *blkio_weight;
|
|
||||||
char *cpu_shares;
|
|
||||||
char *cpu_period;
|
|
||||||
char *cpu_quota;
|
|
||||||
char *cpuset_cpus;
|
|
||||||
char *cpuset_mems;
|
|
||||||
char *memory_limit;
|
|
||||||
char *memory_swap;
|
|
||||||
char *memory_reservation;
|
|
||||||
char *kernel_memory_limit;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct lcr_arguments {
|
|
||||||
const char *progname; /* sub command name */
|
|
||||||
|
|
||||||
// For common options
|
|
||||||
char *name; /*container name */
|
|
||||||
char *log_file;
|
|
||||||
char *log_priority;
|
|
||||||
int quiet;
|
|
||||||
|
|
||||||
char *lcrpath;
|
|
||||||
|
|
||||||
// lcr create
|
|
||||||
char *create_rootfs;
|
|
||||||
char *create_dist;
|
|
||||||
char *ociconfig;
|
|
||||||
|
|
||||||
// lcr run
|
|
||||||
// lcr spec
|
|
||||||
char *spec_bundle;
|
|
||||||
char *spec_translate;
|
|
||||||
char *spec_dist;
|
|
||||||
// lcr list
|
|
||||||
bool list_quiet;
|
|
||||||
bool list_active;
|
|
||||||
bool list_running;
|
|
||||||
bool list_stopped;
|
|
||||||
// lcr start
|
|
||||||
bool start_daemonize;
|
|
||||||
char *start_pidfile;
|
|
||||||
char *console_logpath;
|
|
||||||
const char *console_fifos[2];
|
|
||||||
|
|
||||||
// lcr kill
|
|
||||||
char *signal;
|
|
||||||
|
|
||||||
// lcr delete
|
|
||||||
bool delete_force;
|
|
||||||
// lcr update
|
|
||||||
struct args_cgroup_resources cr;
|
|
||||||
|
|
||||||
// remaining arguments
|
|
||||||
char * const * argv;
|
|
||||||
int argc;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define COMMON_OPTIONS(cmdargs) \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "logfile", 'o', &(cmdargs).log_file, \
|
|
||||||
"Set the log file path wherer debug information is written", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "logpriority", 'l', &(cmdargs).log_priority, "Set log priority to LEVEL", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_BOOL, false, "silence", 's', &(cmdargs).quiet, "Don't produce any output to stderr", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "lcrpath", 'P', &(cmdargs).lcrpath, "Use specified container path", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "help", 0, NULL, "Show help", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "version", 0, NULL, "Print the version", NULL }
|
|
||||||
|
|
||||||
|
|
||||||
extern void print_common_help();
|
|
||||||
|
|
||||||
extern void lcr_arguments_init(struct lcr_arguments *args);
|
|
||||||
|
|
||||||
#define lcr_print_error(arg, fmt, args...) \
|
|
||||||
fprintf(stderr, "%s: " fmt "\n", (arg)->progname, ## args)
|
|
||||||
|
|
||||||
#endif /*__LCR_ARGUMENTS_H*/
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container clean functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "clean.h"
|
|
||||||
#include "lcrcontainer.h"
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
const char g_lcr_cmd_clean_desc[] =
|
|
||||||
"Delete any resources held by the container often used with detached container NAME";
|
|
||||||
static const char g_lcr_cmd_clean_usage[] = "clean [command options] --name=NAME";
|
|
||||||
|
|
||||||
struct lcr_arguments g_lcr_cmd_clean_args;
|
|
||||||
|
|
||||||
int cmd_clean_main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
command_t cmd;
|
|
||||||
struct command_option options[] = {
|
|
||||||
CLEAN_OPTIONS(g_lcr_cmd_clean_args),
|
|
||||||
COMMON_OPTIONS(g_lcr_cmd_clean_args)
|
|
||||||
};
|
|
||||||
|
|
||||||
lcr_arguments_init(&g_lcr_cmd_clean_args);
|
|
||||||
|
|
||||||
command_init(&cmd, options, sizeof(options) / sizeof(options[0]),
|
|
||||||
argc, (const char **)argv,
|
|
||||||
g_lcr_cmd_clean_desc, g_lcr_cmd_clean_usage);
|
|
||||||
if (command_parse_args(&cmd, &(g_lcr_cmd_clean_args.argc), &(g_lcr_cmd_clean_args.argv))) {
|
|
||||||
exit(EINVALIDARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lcr_log_init(g_lcr_cmd_clean_args.name, g_lcr_cmd_clean_args.log_file,
|
|
||||||
g_lcr_cmd_clean_args.log_priority,
|
|
||||||
g_lcr_cmd_clean_args.progname,
|
|
||||||
g_lcr_cmd_clean_args.quiet,
|
|
||||||
LOGPATH)) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_lcr_cmd_clean_args.name == NULL) {
|
|
||||||
fprintf(stderr, "missing container name, use -n,--name option\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lcr_clean(g_lcr_cmd_clean_args.name,
|
|
||||||
g_lcr_cmd_clean_args.lcrpath,
|
|
||||||
g_lcr_cmd_clean_args.log_file,
|
|
||||||
g_lcr_cmd_clean_args.log_priority,
|
|
||||||
0)) {
|
|
||||||
fprintf(stderr, "Failed to clean container %s\n", g_lcr_cmd_clean_args.name);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stdout, "Container \"%s\" Cleaned\n", g_lcr_cmd_clean_args.name);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container clean definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __CMD_CLEAN_H
|
|
||||||
#define __CMD_CLEAN_H
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "commander.h"
|
|
||||||
|
|
||||||
#define CLEAN_OPTIONS(cmdargs) \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "name", 'n', &(cmdargs).name, "Name of the container", NULL }
|
|
||||||
|
|
||||||
extern const char g_lcr_cmd_clean_desc[];
|
|
||||||
extern struct lcr_arguments g_lcr_cmd_clean_args;
|
|
||||||
int cmd_clean_main(int argc, const char **argv);
|
|
||||||
|
|
||||||
#endif /* __CMD_CLEAN_H */
|
|
||||||
@ -1,433 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container commander functions
|
|
||||||
******************************************************************************/
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include "utils.h"
|
|
||||||
#include "commander.h"
|
|
||||||
#include "securec.h"
|
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
int compare_options(const void *s1, const void *s2)
|
|
||||||
{
|
|
||||||
return strcmp((*(const command_option_t *)s1).large, (*(const command_option_t *)s2).large);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_max_option_length(int options_len, const command_option_t *options)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int max_option_len = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < options_len; i++) {
|
|
||||||
command_option_t option = options[i];
|
|
||||||
// -s
|
|
||||||
int len = 2;
|
|
||||||
// -s, --large
|
|
||||||
if (option.large != NULL) {
|
|
||||||
len = (int)(strlen(option.large) + 6);
|
|
||||||
}
|
|
||||||
if (len > max_option_len) {
|
|
||||||
max_option_len = len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return max_option_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void do_print_options(int options_len, const command_option_t *options, int max_option_len)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < options_len; i++) {
|
|
||||||
command_option_t option = options[i];
|
|
||||||
int curindex;
|
|
||||||
int space_left = 0;
|
|
||||||
|
|
||||||
curindex = fprintf(stdout, " ");
|
|
||||||
if (option.small) {
|
|
||||||
curindex += fprintf(stdout, "-%c", (char)(option.small));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (option.large != NULL) {
|
|
||||||
if (option.small) {
|
|
||||||
curindex += fprintf(stdout, ", --%s", option.large);
|
|
||||||
} else {
|
|
||||||
curindex += fprintf(stdout, " --%s", option.large);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (curindex <= max_option_len) {
|
|
||||||
space_left = max_option_len - curindex;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stdout, "%*s%s\n", space_left, "", option.description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_options(int options_len, const command_option_t *options)
|
|
||||||
{
|
|
||||||
int max_option_len = 0;
|
|
||||||
|
|
||||||
max_option_len = get_max_option_length(options_len, options);
|
|
||||||
|
|
||||||
// format: " -s, --large description"
|
|
||||||
max_option_len += 6;
|
|
||||||
|
|
||||||
do_print_options(options_len, options, max_option_len);
|
|
||||||
|
|
||||||
fputc('\n', stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void command_help(const command_t *self)
|
|
||||||
{
|
|
||||||
const char *progname = strrchr(self->name, '/');
|
|
||||||
if (progname == NULL) {
|
|
||||||
progname = self->name;
|
|
||||||
} else {
|
|
||||||
progname++;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "\nUsage: %s [options] %s\n\n", progname, self->usage);
|
|
||||||
fprintf(stderr, "%s\n\n", self->description);
|
|
||||||
qsort(self->options, (size_t)(self->option_count), sizeof(self->options[0]), compare_options);
|
|
||||||
print_options(self->option_count, self->options);
|
|
||||||
}
|
|
||||||
|
|
||||||
void command_init(command_t *self, command_option_t *options, int options_len, int argc, const char **argv,
|
|
||||||
const char *description, const char *usage)
|
|
||||||
{
|
|
||||||
if (memset_s(self, sizeof(command_t), 0, sizeof(command_t)) != EOK) {
|
|
||||||
COMMAND_ERROR("Failed to set memory");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self->name = argv[0];
|
|
||||||
self->argc = argc - 2;
|
|
||||||
self->argv = argv + 2;
|
|
||||||
self->usage = usage;
|
|
||||||
self->description = description;
|
|
||||||
self->options = options;
|
|
||||||
self->option_count = options_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
void command_option(command_t *self, command_option_type_t type, void *data, int small, const char *large,
|
|
||||||
const char *desc, command_callback_t cb)
|
|
||||||
{
|
|
||||||
if (self->option_count == COMMANDER_MAX_OPTIONS) {
|
|
||||||
COMMAND_ERROR("Maximum option definitions exceeded\n");
|
|
||||||
exit(EINVALIDARGS);
|
|
||||||
}
|
|
||||||
int n = self->option_count++;
|
|
||||||
command_option_t *option = &(self->options[n]);
|
|
||||||
option->type = type;
|
|
||||||
option->data = data;
|
|
||||||
option->cb = cb;
|
|
||||||
option->small = small;
|
|
||||||
option->description = desc;
|
|
||||||
option->large = large;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int read_option_arg(command_t *self, command_option_t *option, const char **opt_arg, const char **readed)
|
|
||||||
{
|
|
||||||
if ((self == NULL) || (option == NULL) || (opt_arg == NULL)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (option->hasdata) {
|
|
||||||
*readed = *opt_arg;
|
|
||||||
*opt_arg = NULL;
|
|
||||||
}
|
|
||||||
if (!option->hasdata && self->argc > 1) {
|
|
||||||
option->hasdata = true;
|
|
||||||
*readed = *++(self->argv);
|
|
||||||
self->argc--;
|
|
||||||
}
|
|
||||||
if (!option->hasdata) {
|
|
||||||
COMMAND_ERROR("Flag needs an argument: --%s", option->large);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handle_option_type_bool(const command_option_t *option, const char **opt_arg)
|
|
||||||
{
|
|
||||||
if (option->hasdata && strcmp(*opt_arg, "true") && strcmp(*opt_arg, "false")) {
|
|
||||||
COMMAND_ERROR("Invalid boolean value \"%s\" for flag --%s", *opt_arg, option->large);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (option->hasdata) {
|
|
||||||
if (!strcmp(*opt_arg, "true")) {
|
|
||||||
*(bool *)(option->data) = true;
|
|
||||||
} else {
|
|
||||||
*(bool *)(option->data) = false;
|
|
||||||
}
|
|
||||||
*opt_arg = NULL;
|
|
||||||
} else {
|
|
||||||
*(bool *)option->data = true;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handle_option_type_string(command_t *self, command_option_t *option, const char **opt_arg)
|
|
||||||
{
|
|
||||||
if (read_option_arg(self, option, opt_arg, (const char **)(option->data))) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (option->cb != NULL) {
|
|
||||||
return option->cb(option, *(char **)(option->data));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handle_option_type_string_dup(command_t *self, command_option_t *option, const char **opt_arg)
|
|
||||||
{
|
|
||||||
const char *readed = NULL;
|
|
||||||
if (read_option_arg(self, option, opt_arg, &readed)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(*(char **)(option->data));
|
|
||||||
|
|
||||||
*(char **)option->data = util_strdup_s(readed);
|
|
||||||
|
|
||||||
if (option->cb != NULL) {
|
|
||||||
return option->cb(option, readed);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int handle_option_type_callback(command_t *self, command_option_t *option, const char **opt_arg)
|
|
||||||
{
|
|
||||||
const char *readed = NULL;
|
|
||||||
if (read_option_arg(self, option, opt_arg, &readed)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (option->cb == NULL) {
|
|
||||||
COMMAND_ERROR("Must specify callback for type array");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return option->cb(option, readed);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_get_option_data(command_t *self, command_option_t *option, const char **opt_arg)
|
|
||||||
{
|
|
||||||
if (option == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
switch (option->type) {
|
|
||||||
case CMD_OPT_TYPE_BOOL:
|
|
||||||
return handle_option_type_bool(option, opt_arg);
|
|
||||||
case CMD_OPT_TYPE_STRING:
|
|
||||||
return handle_option_type_string(self, option, opt_arg);
|
|
||||||
case CMD_OPT_TYPE_STRING_DUP:
|
|
||||||
return handle_option_type_string_dup(self, option, opt_arg);
|
|
||||||
case CMD_OPT_TYPE_CALLBACK:
|
|
||||||
return handle_option_type_callback(self, option, opt_arg);
|
|
||||||
default:
|
|
||||||
COMMAND_ERROR("Unkown command option type:%d", option->type);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static int have_short_options(const command_t *self, char arg)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < self->option_count; i++) {
|
|
||||||
if (self->options[i].small == arg) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_option_argument_when_match_flag(const char **opt_arg, command_option_t *option, bool *found)
|
|
||||||
{
|
|
||||||
*found = true;
|
|
||||||
if ((*opt_arg)[1] != '\0') {
|
|
||||||
if ((*opt_arg)[1] == '=') {
|
|
||||||
*opt_arg = *opt_arg + 2;
|
|
||||||
option->hasdata = true;
|
|
||||||
} else {
|
|
||||||
*opt_arg = *opt_arg + 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
*opt_arg = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_parse_short_arg(command_t *self, const char *arg)
|
|
||||||
{
|
|
||||||
const char *opt_arg = arg;
|
|
||||||
bool found = true;
|
|
||||||
int j;
|
|
||||||
|
|
||||||
do {
|
|
||||||
found = false;
|
|
||||||
if (opt_arg[0] == 'h' && have_short_options(self, 'h') < 0) {
|
|
||||||
command_help(self);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
for (j = 0; j < self->option_count; ++j) {
|
|
||||||
command_option_t *option = &(self->options[j]);
|
|
||||||
option->hasdata = false;
|
|
||||||
|
|
||||||
if (option->small != opt_arg[0]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// match flag
|
|
||||||
set_option_argument_when_match_flag(&opt_arg, option, &found);
|
|
||||||
|
|
||||||
if (command_get_option_data(self, option, &opt_arg)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} while (found && (opt_arg != NULL));
|
|
||||||
|
|
||||||
if (opt_arg != NULL) {
|
|
||||||
COMMAND_ERROR("Unkown flag found:'%c'", opt_arg[0]);
|
|
||||||
exit(EINVALIDARGS);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int command_parse_long_arg(command_t *self, const char *arg)
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
|
|
||||||
if (!strcmp(arg, "help")) {
|
|
||||||
command_help(self);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (j = 0; j < self->option_count; ++j) {
|
|
||||||
command_option_t *option = &(self->options[j]);
|
|
||||||
const char *opt_arg = NULL;
|
|
||||||
option->hasdata = false;
|
|
||||||
|
|
||||||
if (option->large == NULL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
opt_arg = str_skip_str(arg, option->large);
|
|
||||||
if (opt_arg == NULL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt_arg[0]) {
|
|
||||||
if (opt_arg[0] != '=') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
opt_arg = opt_arg + 1;
|
|
||||||
option->hasdata = true;
|
|
||||||
} else {
|
|
||||||
opt_arg = NULL;
|
|
||||||
}
|
|
||||||
if (command_get_option_data(self, option, &opt_arg)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
COMMAND_ERROR("Unkown flag found:'--%s'\n", arg);
|
|
||||||
exit(EINVALIDARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
int command_parse_args(command_t *self, int *argc, char * const **argv)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
for (; self->argc; self->argc--, self->argv++) {
|
|
||||||
const char *arg = self->argv[0];
|
|
||||||
|
|
||||||
if (arg[0] != '-' || !arg[1]) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// short option
|
|
||||||
if (arg[1] != '-') {
|
|
||||||
arg = arg + 1;
|
|
||||||
ret = command_parse_short_arg(self, arg);
|
|
||||||
if (!ret) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --
|
|
||||||
if (!arg[2]) {
|
|
||||||
self->argc--;
|
|
||||||
self->argv++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// long option
|
|
||||||
arg = arg + 2;
|
|
||||||
ret = command_parse_long_arg(self, arg);
|
|
||||||
if (!ret) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (self->argc > 0) {
|
|
||||||
*argc = self->argc;
|
|
||||||
*argv = (char * const *)(self->argv);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int command_append_array_with_space(command_option_t *option, const char *arg)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
char *narg = util_string_replace(SPACE_MAGIC_STR, " ", arg);
|
|
||||||
if (narg == NULL) {
|
|
||||||
COMMAND_ERROR("Memory allocation error");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
ret = util_array_append(option->data, narg);
|
|
||||||
free(narg);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int command_append_array(command_option_t *option, const char *arg)
|
|
||||||
{
|
|
||||||
if (option == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
char ***array = option->data;
|
|
||||||
return util_array_append(array, arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
int command_convert_llong(command_option_t *option, const char *arg)
|
|
||||||
{
|
|
||||||
if (option == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (util_safe_llong(arg, option->data)) {
|
|
||||||
COMMAND_ERROR("Invalid value \"%s\" for flag --%s", arg, option->large);
|
|
||||||
return EINVALIDARGS;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int command_convert_uint(command_option_t *option, const char *arg)
|
|
||||||
{
|
|
||||||
if (option == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (util_safe_uint(arg, option->data)) {
|
|
||||||
COMMAND_ERROR("Invalid value \"%s\" for flag --%s", arg, option->large);
|
|
||||||
return EINVALIDARGS;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container commander definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __COMMANDER_H_
|
|
||||||
#define __COMMANDER_H_
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#ifndef COMMANDER_MAX_OPTIONS
|
|
||||||
#define COMMANDER_MAX_OPTIONS 64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
/* no arguments */
|
|
||||||
CMD_OPT_TYPE_BOOL,
|
|
||||||
/* required arguments */
|
|
||||||
CMD_OPT_TYPE_STRING,
|
|
||||||
CMD_OPT_TYPE_STRING_DUP,
|
|
||||||
CMD_OPT_TYPE_CALLBACK
|
|
||||||
} command_option_type_t;
|
|
||||||
|
|
||||||
struct _command;
|
|
||||||
|
|
||||||
struct command_option;
|
|
||||||
|
|
||||||
typedef int (*command_callback_t)(struct command_option *options, const char *arg);
|
|
||||||
|
|
||||||
typedef struct command_option {
|
|
||||||
command_option_type_t type;
|
|
||||||
bool hasdata;
|
|
||||||
const char *large;
|
|
||||||
int small;
|
|
||||||
void *data;
|
|
||||||
const char *description;
|
|
||||||
command_callback_t cb;
|
|
||||||
} command_option_t;
|
|
||||||
|
|
||||||
typedef struct _command {
|
|
||||||
const char *type;
|
|
||||||
const char *usage;
|
|
||||||
const char *description;
|
|
||||||
const char *name;
|
|
||||||
const char *version;
|
|
||||||
int option_count;
|
|
||||||
command_option_t *options;
|
|
||||||
int argc;
|
|
||||||
const char **argv;
|
|
||||||
} command_t;
|
|
||||||
|
|
||||||
void command_init(command_t *self, command_option_t *options, int options_len, int argc, const char **argv,
|
|
||||||
const char *description, const char *usage);
|
|
||||||
|
|
||||||
int compare_options(const void *s1, const void *s2);
|
|
||||||
|
|
||||||
void print_options(int options_len, const command_option_t *options);
|
|
||||||
|
|
||||||
void command_help(const command_t *self);
|
|
||||||
|
|
||||||
void command_option(command_t *self, command_option_type_t type, void *data, int small, const char *large,
|
|
||||||
const char *desc, command_callback_t cb);
|
|
||||||
|
|
||||||
int command_parse_args(command_t *self, int *argc, char * const **argv);
|
|
||||||
|
|
||||||
int command_append_array(command_option_t *option, const char *arg);
|
|
||||||
|
|
||||||
int command_append_array_with_space(command_option_t *option, const char *arg);
|
|
||||||
|
|
||||||
int command_convert_llong(command_option_t *option, const char *arg);
|
|
||||||
|
|
||||||
int command_convert_uint(command_option_t *option, const char *arg);
|
|
||||||
|
|
||||||
#endif /* COMMANDER_H */
|
|
||||||
@ -1,157 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container commands functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "securec.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "commands.h"
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "config.h" // For VERSION
|
|
||||||
|
|
||||||
const char cmd_option_desc[] = "Options";
|
|
||||||
const char cmd_option_usage[] = "[OPTIONS] COMMAND [arg...]";
|
|
||||||
struct lcr_arguments g_lcr_cmd_args = {};
|
|
||||||
|
|
||||||
/* print version */
|
|
||||||
static void print_version()
|
|
||||||
{
|
|
||||||
printf("Version %s, commit %s\n", VERSION, LCR_GIT_COMMIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*command by name*/
|
|
||||||
const struct command *command_by_name(const struct command *commands, const char * const name)
|
|
||||||
{
|
|
||||||
size_t i = 0;
|
|
||||||
|
|
||||||
if (commands == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
if (!commands[i].name) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(commands[i].name, name) == 0) {
|
|
||||||
return commands + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compare commands */
|
|
||||||
int compare_commands(const void *s1, const void *s2)
|
|
||||||
{
|
|
||||||
return strcmp((*(const struct command *)s1).name, (*(const struct command *)s2).name);
|
|
||||||
}
|
|
||||||
// Default help command if implementation doesn't provide one
|
|
||||||
int command_default_help(const char * const program_name, struct command *commands, int argc, const char **argv)
|
|
||||||
{
|
|
||||||
const struct command *command = NULL;
|
|
||||||
|
|
||||||
if (commands == NULL) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc == 0) {
|
|
||||||
size_t i = 0;
|
|
||||||
size_t max_size = 0;
|
|
||||||
|
|
||||||
printf("USAGE:\n");
|
|
||||||
printf("\t%s [OPTIONS] COMMAND [args...]\n", program_name);
|
|
||||||
printf("\n");
|
|
||||||
printf("COMMANDS:\n");
|
|
||||||
|
|
||||||
for (i = 0; commands[i].name != NULL; i++) {
|
|
||||||
size_t cmd_size = strlen(commands[i].name);
|
|
||||||
if (cmd_size > max_size) {
|
|
||||||
max_size = cmd_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qsort(commands, i, sizeof(commands[0]), compare_commands);
|
|
||||||
for (i = 0; commands[i].name != NULL; i++) {
|
|
||||||
printf("\t%*s\t%s\n", -(int)max_size, commands[i].name, commands[i].description);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
print_common_help();
|
|
||||||
return 0;
|
|
||||||
} else if (argc > 1) {
|
|
||||||
printf("%s: unrecognized argument: \"%s\"\n", program_name, argv[1]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
command = command_by_name(commands, argv[0]);
|
|
||||||
|
|
||||||
if (command == NULL) {
|
|
||||||
printf("%s: sub-command \"%s\" not found\n", program_name, argv[0]);
|
|
||||||
printf("run `lcr --help` for a list of sub-commonds\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command->longdesc != NULL) {
|
|
||||||
printf("%s\n", command->longdesc);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* option command init */
|
|
||||||
void option_command_init(command_t *self, command_option_t *options, int options_len, int argc, const char **argv,
|
|
||||||
const char *description, const char *usage)
|
|
||||||
{
|
|
||||||
if (memset_s(self, sizeof(command_t), 0, sizeof(command_t)) != EOK) {
|
|
||||||
COMMAND_ERROR("Failed to set memory");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self->name = argv[0];
|
|
||||||
self->argc = argc - 1;
|
|
||||||
self->argv = argv + 1;
|
|
||||||
self->usage = usage;
|
|
||||||
self->description = description;
|
|
||||||
self->options = options;
|
|
||||||
self->option_count = options_len;
|
|
||||||
}
|
|
||||||
// Tries to execute a command in the command list. The command name
|
|
||||||
// must be in argv[1]. Example usage:
|
|
||||||
//
|
|
||||||
int run_command(struct command *commands, int argc, const char **argv)
|
|
||||||
{
|
|
||||||
const struct command *command = NULL;
|
|
||||||
|
|
||||||
if (argc == 1) {
|
|
||||||
return command_default_help(argv[0], commands, argc - 1, argv + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
|
|
||||||
return command_default_help(argv[0], commands, argc - 2, argv + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(argv[1], "--version") == 0) {
|
|
||||||
print_version();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
command = command_by_name(commands, argv[1]);
|
|
||||||
if (command != NULL) {
|
|
||||||
return command->executor(argc, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s: command \"%s\" not found\n", argv[0], argv[1]);
|
|
||||||
printf("run `%s --help` or `run -h` for a list of sub-commonds\n", argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container commands definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __COMMAND_H
|
|
||||||
#define __COMMAND_H
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "commander.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
// A command is described by:
|
|
||||||
// @name: The name which should be passed as a second parameter
|
|
||||||
// @executor: The function that will be executed if the command
|
|
||||||
// matches. Receives the argc of the program minus two, and
|
|
||||||
// the rest os argv
|
|
||||||
// @description: Brief description, will show in help messages
|
|
||||||
// @longdesc: Long descripton to show when you run `help <command>`
|
|
||||||
struct command {
|
|
||||||
const char * const name;
|
|
||||||
int (*executor)(int, const char **);
|
|
||||||
const char * const description;
|
|
||||||
const char * const longdesc;
|
|
||||||
struct lcr_arguments *args;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Gets a pointer to a command, to allow implementing custom behavior
|
|
||||||
// returns null if not found.
|
|
||||||
//
|
|
||||||
// NOTE: Command arrays must end in a command with all member is NULL
|
|
||||||
const struct command *command_by_name(const struct command *commands, const char * const name);
|
|
||||||
|
|
||||||
// Default help command if implementation doesn't prvide one
|
|
||||||
int commmand_default_help(const char * const program_name, struct command *commands, int argc, char **argv);
|
|
||||||
|
|
||||||
// Tries to execute a command in the command list, The command name
|
|
||||||
// must be in argv[1]. Example usage
|
|
||||||
int run_command(struct command *commands, int argc, const char **argv);
|
|
||||||
#endif /* __COMMAND_H */
|
|
||||||
122
src/cmd/create.c
122
src/cmd/create.c
@ -1,122 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container create functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "lcrcontainer.h"
|
|
||||||
#include "create.h"
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "read_file.h"
|
|
||||||
|
|
||||||
const char g_lcr_cmd_create_desc[] = "create a container";
|
|
||||||
static const char g_lcr_cmd_create_usage[] = "create --name=NAME --rootfs=<dir|blkdev>";
|
|
||||||
|
|
||||||
struct lcr_arguments g_lcr_cmd_create_args = { 0 };
|
|
||||||
|
|
||||||
static int check_create_args(struct lcr_arguments *lcr_cmd_create_args)
|
|
||||||
{
|
|
||||||
if (lcr_cmd_create_args->name == NULL) {
|
|
||||||
ERROR("Missing --name,-n option\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lcr_cmd_create_args->create_rootfs == NULL) {
|
|
||||||
ERROR("Missing --rootfs option\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lcr_cmd_create_args->create_dist == NULL) {
|
|
||||||
lcr_cmd_create_args->create_dist = "ubuntu";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file_exists(lcr_cmd_create_args->create_rootfs)) {
|
|
||||||
ERROR("Rootfs dir \"%s\" does not exist\n", lcr_cmd_create_args->create_rootfs);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int read_oci_json_data(char **oci_json_data, size_t *filesize)
|
|
||||||
{
|
|
||||||
if (g_lcr_cmd_create_args.ociconfig == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
*oci_json_data = read_file(g_lcr_cmd_create_args.ociconfig, filesize);
|
|
||||||
if (*oci_json_data == NULL) {
|
|
||||||
ERROR("Can not read the file \"%s\"\n", g_lcr_cmd_create_args.ociconfig);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cmd_create_main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
char *oci_json_data = NULL;
|
|
||||||
size_t filesize;
|
|
||||||
command_t cmd;
|
|
||||||
struct command_option options[] = {
|
|
||||||
CREATE_OPTIONS(g_lcr_cmd_create_args),
|
|
||||||
COMMON_OPTIONS(g_lcr_cmd_create_args)
|
|
||||||
};
|
|
||||||
|
|
||||||
lcr_arguments_init(&g_lcr_cmd_create_args);
|
|
||||||
|
|
||||||
command_init(&cmd, options, sizeof(options) / sizeof(options[0]), argc, (const char **)argv,
|
|
||||||
g_lcr_cmd_create_desc, g_lcr_cmd_create_usage);
|
|
||||||
|
|
||||||
if (command_parse_args(&cmd, &g_lcr_cmd_create_args.argc, &g_lcr_cmd_create_args.argv)) {
|
|
||||||
exit(EINVALIDARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (check_create_args(&g_lcr_cmd_create_args)) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (read_oci_json_data(&oci_json_data, &filesize) != 0) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lcr_log_init(g_lcr_cmd_create_args.name,
|
|
||||||
g_lcr_cmd_create_args.log_file,
|
|
||||||
g_lcr_cmd_create_args.log_priority,
|
|
||||||
g_lcr_cmd_create_args.progname,
|
|
||||||
g_lcr_cmd_create_args.quiet,
|
|
||||||
LOGPATH)) {
|
|
||||||
free(oci_json_data);
|
|
||||||
oci_json_data = NULL;
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lcr_create(g_lcr_cmd_create_args.name,
|
|
||||||
g_lcr_cmd_create_args.lcrpath,
|
|
||||||
g_lcr_cmd_create_args.create_rootfs,
|
|
||||||
g_lcr_cmd_create_args.create_dist,
|
|
||||||
oci_json_data)) {
|
|
||||||
ERROR("Error creating container %s", g_lcr_cmd_create_args.name);
|
|
||||||
free(oci_json_data);
|
|
||||||
oci_json_data = NULL;
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
INFO("Container \"%s\" created\n", g_lcr_cmd_create_args.name);
|
|
||||||
free(oci_json_data);
|
|
||||||
oci_json_data = NULL;
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container create definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __CMD_CREATE_H
|
|
||||||
#define __CMD_CREATE_H
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "commander.h"
|
|
||||||
|
|
||||||
#define CREATE_OPTIONS(cmdargs) \
|
|
||||||
{CMD_OPT_TYPE_STRING, false, "dist", 0, &(cmdargs).create_dist, \
|
|
||||||
"Generate distribution specification, now support: `ubuntu`, `app`," \
|
|
||||||
" `none`\n\t\t\tthe default dist is `ubuntu`\n\t\t\tNOTE: if the dist is `none`," \
|
|
||||||
" it will not create default spec.", NULL}, \
|
|
||||||
{CMD_OPT_TYPE_STRING, false, "name", 'n', &(cmdargs).name, "Name of the container", NULL}, \
|
|
||||||
{CMD_OPT_TYPE_STRING, false, "ociconfig", 'c', &(cmdargs).ociconfig, \
|
|
||||||
"File containing oci configuration (in json format)", NULL}, \
|
|
||||||
{CMD_OPT_TYPE_STRING, false, "rootfs", 0, &(cmdargs).create_rootfs, \
|
|
||||||
"Specify the rootfs for the container, dir or block device", NULL}
|
|
||||||
|
|
||||||
extern const char g_lcr_cmd_create_desc[];
|
|
||||||
extern struct lcr_arguments g_lcr_cmd_create_args;
|
|
||||||
int cmd_create_main(int argc, const char **argv);
|
|
||||||
|
|
||||||
#endif /* __CMD_CREATE_H */
|
|
||||||
@ -1,72 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container delete functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "lcrcontainer.h"
|
|
||||||
#include "lcrcontainer_extend.h"
|
|
||||||
#include "delete.h"
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
const char g_lcr_cmd_delete_desc[] = "Delete a container";
|
|
||||||
static const char g_lcr_cmd_delete_usage[] = "delete --name=NAME";
|
|
||||||
|
|
||||||
struct lcr_arguments g_lcr_cmd_delete_args;
|
|
||||||
|
|
||||||
static int delete_cmd_init(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
command_t cmd;
|
|
||||||
struct command_option options[] = { DELETE_OPTIONS(g_lcr_cmd_delete_args), COMMON_OPTIONS(g_lcr_cmd_delete_args) };
|
|
||||||
|
|
||||||
lcr_arguments_init(&g_lcr_cmd_delete_args);
|
|
||||||
|
|
||||||
command_init(&cmd, options, sizeof(options) / sizeof(options[0]), argc, (const char **)argv, g_lcr_cmd_delete_desc,
|
|
||||||
g_lcr_cmd_delete_usage);
|
|
||||||
|
|
||||||
if (command_parse_args(&cmd, &g_lcr_cmd_delete_args.argc, &g_lcr_cmd_delete_args.argv)) {
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cmd_delete_main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
if (delete_cmd_init(argc, argv) != 0) {
|
|
||||||
exit(EINVALIDARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lcr_log_init(g_lcr_cmd_delete_args.name, g_lcr_cmd_delete_args.log_file, g_lcr_cmd_delete_args.log_priority,
|
|
||||||
g_lcr_cmd_delete_args.progname, g_lcr_cmd_delete_args.quiet, LOGPATH)) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_lcr_cmd_delete_args.name == NULL) {
|
|
||||||
fprintf(stderr, "missing --name,-n option\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lcr_delete_with_force(g_lcr_cmd_delete_args.name, g_lcr_cmd_delete_args.lcrpath,
|
|
||||||
g_lcr_cmd_delete_args.delete_force)) {
|
|
||||||
fprintf(stderr, "Error deleteing container %s\n", g_lcr_cmd_delete_args.name);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stdout, "Container \"%s\" deleted\n", g_lcr_cmd_delete_args.name);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container delete definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __CMD_DELETE_H
|
|
||||||
#define __CMD_DELETE_H
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "commander.h"
|
|
||||||
|
|
||||||
#define DELETE_OPTIONS(cmdargs) \
|
|
||||||
{ CMD_OPT_TYPE_BOOL, false, "force", 'f', &cmdargs.delete_force, \
|
|
||||||
"Forcibly deletes the container if it is still running", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "name", 'n', &cmdargs.name, "Name of the container", NULL }
|
|
||||||
|
|
||||||
extern const char g_lcr_cmd_delete_desc[];
|
|
||||||
extern struct lcr_arguments g_lcr_cmd_delete_args;
|
|
||||||
int cmd_delete_main(int argc, const char **argv);
|
|
||||||
|
|
||||||
#endif /* __CMD_DELETE_H */
|
|
||||||
@ -1,87 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container exec functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "lcrcontainer.h"
|
|
||||||
#include "exec.h"
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
const char g_lcr_cmd_exec_desc[] = "execute new process inside the container";
|
|
||||||
static const char g_lcr_cmd_exec_usage[] = "exec --name=NAME [-- COMMAND]";
|
|
||||||
|
|
||||||
struct lcr_arguments g_lcr_cmd_exec_args;
|
|
||||||
|
|
||||||
static inline int check_container_name()
|
|
||||||
{
|
|
||||||
if (g_lcr_cmd_exec_args.name == NULL) {
|
|
||||||
fprintf(stderr, "missing --name,-n option\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cmd_exec_main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
pid_t pid = 0;
|
|
||||||
int ret;
|
|
||||||
command_t cmd;
|
|
||||||
struct command_option options[] = {
|
|
||||||
EXEC_OPTIONS(g_lcr_cmd_exec_args),
|
|
||||||
COMMON_OPTIONS(g_lcr_cmd_exec_args)
|
|
||||||
};
|
|
||||||
|
|
||||||
lcr_arguments_init(&g_lcr_cmd_exec_args);
|
|
||||||
|
|
||||||
command_init(&cmd, options, sizeof(options) / sizeof(options[0]), argc, (const char **)argv,
|
|
||||||
g_lcr_cmd_exec_desc, g_lcr_cmd_exec_usage);
|
|
||||||
if (command_parse_args(&cmd, &g_lcr_cmd_exec_args.argc, &g_lcr_cmd_exec_args.argv)) {
|
|
||||||
exit(EINVALIDARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lcr_log_init(g_lcr_cmd_exec_args.name,
|
|
||||||
g_lcr_cmd_exec_args.log_file,
|
|
||||||
g_lcr_cmd_exec_args.log_priority,
|
|
||||||
g_lcr_cmd_exec_args.progname,
|
|
||||||
g_lcr_cmd_exec_args.quiet,
|
|
||||||
LOGPATH)) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (check_container_name() != 0) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lcr_exec(g_lcr_cmd_exec_args.name,
|
|
||||||
g_lcr_cmd_exec_args.lcrpath,
|
|
||||||
g_lcr_cmd_exec_args.argc,
|
|
||||||
g_lcr_cmd_exec_args.argv,
|
|
||||||
&pid)) {
|
|
||||||
fprintf(stderr, "Error execute new process inside container \"%s\"\n",
|
|
||||||
g_lcr_cmd_exec_args.name);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = wait_for_pid(pid) < 0;
|
|
||||||
if (ret < 0) {
|
|
||||||
fprintf(stderr, "exec success bug got bad return %d\n", ret);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container exec definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __CMD_EXEC_H
|
|
||||||
#define __CMD_EXEC_H
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "commander.h"
|
|
||||||
|
|
||||||
#define EXEC_OPTIONS(cmdargs) \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "name", 'n', &(cmdargs).name, "Name of the container", NULL }
|
|
||||||
|
|
||||||
extern const char g_lcr_cmd_exec_desc[];
|
|
||||||
extern struct lcr_arguments g_lcr_cmd_exec_args;
|
|
||||||
int cmd_exec_main(int argc, const char **argv);
|
|
||||||
|
|
||||||
#endif /* __CMD_EXEC_H */
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container help functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "help.h"
|
|
||||||
|
|
||||||
const char g_lcr_cmd_help_desc[] =
|
|
||||||
"show a list of commands or help for one command";
|
|
||||||
const char g_lcr_cmd_help_long_desc[] =
|
|
||||||
"NAME:\n"
|
|
||||||
"\tlcr help - show a list of commands or help for one command\n"
|
|
||||||
"\n"
|
|
||||||
"USAGE:\n"
|
|
||||||
"\tlcr help [command]\n";
|
|
||||||
|
|
||||||
/* cmd help main */
|
|
||||||
int cmd_help_main(int argc, char **argv, struct lcr_arguments *lcr_cmd_args)
|
|
||||||
{
|
|
||||||
printf("cmd_list\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container help definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __CMD_HELP_H
|
|
||||||
#define __CMD_HELP_H
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
|
|
||||||
extern const char g_lcr_cmd_help_desc[];
|
|
||||||
extern const char g_lcr_cmd_help_long_desc[];
|
|
||||||
|
|
||||||
int cmd_help_main(int argc, char **argv, struct lcr_arguments *lcr_cmd_args);
|
|
||||||
|
|
||||||
#endif /* __CMD_HELP_H */
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container kill functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include "lcrcontainer.h"
|
|
||||||
|
|
||||||
#include "securec.h"
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "kill.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
|
|
||||||
const char g_lcr_cmd_kill_desc[] = "Kill a container with the identifier NAME";
|
|
||||||
static const char g_lcr_cmd_kill_usage[] = "kill [command options] --name=NAME";
|
|
||||||
|
|
||||||
struct lcr_arguments g_lcr_cmd_kill_args;
|
|
||||||
|
|
||||||
static int parse_verify_signal(int *signo)
|
|
||||||
{
|
|
||||||
*signo = util_sig_parse(g_lcr_cmd_kill_args.signal);
|
|
||||||
if (*signo == -1) {
|
|
||||||
fprintf(stderr, "Invalid signal: %s", g_lcr_cmd_kill_args.signal);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!util_valid_signal(*signo)) {
|
|
||||||
fprintf(stderr, "The Linux daemon does not support signal %d", *signo);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int check_container_name()
|
|
||||||
{
|
|
||||||
if (g_lcr_cmd_kill_args.name == NULL) {
|
|
||||||
fprintf(stderr, "Missing container name, use -n,--name option");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int cmd_kill_main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
int signo;
|
|
||||||
command_t cmd;
|
|
||||||
struct command_option options[] = {
|
|
||||||
KILL_OPTIONS(g_lcr_cmd_kill_args),
|
|
||||||
COMMON_OPTIONS(g_lcr_cmd_kill_args)
|
|
||||||
};
|
|
||||||
|
|
||||||
lcr_arguments_init(&g_lcr_cmd_kill_args);
|
|
||||||
g_lcr_cmd_kill_args.signal = "SIGKILL";
|
|
||||||
command_init(&cmd, options, sizeof(options) / sizeof(options[0]), argc, (const char **)argv,
|
|
||||||
g_lcr_cmd_kill_desc, g_lcr_cmd_kill_usage);
|
|
||||||
if (command_parse_args(&cmd, &g_lcr_cmd_kill_args.argc, &g_lcr_cmd_kill_args.argv)) {
|
|
||||||
exit(EINVALIDARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lcr_log_init(g_lcr_cmd_kill_args.name, g_lcr_cmd_kill_args.log_file,
|
|
||||||
g_lcr_cmd_kill_args.log_priority,
|
|
||||||
g_lcr_cmd_kill_args.progname,
|
|
||||||
g_lcr_cmd_kill_args.quiet,
|
|
||||||
LOGPATH)) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (check_container_name() != 0) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parse_verify_signal(&signo) != 0) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lcr_kill(g_lcr_cmd_kill_args.name, g_lcr_cmd_kill_args.lcrpath, (uint32_t)signo)) {
|
|
||||||
fprintf(stderr, "Container \"%s\" kill failed", g_lcr_cmd_kill_args.name);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s\n", g_lcr_cmd_kill_args.name);
|
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container kill definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __CMD_KILL_H
|
|
||||||
#define __CMD_KILL_H
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "commander.h"
|
|
||||||
|
|
||||||
#define KILL_OPTIONS(cmdargs) \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "name", 'n', &(cmdargs).name, "Name of the container", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "signal", 's', &(cmdargs).signal, \
|
|
||||||
"Signal to send to the container (default \"SIGKILL\")", NULL }
|
|
||||||
|
|
||||||
extern const char g_lcr_cmd_kill_desc[];
|
|
||||||
extern struct lcr_arguments g_lcr_cmd_kill_args;
|
|
||||||
int cmd_kill_main(int argc, const char **argv);
|
|
||||||
|
|
||||||
#endif /* __CMD_KILL_H */
|
|
||||||
148
src/cmd/lcr.c
148
src/cmd/lcr.c
@ -1,148 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide lcr container functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "commands.h"
|
|
||||||
#include "create.h"
|
|
||||||
#include "delete.h"
|
|
||||||
#include "spec.h"
|
|
||||||
#include "list.h"
|
|
||||||
#include "start.h"
|
|
||||||
#include "clean.h"
|
|
||||||
#include "exec.h"
|
|
||||||
#include "state.h"
|
|
||||||
#include "pause.h"
|
|
||||||
#include "resume.h"
|
|
||||||
#include "update.h"
|
|
||||||
#include "help.h"
|
|
||||||
#include "kill.h"
|
|
||||||
|
|
||||||
|
|
||||||
// The list of our supported commands
|
|
||||||
struct command g_commands[] = {
|
|
||||||
{
|
|
||||||
// `create` sub-command
|
|
||||||
"create",
|
|
||||||
cmd_create_main,
|
|
||||||
g_lcr_cmd_create_desc,
|
|
||||||
NULL,
|
|
||||||
&g_lcr_cmd_create_args
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// `delete` sub-command
|
|
||||||
"delete",
|
|
||||||
cmd_delete_main,
|
|
||||||
g_lcr_cmd_delete_desc,
|
|
||||||
NULL,
|
|
||||||
&g_lcr_cmd_delete_args
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// `spec` sub-command
|
|
||||||
"spec",
|
|
||||||
cmd_spec_main,
|
|
||||||
g_lcr_cmd_spec_desc,
|
|
||||||
NULL,
|
|
||||||
&g_lcr_cmd_spec_args
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// `list` sub-command
|
|
||||||
"list",
|
|
||||||
cmd_list_main,
|
|
||||||
g_lcr_cmd_list_desc,
|
|
||||||
NULL,
|
|
||||||
&g_lcr_cmd_list_args
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// `start` sub-command
|
|
||||||
"start",
|
|
||||||
cmd_start_main,
|
|
||||||
g_lcr_cmd_start_desc,
|
|
||||||
NULL,
|
|
||||||
&g_lcr_cmd_start_args
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// `kill` sub-command
|
|
||||||
"kill",
|
|
||||||
cmd_kill_main,
|
|
||||||
g_lcr_cmd_kill_desc,
|
|
||||||
NULL,
|
|
||||||
&g_lcr_cmd_kill_args
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
// `clean` sub-command
|
|
||||||
"clean",
|
|
||||||
cmd_clean_main,
|
|
||||||
g_lcr_cmd_clean_desc,
|
|
||||||
NULL,
|
|
||||||
&g_lcr_cmd_clean_args
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// `exec` sub-command
|
|
||||||
"exec",
|
|
||||||
cmd_exec_main,
|
|
||||||
g_lcr_cmd_exec_desc,
|
|
||||||
NULL,
|
|
||||||
&g_lcr_cmd_exec_args
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// `state` sub-command
|
|
||||||
"state",
|
|
||||||
cmd_state_main,
|
|
||||||
g_lcr_cmd_state_desc,
|
|
||||||
NULL,
|
|
||||||
&g_lcr_cmd_state_args
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// `pause` sub-command
|
|
||||||
"pause",
|
|
||||||
cmd_pause_main,
|
|
||||||
g_lcr_cmd_pause_desc,
|
|
||||||
NULL,
|
|
||||||
&g_lcr_cmd_pause_args
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// `resume` sub-command
|
|
||||||
"resume",
|
|
||||||
cmd_resume_main,
|
|
||||||
g_lcr_cmd_resume_desc,
|
|
||||||
NULL,
|
|
||||||
&g_lcr_cmd_resume_args
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// `update` sub-command
|
|
||||||
"update",
|
|
||||||
cmd_update_main,
|
|
||||||
g_lcr_cmd_update_desc,
|
|
||||||
NULL,
|
|
||||||
&g_lcr_cmd_update_args
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// `help` sub-command
|
|
||||||
"help",
|
|
||||||
NULL,
|
|
||||||
g_lcr_cmd_help_desc,
|
|
||||||
g_lcr_cmd_help_long_desc,
|
|
||||||
NULL
|
|
||||||
},
|
|
||||||
{ NULL, NULL, NULL, NULL, NULL } // End of the list
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
return run_command(g_commands, argc, argv);
|
|
||||||
}
|
|
||||||
222
src/cmd/list.c
222
src/cmd/list.c
@ -1,222 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container list functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include "lcrcontainer.h"
|
|
||||||
#include "lcrcontainer_extend.h"
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "list.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
/* keep track of field widths for printing. */
|
|
||||||
struct lcr_lens {
|
|
||||||
unsigned int lcr_name_len;
|
|
||||||
unsigned int lcr_state_len;
|
|
||||||
unsigned int lcr_interface_len;
|
|
||||||
unsigned int lcr_ipv4_len;
|
|
||||||
unsigned int lcr_ipv6_len;
|
|
||||||
unsigned int lcr_init_len;
|
|
||||||
unsigned int lcr_ram_len;
|
|
||||||
unsigned int lcr_swap_len;
|
|
||||||
};
|
|
||||||
|
|
||||||
const char g_lcr_cmd_list_desc[] = "lists containers";
|
|
||||||
static const char g_lcr_cmd_list_usage[] = "list [command options]";
|
|
||||||
|
|
||||||
static void info_field_width(const struct lcr_container_info *info, const size_t size, struct lcr_lens *l);
|
|
||||||
static void info_print_table(const struct lcr_container_info *info, size_t size, const struct lcr_lens *length,
|
|
||||||
const struct lcr_arguments *args);
|
|
||||||
static void info_print_quiet(const struct lcr_container_info *info, size_t size, const struct lcr_arguments *args);
|
|
||||||
|
|
||||||
struct lcr_arguments g_lcr_cmd_list_args = { 0 };
|
|
||||||
|
|
||||||
int cmd_list_main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
command_t cmd;
|
|
||||||
struct command_option options[] = { LIST_OPTIONS(g_lcr_cmd_list_args), COMMON_OPTIONS(g_lcr_cmd_list_args) };
|
|
||||||
|
|
||||||
lcr_arguments_init(&g_lcr_cmd_list_args);
|
|
||||||
|
|
||||||
command_init(&cmd, options, sizeof(options) / sizeof(options[0]), argc, (const char **)argv, g_lcr_cmd_list_desc,
|
|
||||||
g_lcr_cmd_list_usage);
|
|
||||||
if (command_parse_args(&cmd, &g_lcr_cmd_list_args.argc, &g_lcr_cmd_list_args.argv)) {
|
|
||||||
exit(EINVALIDARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lcr_log_init(NULL, g_lcr_cmd_list_args.log_file, g_lcr_cmd_list_args.log_priority, g_lcr_cmd_list_args.progname,
|
|
||||||
g_lcr_cmd_list_args.quiet, LOGPATH)) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct lcr_lens max_len = {
|
|
||||||
.lcr_name_len = 4, /* NAME */
|
|
||||||
.lcr_state_len = 5, /* STATE */
|
|
||||||
.lcr_interface_len = 9, /* INTERFACE */
|
|
||||||
.lcr_ipv4_len = 4, /* IPV4 */
|
|
||||||
.lcr_ipv6_len = 4, /* IPV6 */
|
|
||||||
.lcr_init_len = 3, /* PID */
|
|
||||||
.lcr_ram_len = 3, /* RAM */
|
|
||||||
.lcr_swap_len = 4, /* SWAP */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct lcr_container_info *info_arr = NULL;
|
|
||||||
int num;
|
|
||||||
|
|
||||||
DEBUG("Get the container information");
|
|
||||||
if (g_lcr_cmd_list_args.list_active) {
|
|
||||||
num = lcr_list_active_containers(g_lcr_cmd_list_args.lcrpath, &info_arr);
|
|
||||||
} else {
|
|
||||||
num = lcr_list_all_containers(g_lcr_cmd_list_args.lcrpath, &info_arr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num == -1) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_lcr_cmd_list_args.list_quiet == true) {
|
|
||||||
info_print_quiet(info_arr, (size_t)num, &g_lcr_cmd_list_args);
|
|
||||||
} else {
|
|
||||||
info_field_width(info_arr, (size_t)num, &max_len);
|
|
||||||
info_print_table(info_arr, (size_t)num, &max_len, &g_lcr_cmd_list_args);
|
|
||||||
}
|
|
||||||
|
|
||||||
lcr_containers_info_free(&info_arr, (size_t)num);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool should_skip_print_info(const struct lcr_arguments *args, const struct lcr_container_info *in)
|
|
||||||
{
|
|
||||||
return (args->list_running == true && strncmp(in->state, "RUNNING", 7)) ||
|
|
||||||
(args->list_stopped == true && strncmp(in->state, "STOPPED", 7));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void info_print_quiet(const struct lcr_container_info *info, size_t size, const struct lcr_arguments *args)
|
|
||||||
{
|
|
||||||
if (size == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const struct lcr_container_info *in = NULL;
|
|
||||||
size_t i = 0;
|
|
||||||
for (i = 0, in = info; i < size; i++, in++) {
|
|
||||||
if (should_skip_print_info(args, in)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
printf("%s\n", in->name ? in->name : "-");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void info_print_table(const struct lcr_container_info *info, size_t size, const struct lcr_lens *length,
|
|
||||||
const struct lcr_arguments *args)
|
|
||||||
{
|
|
||||||
if (size == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
printf("%-*s ", (int)length->lcr_name_len, "NAME");
|
|
||||||
printf("%-*s ", (int)length->lcr_state_len, "STATE");
|
|
||||||
printf("%-*s ", (int)length->lcr_ipv4_len, "IPV4");
|
|
||||||
printf("%-*s ", (int)length->lcr_ipv6_len, "IPV6");
|
|
||||||
printf("\n");
|
|
||||||
const struct lcr_container_info *in = NULL;
|
|
||||||
size_t i = 0;
|
|
||||||
for (i = 0, in = info; i < size; i++, in++) {
|
|
||||||
if (should_skip_print_info(args, in)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
printf("%-*s ", (int)length->lcr_name_len, in->name ? in->name : "-");
|
|
||||||
printf("%-*s ", (int)length->lcr_state_len, in->state ? in->state : "-");
|
|
||||||
printf("%-*s ", (int)length->lcr_ipv4_len, in->ipv4 ? in->ipv4 : "-");
|
|
||||||
printf("%-*s ", (int)length->lcr_ipv6_len, in->ipv6 ? in->ipv6 : "-");
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void width_ip_and_memory(const struct lcr_container_info *in, struct lcr_lens *l)
|
|
||||||
{
|
|
||||||
size_t len = 0;
|
|
||||||
char buf[64];
|
|
||||||
|
|
||||||
if (in->ipv4) {
|
|
||||||
len = strlen(in->ipv4);
|
|
||||||
if (len > l->lcr_ipv4_len) {
|
|
||||||
l->lcr_ipv4_len = (unsigned int)len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (in->ipv6) {
|
|
||||||
len = strlen(in->ipv6);
|
|
||||||
if (len > l->lcr_ipv6_len) {
|
|
||||||
l->lcr_ipv6_len = (unsigned int)len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
len = (size_t)sprintf_s(buf, sizeof(buf), "%.2f", in->ram);
|
|
||||||
if (len > l->lcr_ram_len) {
|
|
||||||
l->lcr_ram_len = (unsigned int)len;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = (size_t)sprintf_s(buf, sizeof(buf), "%.2f", in->swap);
|
|
||||||
if (len > l->lcr_swap_len) {
|
|
||||||
l->lcr_swap_len = (unsigned int)len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_info_field_max_width(const struct lcr_container_info *in, struct lcr_lens *l)
|
|
||||||
{
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (in->name) {
|
|
||||||
len = strlen(in->name);
|
|
||||||
if (len > l->lcr_name_len) {
|
|
||||||
l->lcr_name_len = (unsigned int)len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (in->state) {
|
|
||||||
len = strlen(in->state);
|
|
||||||
if (len > l->lcr_state_len) {
|
|
||||||
l->lcr_state_len = (unsigned int)len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (in->interface) {
|
|
||||||
len = strlen(in->interface);
|
|
||||||
if (len > l->lcr_interface_len) {
|
|
||||||
l->lcr_interface_len = (unsigned int)len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in->init != -1) {
|
|
||||||
char buf[64];
|
|
||||||
int nret = sprintf_s(buf, sizeof(buf), "%d", in->init);
|
|
||||||
if (nret > 0 && (size_t)nret > l->lcr_init_len) {
|
|
||||||
l->lcr_init_len = (size_t)nret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
width_ip_and_memory(in, l);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void info_field_width(const struct lcr_container_info *info, const size_t size, struct lcr_lens *l)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
const struct lcr_container_info *in = NULL;
|
|
||||||
|
|
||||||
for (i = 0, in = info; i < size; i++, in++) {
|
|
||||||
set_info_field_max_width(in, l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container list definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __CMD_LIST_H
|
|
||||||
#define __CMD_LIST_H
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "commander.h"
|
|
||||||
|
|
||||||
#define LIST_OPTIONS(cmdargs) \
|
|
||||||
{ CMD_OPT_TYPE_BOOL, false, "quiet", 'q', &(cmdargs).list_quiet, "Display only container names", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_BOOL, false, "active", 0, &(cmdargs).list_active, "List only active containers", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_BOOL, false, "running", 0, &(cmdargs).list_running, "List only running containers", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_BOOL, false, "stopped", 0, &(cmdargs).list_stopped, "List only stopped containers", NULL }
|
|
||||||
|
|
||||||
extern const char g_lcr_cmd_list_desc[];
|
|
||||||
extern struct lcr_arguments g_lcr_cmd_list_args;
|
|
||||||
int cmd_list_main(int argc, const char **argv);
|
|
||||||
|
|
||||||
#endif /* __CMD_LIST_H */
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container pause functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "lcrcontainer.h"
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "pause.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
const char g_lcr_cmd_pause_desc[] = "Pause container in specified container NAME";
|
|
||||||
static const char g_lcr_cmd_pause_usage[] = "pause [command options] --name=NAME";
|
|
||||||
|
|
||||||
struct lcr_arguments g_lcr_cmd_pause_args;
|
|
||||||
|
|
||||||
int cmd_pause_main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
command_t cmd;
|
|
||||||
struct command_option options[] = {
|
|
||||||
PAUSE_OPTIONS(g_lcr_cmd_pause_args),
|
|
||||||
COMMON_OPTIONS(g_lcr_cmd_pause_args)
|
|
||||||
};
|
|
||||||
|
|
||||||
lcr_arguments_init(&g_lcr_cmd_pause_args);
|
|
||||||
|
|
||||||
command_init(&cmd, options, sizeof(options) / sizeof(options[0]),
|
|
||||||
argc,
|
|
||||||
(const char **)argv,
|
|
||||||
g_lcr_cmd_pause_desc, g_lcr_cmd_pause_usage);
|
|
||||||
if (command_parse_args(&cmd, &g_lcr_cmd_pause_args.argc, &g_lcr_cmd_pause_args.argv)) {
|
|
||||||
exit(EINVALIDARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lcr_log_init(g_lcr_cmd_pause_args.name, g_lcr_cmd_pause_args.log_file,
|
|
||||||
g_lcr_cmd_pause_args.log_priority,
|
|
||||||
g_lcr_cmd_pause_args.progname,
|
|
||||||
g_lcr_cmd_pause_args.quiet,
|
|
||||||
LOGPATH)) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_lcr_cmd_pause_args.name == NULL) {
|
|
||||||
fprintf(stderr, "missing container name, use -n,--name option\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lcr_pause(g_lcr_cmd_pause_args.name, g_lcr_cmd_pause_args.lcrpath)) {
|
|
||||||
fprintf(stderr, "Failed to pause container %s\n", g_lcr_cmd_pause_args.name);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stdout, "Container \"%s\" paused\n", g_lcr_cmd_pause_args.name);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container pause definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __CMD_PAUSE_H
|
|
||||||
#define __CMD_PAUSE_H
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "commander.h"
|
|
||||||
|
|
||||||
#define PAUSE_OPTIONS(cmdargs) \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "name", 'n', &(cmdargs).name, "Name of the container", NULL }
|
|
||||||
|
|
||||||
extern const char g_lcr_cmd_pause_desc[];
|
|
||||||
extern struct lcr_arguments g_lcr_cmd_pause_args;
|
|
||||||
int cmd_pause_main(int argc, const char **argv);
|
|
||||||
|
|
||||||
#endif /* __CMD_PAUSE_H */
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container resume functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "lcrcontainer.h"
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "resume.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
const char g_lcr_cmd_resume_desc[] = "Resume container in specified container NAME";
|
|
||||||
static const char g_lcr_cmd_resume_usage[] = "resume [command options] --name=NAME";
|
|
||||||
|
|
||||||
struct lcr_arguments g_lcr_cmd_resume_args;
|
|
||||||
|
|
||||||
int cmd_resume_main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
command_t cmd;
|
|
||||||
struct command_option options[] = { RESUME_OPTIONS(g_lcr_cmd_resume_args), COMMON_OPTIONS(g_lcr_cmd_resume_args) };
|
|
||||||
|
|
||||||
lcr_arguments_init(&g_lcr_cmd_resume_args);
|
|
||||||
|
|
||||||
command_init(&cmd, options, sizeof(options) / sizeof(options[0]), argc, (const char **)argv, g_lcr_cmd_resume_desc,
|
|
||||||
g_lcr_cmd_resume_usage);
|
|
||||||
if (command_parse_args(&cmd, &g_lcr_cmd_resume_args.argc, &g_lcr_cmd_resume_args.argv)) {
|
|
||||||
exit(EINVALIDARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lcr_log_init(g_lcr_cmd_resume_args.name, g_lcr_cmd_resume_args.log_file, g_lcr_cmd_resume_args.log_priority,
|
|
||||||
g_lcr_cmd_resume_args.progname, g_lcr_cmd_resume_args.quiet, LOGPATH)) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_lcr_cmd_resume_args.name == NULL) {
|
|
||||||
fprintf(stderr, "missing container name, use -n,--name option\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lcr_resume(g_lcr_cmd_resume_args.name, g_lcr_cmd_resume_args.lcrpath)) {
|
|
||||||
fprintf(stderr, "Failed to resume container %s\n", g_lcr_cmd_resume_args.name);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stdout, "Container \"%s\" resumed\n", g_lcr_cmd_resume_args.name);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container resume definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __CMD_RESUME_H
|
|
||||||
#define __CMD_RESUME_H
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "commander.h"
|
|
||||||
|
|
||||||
#define RESUME_OPTIONS(cmdargs) \
|
|
||||||
{CMD_OPT_TYPE_STRING, false, "name", 'n', &(cmdargs).name, "Name of the container", NULL}
|
|
||||||
|
|
||||||
extern const char g_lcr_cmd_resume_desc[];
|
|
||||||
extern struct lcr_arguments g_lcr_cmd_resume_args;
|
|
||||||
int cmd_resume_main(int argc, const char **argv);
|
|
||||||
|
|
||||||
#endif /* __CMD_RESUME_H */
|
|
||||||
209
src/cmd/spec.c
209
src/cmd/spec.c
@ -1,209 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container spec functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "lcrcontainer.h"
|
|
||||||
#include "lcrcontainer_extend.h"
|
|
||||||
#include "oci_runtime_spec.h"
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "spec.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
const char g_lcr_cmd_spec_desc[] =
|
|
||||||
"Create a new specification file.";
|
|
||||||
static const char g_lcr_cmd_spec_usage[] = "spec [command options]";
|
|
||||||
|
|
||||||
struct lcr_arguments g_lcr_cmd_spec_args;
|
|
||||||
|
|
||||||
static void determine_distribution(const struct lcr_arguments *spec_args,
|
|
||||||
struct lcr_list **lcr_conf, char **seccomp_conf)
|
|
||||||
{
|
|
||||||
char *distribution = NULL;
|
|
||||||
|
|
||||||
if (spec_args->spec_dist != NULL) {
|
|
||||||
distribution = util_strdup_s(spec_args->spec_dist);
|
|
||||||
} else {
|
|
||||||
distribution = util_strdup_s("app");
|
|
||||||
}
|
|
||||||
*lcr_conf = lcr_dist2spec(distribution, seccomp_conf);
|
|
||||||
|
|
||||||
free(distribution);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int check_lcr_config(const struct lcr_arguments *spec_args, const struct lcr_list *lcr_conf)
|
|
||||||
{
|
|
||||||
if (lcr_conf == NULL) {
|
|
||||||
if (spec_args->spec_dist != NULL) {
|
|
||||||
ERROR("Create distribution specific configuration failed");
|
|
||||||
} else {
|
|
||||||
ERROR("Translate oci specification to lcr configuration failed");
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_lcr_conf(const struct lcr_arguments *spec_args,
|
|
||||||
struct lcr_list **lcr_conf, char **seccomp_conf)
|
|
||||||
{
|
|
||||||
int ret = -1;
|
|
||||||
oci_runtime_spec *container = NULL;
|
|
||||||
|
|
||||||
if (spec_args->spec_translate == NULL) {
|
|
||||||
determine_distribution(spec_args, lcr_conf, seccomp_conf);
|
|
||||||
} else {
|
|
||||||
if (!container_parse(spec_args->spec_translate, NULL, &container)) {
|
|
||||||
ERROR("Failed to parse container!");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
*lcr_conf = lcr_oci2lcr(NULL, NULL, container, seccomp_conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (check_lcr_config(spec_args, *lcr_conf) != 0) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
out:
|
|
||||||
free_oci_runtime_spec(container);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_lcr_fake_path_name(const char *bundle, char **fake_path,
|
|
||||||
char **fake_name)
|
|
||||||
{
|
|
||||||
int ret = -1;
|
|
||||||
size_t len = 0;
|
|
||||||
size_t slash_index = 0;
|
|
||||||
|
|
||||||
len = strlen(bundle);
|
|
||||||
for (slash_index = len - 1; slash_index > 0;
|
|
||||||
slash_index--) {
|
|
||||||
if (bundle[slash_index] == '/') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*fake_path = util_common_calloc_s(slash_index + 1);
|
|
||||||
if (*fake_path == NULL) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strncpy_s(*fake_path, slash_index + 1, bundle, slash_index) != EOK) {
|
|
||||||
ERROR("Failed to copy string!");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
(*fake_path)[slash_index] = '\0';
|
|
||||||
|
|
||||||
*fake_name = util_common_calloc_s((len - slash_index) + 1);
|
|
||||||
if (*fake_name == NULL) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strncpy_s(*fake_name, (len - slash_index) + 1, &(bundle[slash_index + 1]),
|
|
||||||
len - slash_index) != EOK) {
|
|
||||||
ERROR("Failed to copy string!");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
(*fake_name)[(len - slash_index) - 1] = '\0';
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int check_spec_dist_and_translate()
|
|
||||||
{
|
|
||||||
if ((g_lcr_cmd_spec_args.spec_dist != NULL) && (g_lcr_cmd_spec_args.spec_translate != NULL)) {
|
|
||||||
ERROR("-t can't be used with --dist");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_spec_bundle(char *bundle, size_t len)
|
|
||||||
{
|
|
||||||
if (g_lcr_cmd_spec_args.spec_bundle == NULL) {
|
|
||||||
if (getcwd(bundle, len) == NULL) {
|
|
||||||
ERROR("getcwd failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else if (strlen(g_lcr_cmd_spec_args.spec_bundle) >= PATH_MAX ||
|
|
||||||
realpath(g_lcr_cmd_spec_args.spec_bundle, bundle) == NULL) {
|
|
||||||
ERROR("failed to get absolute path '%s'\n", g_lcr_cmd_spec_args.spec_bundle);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cmd_spec_main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
int ret = -1;
|
|
||||||
char *fakepath = NULL;
|
|
||||||
char *fakename = NULL;
|
|
||||||
char *seccomp = NULL;
|
|
||||||
char bundle[PATH_MAX] = { 0 };
|
|
||||||
struct lcr_list *lcr_conf = NULL;
|
|
||||||
command_t cmd;
|
|
||||||
struct command_option options[] = {
|
|
||||||
SPEC_OPTIONS(g_lcr_cmd_spec_args),
|
|
||||||
COMMON_OPTIONS(g_lcr_cmd_spec_args)
|
|
||||||
};
|
|
||||||
|
|
||||||
lcr_arguments_init(&g_lcr_cmd_spec_args);
|
|
||||||
|
|
||||||
command_init(&cmd, options, sizeof(options) / sizeof(options[0]), argc,
|
|
||||||
(const char **)argv, g_lcr_cmd_spec_desc, g_lcr_cmd_spec_usage);
|
|
||||||
if (command_parse_args(&cmd, &g_lcr_cmd_spec_args.argc, &g_lcr_cmd_spec_args.argv)) {
|
|
||||||
exit(EINVALIDARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lcr_log_init(NULL, g_lcr_cmd_spec_args.log_file, g_lcr_cmd_spec_args.log_priority,
|
|
||||||
g_lcr_cmd_spec_args.progname, g_lcr_cmd_spec_args.quiet, LOGPATH)) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (check_spec_dist_and_translate() != 0) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_spec_bundle(bundle, PATH_MAX) != 0) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_lcr_fake_path_name(bundle, &fakepath, &fakename) ||
|
|
||||||
get_lcr_conf(&g_lcr_cmd_spec_args, &lcr_conf, &seccomp)) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lcr_save_spec(fakename, fakepath, lcr_conf, seccomp)) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
ret = 0;
|
|
||||||
out:
|
|
||||||
lcr_free_config(lcr_conf);
|
|
||||||
free(lcr_conf);
|
|
||||||
free(seccomp);
|
|
||||||
free(fakepath);
|
|
||||||
free(fakename);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container spec definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __CMD_SPEC_H
|
|
||||||
#define __CMD_SPEC_H
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "commander.h"
|
|
||||||
|
|
||||||
#define SPEC_OPTIONS(cmdargs) \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "bundle", 'b', &(cmdargs).spec_bundle, \
|
|
||||||
"Path to the root of the bundle directory, default is current directory", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "translate", 't', &(cmdargs).spec_translate, \
|
|
||||||
"Translate oci specification (in json format) to lcr configuration", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "dist", 0, &(cmdargs).spec_dist, \
|
|
||||||
"Generate distribution specification, now support: ubuntu", NULL }
|
|
||||||
|
|
||||||
extern const char g_lcr_cmd_spec_desc[];
|
|
||||||
extern struct lcr_arguments g_lcr_cmd_spec_args;
|
|
||||||
int cmd_spec_main(int argc, const char **argv);
|
|
||||||
|
|
||||||
#endif /* __CMD_SPEC_H */
|
|
||||||
111
src/cmd/start.c
111
src/cmd/start.c
@ -1,111 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container start functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "lcrcontainer.h"
|
|
||||||
#include "start.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
const char g_lcr_cmd_start_desc[] = "start container";
|
|
||||||
static const char g_lcr_cmd_start_usage[] = "start [command options] --name=NAME";
|
|
||||||
|
|
||||||
struct lcr_arguments g_lcr_cmd_start_args;
|
|
||||||
int callback_foreground(command_option_t *option, const char *arg)
|
|
||||||
{
|
|
||||||
struct lcr_arguments *args = (struct lcr_arguments *)option->data;
|
|
||||||
if (arg == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!strcmp(arg, "true")) {
|
|
||||||
args->start_daemonize = false;
|
|
||||||
} else if (!strcmp(arg, "false")) {
|
|
||||||
args->start_daemonize = true;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int cmd_start_main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
command_t cmd;
|
|
||||||
struct command_option options[] = {
|
|
||||||
START_OPTIONS(g_lcr_cmd_start_args),
|
|
||||||
COMMON_OPTIONS(g_lcr_cmd_start_args)
|
|
||||||
};
|
|
||||||
struct lcr_start_request request = {0};
|
|
||||||
|
|
||||||
lcr_arguments_init(&g_lcr_cmd_start_args);
|
|
||||||
|
|
||||||
command_init(&cmd, options, sizeof(options) / sizeof(options[0]), argc, (const char **)argv,
|
|
||||||
g_lcr_cmd_start_desc, g_lcr_cmd_start_usage);
|
|
||||||
|
|
||||||
if (command_parse_args(&cmd, &g_lcr_cmd_start_args.argc, &g_lcr_cmd_start_args.argv) ||
|
|
||||||
start_checker(&g_lcr_cmd_start_args)) {
|
|
||||||
exit(EINVALIDARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lcr_log_init(g_lcr_cmd_start_args.name, g_lcr_cmd_start_args.log_file,
|
|
||||||
g_lcr_cmd_start_args.log_priority,
|
|
||||||
g_lcr_cmd_start_args.name,
|
|
||||||
g_lcr_cmd_start_args.quiet,
|
|
||||||
LOGPATH)) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_lcr_cmd_start_args.name == NULL) {
|
|
||||||
fprintf(stderr, "missing container name, use -n,--name option\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
request.name = g_lcr_cmd_start_args.name;
|
|
||||||
request.lcrpath = g_lcr_cmd_start_args.lcrpath;
|
|
||||||
request.logpath = g_lcr_cmd_start_args.log_file;
|
|
||||||
request.loglevel = g_lcr_cmd_start_args.log_priority;
|
|
||||||
request.daemonize = g_lcr_cmd_start_args.start_daemonize;
|
|
||||||
request.tty = true;
|
|
||||||
request.open_stdin = true;
|
|
||||||
request.pidfile = g_lcr_cmd_start_args.start_pidfile;
|
|
||||||
request.console_fifos = g_lcr_cmd_start_args.console_fifos;
|
|
||||||
request.console_logpath = g_lcr_cmd_start_args.console_logpath;
|
|
||||||
|
|
||||||
if (!lcr_start(&request)) {
|
|
||||||
ERROR("Failed to start container %s", g_lcr_cmd_start_args.name);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_lcr_cmd_start_args.start_daemonize) {
|
|
||||||
fprintf(stdout, "Container \"%s\" started\n", g_lcr_cmd_start_args.name);
|
|
||||||
}
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool check_start_arguments(const struct lcr_arguments *args)
|
|
||||||
{
|
|
||||||
return (args->console_fifos[0] && !args->console_fifos[1]) ||
|
|
||||||
(!args->console_fifos[0] && args->console_fifos[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
int start_checker(const struct lcr_arguments *args)
|
|
||||||
{
|
|
||||||
if (check_start_arguments(args)) {
|
|
||||||
fprintf(stderr, "Should specify the input and output FIFOs at the same time\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container start definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __CMD_START_H
|
|
||||||
#define __CMD_START_H
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "commander.h"
|
|
||||||
|
|
||||||
#define START_OPTIONS(cmdargs) \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "name", 'n', &(cmdargs).name, "Name of the container", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_BOOL, false, "daemon", 'd', &(cmdargs).start_daemonize, \
|
|
||||||
"Daemonize the container (default)", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_CALLBACK, false, "foreground", 'F', &(cmdargs).start_daemonize, \
|
|
||||||
"Start with the current tty attached to /dev/console", callback_foreground }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "pidfile", 0, &(cmdargs).start_pidfile, "Create a file with the process id", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "console_file", 'L', &(cmdargs).console_logpath, \
|
|
||||||
"Save the console output to the file", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "in-fifo", 0, &(cmdargs).console_fifos[0], "console fifo", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "out-fifo", 0, &(cmdargs).console_fifos[1], "console fifo", NULL }
|
|
||||||
|
|
||||||
extern const char g_lcr_cmd_start_desc[];
|
|
||||||
extern struct lcr_arguments g_lcr_cmd_start_args;
|
|
||||||
int callback_foreground(command_option_t *option, const char *arg);
|
|
||||||
int start_checker(const struct lcr_arguments *args);
|
|
||||||
int cmd_start_main(int argc, const char **argv);
|
|
||||||
|
|
||||||
#endif /* __CMD_START_H */
|
|
||||||
194
src/cmd/state.c
194
src/cmd/state.c
@ -1,194 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container state functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <securec.h>
|
|
||||||
|
|
||||||
#include "lcrcontainer.h"
|
|
||||||
#include "state.h"
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
const char g_lcr_cmd_state_desc[] = "Output the state of a container";
|
|
||||||
static const char g_lcr_cmd_state_usage[] = "state --name=NAME";
|
|
||||||
|
|
||||||
struct lcr_arguments g_lcr_cmd_state_args;
|
|
||||||
|
|
||||||
static uint64_t read_memory_info(void)
|
|
||||||
{
|
|
||||||
uint64_t sysmem_limit = 0;
|
|
||||||
size_t len = 0;
|
|
||||||
char *line = NULL;
|
|
||||||
char *p = NULL;
|
|
||||||
|
|
||||||
FILE *fp = util_fopen("/proc/meminfo", "r");
|
|
||||||
if (fp == NULL) {
|
|
||||||
ERROR("Failed to open /proc/meminfo");
|
|
||||||
return sysmem_limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (getline(&line, &len, fp) != -1) {
|
|
||||||
p = strchr(line, ' ');
|
|
||||||
if (p == NULL) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
*p = '\0';
|
|
||||||
p++;
|
|
||||||
if (strcmp(line, "MemTotal:") == 0) {
|
|
||||||
while (*p != '\0' && (*p == ' ' || *p == '\t')) {
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
if (*p == '\0') {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
sysmem_limit = strtoull(p, NULL, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
fclose(fp);
|
|
||||||
free(line);
|
|
||||||
return sysmem_limit * SIZE_KB;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void size_humanize(unsigned long long val, char *buf, size_t bufsz)
|
|
||||||
{
|
|
||||||
errno_t ret;
|
|
||||||
|
|
||||||
if (val > 1 << 30) {
|
|
||||||
ret = sprintf_s(buf, bufsz, "%u.%2.2u GiB",
|
|
||||||
(unsigned int)(val >> 30),
|
|
||||||
(unsigned int)((val & ((1 << 30) - 1)) * 100) >> 30);
|
|
||||||
} else if (val > 1 << 20) {
|
|
||||||
unsigned long long x = val + 5243; /* for rounding */
|
|
||||||
ret = sprintf_s(buf, bufsz, "%u.%2.2u MiB",
|
|
||||||
(unsigned int)(x >> 20), (unsigned int)(((x & ((1 << 20) - 1)) * 100) >> 20));
|
|
||||||
} else if (val > 1 << 10) {
|
|
||||||
unsigned long long x = val + 5; /* for rounding */
|
|
||||||
ret = sprintf_s(buf, bufsz, "%u.%2.2u KiB",
|
|
||||||
(unsigned int)(x >> 10), (unsigned int)(((x & ((1 << 10) - 1)) * 100) >> 10));
|
|
||||||
} else {
|
|
||||||
ret = sprintf_s(buf, bufsz, "%u bytes", (unsigned int)val);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret < 0) {
|
|
||||||
ERROR("Failed to sprintf string");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_state(const struct lcr_container_state *lcs)
|
|
||||||
{
|
|
||||||
char buf[BUFSIZE];
|
|
||||||
|
|
||||||
fprintf(stdout, "%-15s %s\n", "Name:", lcs->name);
|
|
||||||
fprintf(stdout, "%-15s %s\n", "State:", lcs->state);
|
|
||||||
if (strcmp(lcs->state, "RUNNING") != 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stdout, "%-15s %d\n", "PID:", lcs->init);
|
|
||||||
fprintf(stdout, "%-15s %.2f seconds\n", "CPU use:",
|
|
||||||
(double)lcs->cpu_use_nanos / 1000000000.0);
|
|
||||||
|
|
||||||
fprintf(stdout, "%-15s %llu\n", "Pids current:",
|
|
||||||
(unsigned long long)lcs->pids_current);
|
|
||||||
|
|
||||||
size_humanize(lcs->mem_used, buf, sizeof(buf));
|
|
||||||
fprintf(stdout, "%-15s %s\n", "Memory use:", buf);
|
|
||||||
|
|
||||||
size_humanize(lcs->mem_limit, buf, sizeof(buf));
|
|
||||||
fprintf(stdout, "%-15s %s\n", "Memory limit:", buf);
|
|
||||||
|
|
||||||
size_humanize(lcs->kmem_used, buf, sizeof(buf));
|
|
||||||
fprintf(stdout, "%-15s %s\n", "KMem use:", buf);
|
|
||||||
|
|
||||||
size_humanize(lcs->kmem_limit, buf, sizeof(buf));
|
|
||||||
fprintf(stdout, "%-15s %s\n", "KMem limit:", buf);
|
|
||||||
|
|
||||||
size_humanize(lcs->io_service_bytes.read, buf, sizeof(buf));
|
|
||||||
fprintf(stdout, "%-15s %s\n", "Blkio read:", buf);
|
|
||||||
|
|
||||||
size_humanize(lcs->io_service_bytes.write, buf, sizeof(buf));
|
|
||||||
fprintf(stdout, "%-15s %s\n", "Blkio write:", buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int check_container_name()
|
|
||||||
{
|
|
||||||
if (g_lcr_cmd_state_args.name == NULL) {
|
|
||||||
fprintf(stderr, "missing --name,-n option\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_sysmem_limit(struct lcr_container_state *state)
|
|
||||||
{
|
|
||||||
uint64_t sysmem_limit = 0;
|
|
||||||
|
|
||||||
sysmem_limit = read_memory_info();
|
|
||||||
if (sysmem_limit > 0 && state->mem_limit > sysmem_limit) {
|
|
||||||
state->mem_limit = sysmem_limit;
|
|
||||||
}
|
|
||||||
if (sysmem_limit > 0 && state->kmem_limit > sysmem_limit) {
|
|
||||||
state->kmem_limit = sysmem_limit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int cmd_state_main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
struct lcr_container_state state = { 0 };
|
|
||||||
command_t cmd;
|
|
||||||
struct command_option options[] = {
|
|
||||||
STATE_OPTIONS(g_lcr_cmd_state_args),
|
|
||||||
COMMON_OPTIONS(g_lcr_cmd_state_args)
|
|
||||||
};
|
|
||||||
|
|
||||||
lcr_arguments_init(&g_lcr_cmd_state_args);
|
|
||||||
|
|
||||||
command_init(&cmd, options, sizeof(options) / sizeof(options[0]), argc, (const char **)argv,
|
|
||||||
g_lcr_cmd_state_desc, g_lcr_cmd_state_usage);
|
|
||||||
if (command_parse_args(&cmd, &g_lcr_cmd_state_args.argc, &g_lcr_cmd_state_args.argv)) {
|
|
||||||
exit(EINVALIDARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lcr_log_init(g_lcr_cmd_state_args.name,
|
|
||||||
g_lcr_cmd_state_args.log_file,
|
|
||||||
g_lcr_cmd_state_args.log_priority,
|
|
||||||
g_lcr_cmd_state_args.progname,
|
|
||||||
g_lcr_cmd_state_args.quiet,
|
|
||||||
LOGPATH)) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (check_container_name() != 0) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lcr_state(g_lcr_cmd_state_args.name, g_lcr_cmd_state_args.lcrpath, &state)) {
|
|
||||||
fprintf(stderr, "Error get the container \"%s\"'s state\n", g_lcr_cmd_state_args.name);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
set_sysmem_limit(&state);
|
|
||||||
|
|
||||||
print_state(&state);
|
|
||||||
lcr_container_state_free(&state);
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container state definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __CMD_STATE_H
|
|
||||||
#define __CMD_STATE_H
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "commander.h"
|
|
||||||
|
|
||||||
#define STATE_OPTIONS(cmdargs) \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "name", 'n', &(cmdargs).name, "Name of the container", NULL }
|
|
||||||
|
|
||||||
extern const char g_lcr_cmd_state_desc[];
|
|
||||||
extern struct lcr_arguments g_lcr_cmd_state_args;
|
|
||||||
int cmd_state_main(int argc, const char **argv);
|
|
||||||
|
|
||||||
#endif /* __CMD_STATE_H */
|
|
||||||
122
src/cmd/update.c
122
src/cmd/update.c
@ -1,122 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container update functions
|
|
||||||
******************************************************************************/
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <securec.h>
|
|
||||||
|
|
||||||
#include "lcrcontainer.h"
|
|
||||||
#include "update.h"
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
#define BLKIOWEIGHT 1
|
|
||||||
#define CPUSHARES 2
|
|
||||||
#define CPUPERIOD 3
|
|
||||||
#define CPUQUOTA 4
|
|
||||||
#define CPUSETCPUS 5
|
|
||||||
#define CPUSETMEMS 6
|
|
||||||
#define KERNELMEMORY 7
|
|
||||||
#define MEMORYRESERV 8
|
|
||||||
#define MEMORYSWAP 9
|
|
||||||
|
|
||||||
const char g_lcr_cmd_update_desc[] = "Update configuration of a container";
|
|
||||||
static const char g_lcr_cmd_update_usage[] = "update --name=NAME";
|
|
||||||
|
|
||||||
struct lcr_arguments g_lcr_cmd_update_args;
|
|
||||||
|
|
||||||
static void to_cgroup_cpu_resources(const struct lcr_arguments *args, struct lcr_cgroup_resources *cr)
|
|
||||||
{
|
|
||||||
if (args->cr.blkio_weight) {
|
|
||||||
cr->blkio_weight = strtoull(args->cr.blkio_weight, NULL, 10);
|
|
||||||
}
|
|
||||||
if (args->cr.cpu_shares) {
|
|
||||||
cr->cpu_shares = strtoull(args->cr.cpu_shares, NULL, 10);
|
|
||||||
}
|
|
||||||
if (args->cr.cpu_period) {
|
|
||||||
cr->cpu_period = strtoull(args->cr.cpu_period, NULL, 10);
|
|
||||||
}
|
|
||||||
if (args->cr.cpu_quota) {
|
|
||||||
cr->cpu_quota = strtoull(args->cr.cpu_quota, NULL, 10);
|
|
||||||
}
|
|
||||||
if (args->cr.cpuset_cpus) {
|
|
||||||
cr->cpuset_cpus = args->cr.cpuset_cpus;
|
|
||||||
}
|
|
||||||
if (args->cr.cpuset_mems) {
|
|
||||||
cr->cpuset_mems = args->cr.cpuset_mems;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void to_cgroup_mem_resources(const struct lcr_arguments *args, struct lcr_cgroup_resources *cr)
|
|
||||||
{
|
|
||||||
if (args->cr.kernel_memory_limit) {
|
|
||||||
cr->kernel_memory_limit = strtoull(args->cr.kernel_memory_limit, NULL, 10);
|
|
||||||
}
|
|
||||||
if (args->cr.memory_reservation) {
|
|
||||||
cr->memory_reservation = strtoull(args->cr.memory_reservation, NULL, 10);
|
|
||||||
}
|
|
||||||
if (args->cr.memory_limit) {
|
|
||||||
cr->memory_limit = strtoull(args->cr.memory_limit, NULL, 10);
|
|
||||||
}
|
|
||||||
if (args->cr.memory_swap) {
|
|
||||||
cr->memory_swap = strtoull(args->cr.memory_swap, NULL, 10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void to_cgroup_resources(const struct lcr_arguments *args, struct lcr_cgroup_resources *cr)
|
|
||||||
{
|
|
||||||
if (args == NULL || cr == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
to_cgroup_cpu_resources(args, cr);
|
|
||||||
|
|
||||||
to_cgroup_mem_resources(args, cr);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cmd_update_main(int argc, const char **argv)
|
|
||||||
{
|
|
||||||
command_t cmd;
|
|
||||||
struct lcr_cgroup_resources cr = { 0 };
|
|
||||||
struct command_option options[] = { UPDATE_OPTIONS(g_lcr_cmd_update_args), COMMON_OPTIONS(g_lcr_cmd_update_args) };
|
|
||||||
|
|
||||||
lcr_arguments_init(&g_lcr_cmd_update_args);
|
|
||||||
|
|
||||||
command_init(&cmd, options, sizeof(options) / sizeof(options[0]), argc, (const char **)argv, g_lcr_cmd_update_desc,
|
|
||||||
g_lcr_cmd_update_usage);
|
|
||||||
|
|
||||||
if (command_parse_args(&cmd, &g_lcr_cmd_update_args.argc, &g_lcr_cmd_update_args.argv)) {
|
|
||||||
exit(EINVALIDARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lcr_log_init(g_lcr_cmd_update_args.name, g_lcr_cmd_update_args.log_file, g_lcr_cmd_update_args.log_priority,
|
|
||||||
g_lcr_cmd_update_args.progname, g_lcr_cmd_update_args.quiet, LOGPATH)) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_lcr_cmd_update_args.name == NULL) {
|
|
||||||
fprintf(stderr, "missing --name,-n option\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
to_cgroup_resources(&g_lcr_cmd_update_args, &cr);
|
|
||||||
if (!lcr_update(g_lcr_cmd_update_args.name, g_lcr_cmd_update_args.lcrpath, &cr)) {
|
|
||||||
fprintf(stderr, "Error update container %s\n", g_lcr_cmd_update_args.name);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
|
||||||
* lcr licensed under the Mulan PSL v1.
|
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
|
||||||
* http://license.coscl.org.cn/MulanPSL
|
|
||||||
* 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 v1 for more details.
|
|
||||||
* Author: wujing
|
|
||||||
* Create: 2018-11-08
|
|
||||||
* Description: provide container update definition
|
|
||||||
******************************************************************************/
|
|
||||||
#ifndef __CMD_UPDATE_H
|
|
||||||
#define __CMD_UPDATE_H
|
|
||||||
|
|
||||||
#include "arguments.h"
|
|
||||||
#include "commander.h"
|
|
||||||
|
|
||||||
#define UPDATE_OPTIONS(cmdargs) \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "name", 'n', &(cmdargs).name, "Name of the container", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "blkio-weight", 0, &(cmdargs).cr.blkio_weight, \
|
|
||||||
"Block IO (relative weight), between 10 and 1000", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "cpu-shares", 0, &(cmdargs).cr.cpu_shares, "CPU shares (relative weight)", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "cpu-period", 0, &(cmdargs).cr.cpu_period, \
|
|
||||||
"Limit CPU CFS (Completely Fair Scheduler) period", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "cpu-quota", 0, &(cmdargs).cr.cpu_quota, \
|
|
||||||
"Limit CPU CFS (Completely Fair Scheduler) quota", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "cpuset-cpus", 0, &(cmdargs).cr.cpuset_cpus, \
|
|
||||||
"CPUs in which to allow execution (0-3, 0,1)", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "cpuset-mems", 0, &(cmdargs).cr.cpuset_mems, \
|
|
||||||
"MEMs in which to allow execution (0-3, 0,1)", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "kernel-memory", 0, &(cmdargs).cr.kernel_memory_limit, \
|
|
||||||
"Kernel memory limit", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "memory", 'm', &(cmdargs).cr.memory_limit, "Memory limit", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "memory-reservation", 0, &(cmdargs).cr.memory_reservation, \
|
|
||||||
"Memory soft limit", NULL }, \
|
|
||||||
{ CMD_OPT_TYPE_STRING, false, "memory-swap", 0, &(cmdargs).cr.memory_swap, \
|
|
||||||
"Swap limit equal to memory plus swap: '-1' to enable unlimited swap", NULL }
|
|
||||||
|
|
||||||
extern const char g_lcr_cmd_update_desc[];
|
|
||||||
extern struct lcr_arguments g_lcr_cmd_update_args;
|
|
||||||
int cmd_update_main(int argc, const char **argv);
|
|
||||||
|
|
||||||
#endif /* __CMD_UPDATE_H */
|
|
||||||
@ -28,6 +28,8 @@
|
|||||||
|
|
||||||
#define CONFIG_FILE_MODE 0640
|
#define CONFIG_FILE_MODE 0640
|
||||||
|
|
||||||
|
#define NETWORK_MOUNT_FILE_MODE 0644
|
||||||
|
|
||||||
#define ARCH_LOG_FILE_MODE 0440
|
#define ARCH_LOG_FILE_MODE 0440
|
||||||
|
|
||||||
#define WORKING_LOG_FILE_MODE 0640
|
#define WORKING_LOG_FILE_MODE 0640
|
||||||
|
|||||||
@ -74,7 +74,7 @@ class MyRoot(object):
|
|||||||
return self.root_path
|
return self.root_path
|
||||||
|
|
||||||
|
|
||||||
def trimJsonSuffix(name):
|
def trim_json_suffix(name):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -82,10 +82,10 @@ def trimJsonSuffix(name):
|
|||||||
"""
|
"""
|
||||||
if name.endswith(JSON_SUFFIX) or name.endswith(REF_SUFFIX):
|
if name.endswith(JSON_SUFFIX) or name.endswith(REF_SUFFIX):
|
||||||
name = name[:-len(JSON_SUFFIX)]
|
name = name[:-len(JSON_SUFFIX)]
|
||||||
return helpers.convertToCStyle(name.replace('.', '_').replace('-', '_'))
|
return helpers.conv_to_c_style(name.replace('.', '_').replace('-', '_'))
|
||||||
|
|
||||||
|
|
||||||
def getPrefixPackage(filepath, rootpath):
|
def get_prefix_package(filepath, rootpath):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -94,49 +94,52 @@ def getPrefixPackage(filepath, rootpath):
|
|||||||
realpath = os.path.realpath(filepath)
|
realpath = os.path.realpath(filepath)
|
||||||
|
|
||||||
if realpath.startswith(rootpath) and len(realpath) > len(rootpath):
|
if realpath.startswith(rootpath) and len(realpath) > len(rootpath):
|
||||||
return helpers.convertToCStyle(os.path.dirname(realpath)[(len(rootpath) + 1):])
|
return helpers.conv_to_c_style(os.path.dirname(realpath)[(len(rootpath) + 1):])
|
||||||
else:
|
else:
|
||||||
raise RuntimeError('schema path \"%s\" is not in scope of root path \"%s\"' \
|
raise RuntimeError('schema path \"%s\" is not in scope of root path \"%s\"' \
|
||||||
% (realpath, rootpath))
|
% (realpath, rootpath))
|
||||||
|
|
||||||
|
|
||||||
def getPrefixFromFile(filepath):
|
def get_prefix_from_file(filepath):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
prefix_file = trimJsonSuffix(os.path.basename(filepath))
|
prefix_file = trim_json_suffix(os.path.basename(filepath))
|
||||||
root_path = MyRoot.root_path
|
root_path = MyRoot.root_path
|
||||||
prefix_package = getPrefixPackage(filepath, root_path)
|
prefix_package = get_prefix_package(filepath, root_path)
|
||||||
prefix = prefix_file if prefix_package == "" else prefix_package + "_" + prefix_file
|
prefix = prefix_file if prefix_package == "" else prefix_package + "_" + prefix_file
|
||||||
return prefix
|
return prefix
|
||||||
|
|
||||||
def schemaFromFile(filepath, srcpath):
|
|
||||||
|
def schema_from_file(filepath, srcpath):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
schemapath = helpers.FilePath(filepath)
|
schemapath = helpers.FilePath(filepath)
|
||||||
prefix = getPrefixFromFile(schemapath.name)
|
prefix = get_prefix_from_file(schemapath.name)
|
||||||
header = helpers.FilePath(os.path.join(srcpath, prefix + ".h"))
|
header = helpers.FilePath(os.path.join(srcpath, prefix + ".h"))
|
||||||
source = helpers.FilePath(os.path.join(srcpath, prefix + ".c"))
|
source = helpers.FilePath(os.path.join(srcpath, prefix + ".c"))
|
||||||
schema_info = helpers.SchemaInfo(schemapath, header, source, prefix, srcpath)
|
schema_info = helpers.SchemaInfo(schemapath, header, source, prefix, srcpath)
|
||||||
return schema_info
|
return schema_info
|
||||||
|
|
||||||
def makeRefName(refname, reffile):
|
|
||||||
|
def make_ref_name(refname, reffile):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
prefix = getPrefixFromFile(reffile)
|
prefix = get_prefix_from_file(reffile)
|
||||||
if refname == "" or prefix.endswith(refname):
|
if refname == "" or prefix.endswith(refname):
|
||||||
return prefix
|
return prefix
|
||||||
return prefix + "_" + helpers.convertToCStyle(refname)
|
return prefix + "_" + helpers.conv_to_c_style(refname)
|
||||||
|
|
||||||
def splitRefName(ref):
|
|
||||||
|
def splite_ref_name(ref):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -145,6 +148,7 @@ def splitRefName(ref):
|
|||||||
tmp_f, tmp_r = ref.split("#/") if '#/' in ref else (ref, "")
|
tmp_f, tmp_r = ref.split("#/") if '#/' in ref else (ref, "")
|
||||||
return tmp_f, tmp_r
|
return tmp_f, tmp_r
|
||||||
|
|
||||||
|
|
||||||
def merge(children):
|
def merge(children):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
@ -166,7 +170,8 @@ BASIC_TYPES = (
|
|||||||
"booleanPointer"
|
"booleanPointer"
|
||||||
)
|
)
|
||||||
|
|
||||||
def judgeSupportedType(typ):
|
|
||||||
|
def judge_support_type(typ):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -174,7 +179,8 @@ def judgeSupportedType(typ):
|
|||||||
"""
|
"""
|
||||||
return typ in ("integer", "boolean", "string", "double") or typ in BASIC_TYPES
|
return typ in ("integer", "boolean", "string", "double") or typ in BASIC_TYPES
|
||||||
|
|
||||||
def getRefSubref(src, subref):
|
|
||||||
|
def get_ref_subref(src, subref):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -190,14 +196,15 @@ def getRefSubref(src, subref):
|
|||||||
|
|
||||||
return src, cur, subrefname
|
return src, cur, subrefname
|
||||||
|
|
||||||
def getRefRoot(schema_info, src, ref, curfile):
|
|
||||||
|
def get_ref_root(schema_info, src, ref, curfile):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
refname = ""
|
refname = ""
|
||||||
tmp_f, tmp_r = splitRefName(ref)
|
tmp_f, tmp_r = splite_ref_name(ref)
|
||||||
|
|
||||||
if tmp_f == "":
|
if tmp_f == "":
|
||||||
cur = src
|
cur = src
|
||||||
@ -205,7 +212,7 @@ def getRefRoot(schema_info, src, ref, curfile):
|
|||||||
realpath = os.path.realpath(os.path.join(os.path.dirname(curfile), tmp_f))
|
realpath = os.path.realpath(os.path.join(os.path.dirname(curfile), tmp_f))
|
||||||
curfile = realpath
|
curfile = realpath
|
||||||
|
|
||||||
subschema = schemaFromFile(realpath, schema_info.filesdir)
|
subschema = schema_from_file(realpath, schema_info.filesdir)
|
||||||
if schema_info.refs is None:
|
if schema_info.refs is None:
|
||||||
schema_info.refs = {}
|
schema_info.refs = {}
|
||||||
schema_info.refs[subschema.header.basename] = subschema
|
schema_info.refs[subschema.header.basename] = subschema
|
||||||
@ -213,19 +220,20 @@ def getRefRoot(schema_info, src, ref, curfile):
|
|||||||
cur = src = json.loads(i.read())
|
cur = src = json.loads(i.read())
|
||||||
subcur = cur
|
subcur = cur
|
||||||
if tmp_r != "":
|
if tmp_r != "":
|
||||||
src, subcur, refname = getRefSubref(src, tmp_r)
|
src, subcur, refname = get_ref_subref(src, tmp_r)
|
||||||
|
|
||||||
if 'type' not in subcur and '$ref' in subcur:
|
if 'type' not in subcur and '$ref' in subcur:
|
||||||
subf, subr = splitRefName(subcur['$ref'])
|
subf, subr = splite_ref_name(subcur['$ref'])
|
||||||
if subf == "":
|
if subf == "":
|
||||||
src, subcur, refname = getRefSubref(src, subr)
|
src, subcur, refname = get_ref_subref(src, subr)
|
||||||
if 'type' not in subcur:
|
if 'type' not in subcur:
|
||||||
raise RuntimeError("Not support reference of nesting more than 2 level: ", ref)
|
raise RuntimeError("Not support reference of nesting more than 2 level: ", ref)
|
||||||
else:
|
else:
|
||||||
return getRefRoot(schema_info, src, subcur['$ref'], curfile)
|
return get_ref_root(schema_info, src, subcur['$ref'], curfile)
|
||||||
return src, subcur, curfile, makeRefName(refname, curfile)
|
return src, subcur, curfile, make_ref_name(refname, curfile)
|
||||||
|
|
||||||
def getTypePatternInCur(cur, schema_info, src, curfile):
|
|
||||||
|
def get_type_pattern_incur(cur, schema_info, src, curfile):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -244,22 +252,23 @@ def getTypePatternInCur(cur, schema_info, src, curfile):
|
|||||||
if 'type' in value:
|
if 'type' in value:
|
||||||
val = value["type"]
|
val = value["type"]
|
||||||
else:
|
else:
|
||||||
dummy_subsrc, subcur, dummy_subcurfile, dummy_subrefname = getRefRoot(
|
dummy_subsrc, subcur, dummy_subcurfile, dummy_subrefname = get_ref_root(
|
||||||
schema_info, src, value['$ref'], curfile)
|
schema_info, src, value['$ref'], curfile)
|
||||||
val = subcur['type']
|
val = subcur['type']
|
||||||
break
|
break
|
||||||
|
|
||||||
mapKey = {
|
m_key = {
|
||||||
'object': 'Object',
|
'object': 'Object',
|
||||||
'string': 'String',
|
'string': 'String',
|
||||||
'integer': 'Int',
|
'integer': 'Int',
|
||||||
'boolean': 'Bool'
|
'boolean': 'Bool'
|
||||||
}[val]
|
}[val]
|
||||||
map_val = mapKey
|
map_val = m_key
|
||||||
|
|
||||||
typ = 'map' + map_key + map_val
|
typ = 'map' + map_key + map_val
|
||||||
return typ
|
return typ
|
||||||
|
|
||||||
|
|
||||||
class GenerateNodeInfo(object):
|
class GenerateNodeInfo(object):
|
||||||
'''
|
'''
|
||||||
Description: Store schema information
|
Description: Store schema information
|
||||||
@ -289,7 +298,8 @@ class GenerateNodeInfo(object):
|
|||||||
'''
|
'''
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def generateAllofArrayTypNode(node_info, src, typ, refname):
|
|
||||||
|
def gen_all_arr_typnode(node_info, src, typ, refname):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -302,7 +312,7 @@ def generateAllofArrayTypNode(node_info, src, typ, refname):
|
|||||||
subtyp = None
|
subtyp = None
|
||||||
subtypobj = None
|
subtypobj = None
|
||||||
required = None
|
required = None
|
||||||
children = merge(parseList(schema_info, name, src, cur["items"]['allOf'], curfile))
|
children = merge(resolve_list(schema_info, name, src, cur["items"]['allOf'], curfile))
|
||||||
subtyp = children[0].typ
|
subtyp = children[0].typ
|
||||||
subtypobj = children
|
subtypobj = children
|
||||||
return helpers.Unite(name,
|
return helpers.Unite(name,
|
||||||
@ -313,7 +323,8 @@ def generateAllofArrayTypNode(node_info, src, typ, refname):
|
|||||||
subtypname=refname,
|
subtypname=refname,
|
||||||
required=required), src
|
required=required), src
|
||||||
|
|
||||||
def generateAnyofArrayTypNode(node_info, src, typ, refname):
|
|
||||||
|
def gen_any_arr_typnode(node_info, src, typ, refname):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -326,7 +337,7 @@ def generateAnyofArrayTypNode(node_info, src, typ, refname):
|
|||||||
subtyp = None
|
subtyp = None
|
||||||
subtypobj = None
|
subtypobj = None
|
||||||
required = None
|
required = None
|
||||||
anychildren = parseList(schema_info, name, src, cur["items"]['anyOf'], curfile)
|
anychildren = resolve_list(schema_info, name, src, cur["items"]['anyOf'], curfile)
|
||||||
subtyp = anychildren[0].typ
|
subtyp = anychildren[0].typ
|
||||||
children = anychildren[0].children
|
children = anychildren[0].children
|
||||||
subtypobj = children
|
subtypobj = children
|
||||||
@ -339,7 +350,8 @@ def generateAnyofArrayTypNode(node_info, src, typ, refname):
|
|||||||
subtypname=refname,
|
subtypname=refname,
|
||||||
required=required), src
|
required=required), src
|
||||||
|
|
||||||
def generateRefArrayTypNode(node_info, src, typ, refname):
|
|
||||||
|
def gen_ref_arr_typnode(node_info, src, typ, refname):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -350,11 +362,11 @@ def generateRefArrayTypNode(node_info, src, typ, refname):
|
|||||||
cur = node_info.cur
|
cur = node_info.cur
|
||||||
curfile = node_info.curfile
|
curfile = node_info.curfile
|
||||||
|
|
||||||
item_type, src = resolveType(schema_info, name, src, cur["items"], curfile)
|
item_type, src = resolve_type(schema_info, name, src, cur["items"], curfile)
|
||||||
ref_file, subref = splitRefName(cur['items']['$ref'])
|
ref_file, subref = splite_ref_name(cur['items']['$ref'])
|
||||||
if ref_file == "":
|
if ref_file == "":
|
||||||
src, dummy_subcur, subrefname = getRefSubref(src, subref)
|
src, dummy_subcur, subrefname = get_ref_subref(src, subref)
|
||||||
refname = makeRefName(subrefname, curfile)
|
refname = make_ref_name(subrefname, curfile)
|
||||||
else:
|
else:
|
||||||
refname = item_type.subtypname
|
refname = item_type.subtypname
|
||||||
return helpers.Unite(name,
|
return helpers.Unite(name,
|
||||||
@ -365,7 +377,8 @@ def generateRefArrayTypNode(node_info, src, typ, refname):
|
|||||||
subtypname=refname,
|
subtypname=refname,
|
||||||
required=item_type.required), src
|
required=item_type.required), src
|
||||||
|
|
||||||
def generateTypeArrayTypNode(node_info, src, typ, refname):
|
|
||||||
|
def gen_type_arr_typnode(node_info, src, typ, refname):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -376,7 +389,7 @@ def generateTypeArrayTypNode(node_info, src, typ, refname):
|
|||||||
cur = node_info.cur
|
cur = node_info.cur
|
||||||
curfile = node_info.curfile
|
curfile = node_info.curfile
|
||||||
|
|
||||||
item_type, src = resolveType(schema_info, name, src, cur["items"], curfile)
|
item_type, src = resolve_type(schema_info, name, src, cur["items"], curfile)
|
||||||
return helpers.Unite(name,
|
return helpers.Unite(name,
|
||||||
typ,
|
typ,
|
||||||
None,
|
None,
|
||||||
@ -386,7 +399,7 @@ def generateTypeArrayTypNode(node_info, src, typ, refname):
|
|||||||
required=item_type.required), src
|
required=item_type.required), src
|
||||||
|
|
||||||
|
|
||||||
def generateArrayTypNode(node_info, src, typ, refname):
|
def gen_arr_typnode(node_info, src, typ, refname):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -395,16 +408,17 @@ def generateArrayTypNode(node_info, src, typ, refname):
|
|||||||
cur = node_info.cur
|
cur = node_info.cur
|
||||||
|
|
||||||
if 'allOf' in cur["items"]:
|
if 'allOf' in cur["items"]:
|
||||||
return generateAllofArrayTypNode(node_info, src, typ, refname)
|
return gen_all_arr_typnode(node_info, src, typ, refname)
|
||||||
elif 'anyOf' in cur["items"]:
|
elif 'anyOf' in cur["items"]:
|
||||||
return generateAnyofArrayTypNode(node_info, src, typ, refname)
|
return gen_any_arr_typnode(node_info, src, typ, refname)
|
||||||
elif '$ref' in cur["items"]:
|
elif '$ref' in cur["items"]:
|
||||||
return generateRefArrayTypNode(node_info, src, typ, refname)
|
return gen_ref_arr_typnode(node_info, src, typ, refname)
|
||||||
elif 'type' in cur["items"]:
|
elif 'type' in cur["items"]:
|
||||||
return generateTypeArrayTypNode(node_info, src, typ, refname)
|
return gen_type_arr_typnode(node_info, src, typ, refname)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def generateObjTypNode(node_info, src, typ, refname):
|
|
||||||
|
def gen_obj_typnode(node_info, src, typ, refname):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -420,18 +434,18 @@ def generateObjTypNode(node_info, src, typ, refname):
|
|||||||
required = None
|
required = None
|
||||||
|
|
||||||
if 'allOf' in cur:
|
if 'allOf' in cur:
|
||||||
children = merge(parseList(schema_info, name, src, cur['allOf'], curfile))
|
children = merge(resolve_list(schema_info, name, src, cur['allOf'], curfile))
|
||||||
elif 'anyOf' in cur:
|
elif 'anyOf' in cur:
|
||||||
children = parseList(schema_info, name, src, cur['anyOf'], curfile)
|
children = resolve_list(schema_info, name, src, cur['anyOf'], curfile)
|
||||||
elif 'patternProperties' in cur:
|
elif 'patternProperties' in cur:
|
||||||
children = parseProperties(schema_info, name, src, cur, curfile)
|
children = parse_properties(schema_info, name, src, cur, curfile)
|
||||||
children[0].name = children[0].name.replace('_{1,}', 'element').replace('_{2,}', \
|
children[0].name = children[0].name.replace('_{1,}', 'element').replace('_{2,}', \
|
||||||
'element')
|
'element')
|
||||||
children[0].fixname = "values"
|
children[0].fixname = "values"
|
||||||
if helpers.validBasicMapName(children[0].typ):
|
if helpers.valid_basic_map_name(children[0].typ):
|
||||||
children[0].name = helpers.makeBasicMapName(children[0].typ)
|
children[0].name = helpers.make_basic_map_name(children[0].typ)
|
||||||
else:
|
else:
|
||||||
children = parseProperties(schema_info, name, src, cur, curfile) \
|
children = parse_properties(schema_info, name, src, cur, curfile) \
|
||||||
if 'properties' in cur else None
|
if 'properties' in cur else None
|
||||||
if 'required' in cur:
|
if 'required' in cur:
|
||||||
required = cur['required']
|
required = cur['required']
|
||||||
@ -443,14 +457,15 @@ def generateObjTypNode(node_info, src, typ, refname):
|
|||||||
subtypname=refname,\
|
subtypname=refname,\
|
||||||
required=required), src
|
required=required), src
|
||||||
|
|
||||||
def getTypNotOneof(schema_info, src, cur, curfile):
|
|
||||||
|
def get_typ_notoneof(schema_info, src, cur, curfile):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
if 'patternProperties' in cur:
|
if 'patternProperties' in cur:
|
||||||
typ = getTypePatternInCur(cur, schema_info, src, curfile)
|
typ = get_type_pattern_incur(cur, schema_info, src, curfile)
|
||||||
elif "type" in cur:
|
elif "type" in cur:
|
||||||
typ = cur["type"]
|
typ = cur["type"]
|
||||||
else:
|
else:
|
||||||
@ -459,7 +474,7 @@ def getTypNotOneof(schema_info, src, cur, curfile):
|
|||||||
return typ
|
return typ
|
||||||
|
|
||||||
|
|
||||||
def resolveType(schema_info, name, src, cur, curfile):
|
def resolve_type(schema_info, name, src, cur, curfile):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -472,31 +487,31 @@ def resolveType(schema_info, name, src, cur, curfile):
|
|||||||
refname = None
|
refname = None
|
||||||
|
|
||||||
if '$ref' in cur:
|
if '$ref' in cur:
|
||||||
src, cur, curfile, refname = getRefRoot(schema_info, src, cur['$ref'], curfile)
|
src, cur, curfile, refname = get_ref_root(schema_info, src, cur['$ref'], curfile)
|
||||||
|
|
||||||
if "oneOf" in cur:
|
if "oneOf" in cur:
|
||||||
cur = cur['oneOf'][0]
|
cur = cur['oneOf'][0]
|
||||||
if '$ref' in cur:
|
if '$ref' in cur:
|
||||||
return resolveType(schema_info, name, src, cur, curfile)
|
return resolve_type(schema_info, name, src, cur, curfile)
|
||||||
else:
|
else:
|
||||||
typ = cur['type']
|
typ = cur['type']
|
||||||
else:
|
else:
|
||||||
typ = getTypNotOneof(schema_info, src, cur, curfile)
|
typ = get_typ_notoneof(schema_info, src, cur, curfile)
|
||||||
|
|
||||||
node_info = GenerateNodeInfo(schema_info, name, cur, curfile)
|
node_info = GenerateNodeInfo(schema_info, name, cur, curfile)
|
||||||
|
|
||||||
if helpers.validBasicMapName(typ):
|
if helpers.valid_basic_map_name(typ):
|
||||||
pass
|
pass
|
||||||
elif typ == 'array':
|
elif typ == 'array':
|
||||||
return generateArrayTypNode(node_info, src, typ, refname)
|
return gen_arr_typnode(node_info, src, typ, refname)
|
||||||
elif typ == 'object' or typ == 'mapStringObject':
|
elif typ == 'object' or typ == 'mapStringObject':
|
||||||
return generateObjTypNode(node_info, src, typ, refname)
|
return gen_obj_typnode(node_info, src, typ, refname)
|
||||||
elif typ == 'ArrayOfStrings':
|
elif typ == 'ArrayOfStrings':
|
||||||
typ = 'array'
|
typ = 'array'
|
||||||
subtyp = 'string'
|
subtyp = 'string'
|
||||||
children = subtypobj = None
|
children = subtypobj = None
|
||||||
else:
|
else:
|
||||||
if not judgeSupportedType(typ):
|
if not judge_support_type(typ):
|
||||||
raise RuntimeError("Invalid schema type: %s" % typ)
|
raise RuntimeError("Invalid schema type: %s" % typ)
|
||||||
children = None
|
children = None
|
||||||
|
|
||||||
@ -509,7 +524,7 @@ def resolveType(schema_info, name, src, cur, curfile):
|
|||||||
required=required), src
|
required=required), src
|
||||||
|
|
||||||
|
|
||||||
def parseList(schema_info, name, schema, objs, curfile):
|
def resolve_list(schema_info, name, schema, objs, curfile):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -518,9 +533,10 @@ def parseList(schema_info, name, schema, objs, curfile):
|
|||||||
obj = []
|
obj = []
|
||||||
index = 0
|
index = 0
|
||||||
for i in objs:
|
for i in objs:
|
||||||
generated_name = helpers.CombinationName( \
|
generated_name = helpers.CombinateName( \
|
||||||
i['$ref'].split("/")[-1]) if '$ref' in i else helpers.CombinationName(name.name + str(index))
|
i['$ref'].split("/")[-1]) if '$ref' in i \
|
||||||
node, _ = resolveType(schema_info, generated_name, schema, i, curfile)
|
else helpers.CombinateName(name.name + str(index))
|
||||||
|
node, _ = resolve_type(schema_info, generated_name, schema, i, curfile)
|
||||||
if node:
|
if node:
|
||||||
obj.append(node)
|
obj.append(node)
|
||||||
index += 1
|
index += 1
|
||||||
@ -529,7 +545,7 @@ def parseList(schema_info, name, schema, objs, curfile):
|
|||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
def parseDictionary(schema_info, name, schema, objs, curfile):
|
def parse_dict(schema_info, name, schema, objs, curfile):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -537,7 +553,7 @@ def parseDictionary(schema_info, name, schema, objs, curfile):
|
|||||||
"""
|
"""
|
||||||
obj = []
|
obj = []
|
||||||
for i in objs:
|
for i in objs:
|
||||||
node, _ = resolveType(schema_info, name.append(i), schema, objs[i], curfile)
|
node, _ = resolve_type(schema_info, name.append(i), schema, objs[i], curfile)
|
||||||
if node:
|
if node:
|
||||||
obj.append(node)
|
obj.append(node)
|
||||||
if not obj:
|
if not obj:
|
||||||
@ -545,19 +561,20 @@ def parseDictionary(schema_info, name, schema, objs, curfile):
|
|||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
def parseProperties(schema_info, name, schema, props, curfile):
|
def parse_properties(schema_info, name, schema, props, curfile):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
if 'definitions' in props:
|
if 'definitions' in props:
|
||||||
return parseDictionary(schema_info, name, schema, props['definitions'], curfile)
|
return parse_dict(schema_info, name, schema, props['definitions'], curfile)
|
||||||
if 'patternProperties' in props:
|
if 'patternProperties' in props:
|
||||||
return parseDictionary(schema_info, name, schema, props['patternProperties'], curfile)
|
return parse_dict(schema_info, name, schema, props['patternProperties'], curfile)
|
||||||
return parseDictionary(schema_info, name, schema, props['properties'], curfile)
|
return parse_dict(schema_info, name, schema, props['properties'], curfile)
|
||||||
|
|
||||||
def handleTypeNotInSchema(schema_info, schema, prefix):
|
|
||||||
|
def handle_type_not_in_schema(schema_info, schema, prefix):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -566,8 +583,8 @@ def handleTypeNotInSchema(schema_info, schema, prefix):
|
|||||||
required = None
|
required = None
|
||||||
if 'definitions' in schema:
|
if 'definitions' in schema:
|
||||||
return helpers.Unite( \
|
return helpers.Unite( \
|
||||||
helpers.CombinationName("definitions"), 'definitions', \
|
helpers.CombinateName("definitions"), 'definitions', \
|
||||||
parseProperties(schema_info, helpers.CombinationName(""), schema, schema, \
|
parse_properties(schema_info, helpers.CombinateName(""), schema, schema, \
|
||||||
schema_info.name.name), None, None, None, None)
|
schema_info.name.name), None, None, None, None)
|
||||||
else:
|
else:
|
||||||
if len(schema) > 1:
|
if len(schema) > 1:
|
||||||
@ -577,15 +594,19 @@ def handleTypeNotInSchema(schema_info, schema, prefix):
|
|||||||
for value in schema:
|
for value in schema:
|
||||||
if 'required' in schema[value]:
|
if 'required' in schema[value]:
|
||||||
required = schema[value]['required']
|
required = schema[value]['required']
|
||||||
childrens = parseProperties(schema_info, helpers.CombinationName(""), schema[value], \
|
childrens = parse_properties(schema_info, helpers.CombinateName(""), \
|
||||||
schema[value], schema_info.name.name)
|
schema[value], schema[value], \
|
||||||
value_node = helpers.Unite(helpers.CombinationName(prefix), 'object', childrens, None, None, \
|
schema_info.name.name)
|
||||||
|
value_node = helpers.Unite(helpers.CombinateName(prefix), \
|
||||||
|
'object', childrens, None, None, \
|
||||||
None, required)
|
None, required)
|
||||||
value_nodes.append(value_node)
|
value_nodes.append(value_node)
|
||||||
return helpers.Unite(helpers.CombinationName("definitions"), 'definitions', value_nodes, None, None, \
|
return helpers.Unite(helpers.CombinateName("definitions"), \
|
||||||
|
'definitions', value_nodes, None, None, \
|
||||||
None, None)
|
None, None)
|
||||||
|
|
||||||
def parseSchema(schema_info, schema, prefix):
|
|
||||||
|
def parse_schema(schema_info, schema, prefix):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -593,23 +614,21 @@ def parseSchema(schema_info, schema, prefix):
|
|||||||
"""
|
"""
|
||||||
required = None
|
required = None
|
||||||
if 'type' not in schema:
|
if 'type' not in schema:
|
||||||
return handleTypeNotInSchema(schema_info, schema, prefix)
|
return handle_type_not_in_schema(schema_info, schema, prefix)
|
||||||
|
|
||||||
if 'type' not in schema:
|
|
||||||
print("No 'type' defined in schema")
|
|
||||||
return prefix, None
|
|
||||||
|
|
||||||
if 'object' in schema['type']:
|
if 'object' in schema['type']:
|
||||||
if 'required' in schema:
|
if 'required' in schema:
|
||||||
required = schema['required']
|
required = schema['required']
|
||||||
return helpers.Unite(
|
return helpers.Unite(
|
||||||
helpers.CombinationName(prefix), 'object',
|
helpers.CombinateName(prefix), 'object',
|
||||||
parseProperties(schema_info, helpers.CombinationName(""), schema, schema, schema_info.name.name), \
|
parse_properties(schema_info, \
|
||||||
|
helpers.CombinateName(""), \
|
||||||
|
schema, schema, schema_info.name.name), \
|
||||||
None, None, None, required)
|
None, None, None, required)
|
||||||
elif 'array' in schema['type']:
|
elif 'array' in schema['type']:
|
||||||
item_type, _ = resolveType(schema_info, helpers.CombinationName(""), schema['items'], \
|
item_type, _ = resolve_type(schema_info, helpers.CombinateName(""), \
|
||||||
schema['items'], schema_info.name.name)
|
schema['items'], schema['items'], schema_info.name.name)
|
||||||
return helpers.Unite(helpers.CombinationName(prefix), 'array', None, item_type.typ, \
|
return helpers.Unite(helpers.CombinateName(prefix), 'array', None, item_type.typ, \
|
||||||
item_type.children, None, item_type.required)
|
item_type.children, None, item_type.required)
|
||||||
else:
|
else:
|
||||||
print("Not supported type '%s'") % schema['type']
|
print("Not supported type '%s'") % schema['type']
|
||||||
@ -631,8 +650,8 @@ def expand(tree, structs, visited):
|
|||||||
for i in tree.subtypobj:
|
for i in tree.subtypobj:
|
||||||
expand(i, structs, visited=visited)
|
expand(i, structs, visited=visited)
|
||||||
|
|
||||||
if tree.typ == 'array' and helpers.validBasicMapName(tree.subtyp):
|
if tree.typ == 'array' and helpers.valid_basic_map_name(tree.subtyp):
|
||||||
name = helpers.CombinationName(tree.name + "_element")
|
name = helpers.CombinateName(tree.name + "_element")
|
||||||
node = helpers.Unite(name, tree.subtyp, None)
|
node = helpers.Unite(name, tree.subtyp, None)
|
||||||
expand(node, structs, visited)
|
expand(node, structs, visited)
|
||||||
|
|
||||||
@ -658,13 +677,13 @@ def reflection(schema_info, gen_ref):
|
|||||||
with open(schema_info.name.name) as schema_file:
|
with open(schema_info.name.name) as schema_file:
|
||||||
schema_json = json.loads(schema_file.read(), object_pairs_hook=OrderedDict)
|
schema_json = json.loads(schema_file.read(), object_pairs_hook=OrderedDict)
|
||||||
try:
|
try:
|
||||||
tree = parseSchema(schema_info, schema_json, schema_info.prefix)
|
tree = parse_schema(schema_info, schema_json, schema_info.prefix)
|
||||||
if tree is None:
|
if tree is None:
|
||||||
print("Failed parse schema")
|
print("Failed parse schema")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
structs = expand(tree, [], {})
|
structs = expand(tree, [], {})
|
||||||
headers.headerReflection(structs, schema_info, header_file)
|
headers.header_reflect(structs, schema_info, header_file)
|
||||||
sources.sourceReflection(structs, schema_info, source_file, tree.typ)
|
sources.src_reflect(structs, schema_info, source_file, tree.typ)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
print("Failed to parse schema file: %s") % schema_info.name.name
|
print("Failed to parse schema file: %s") % schema_info.name.name
|
||||||
@ -681,7 +700,7 @@ def reflection(schema_info, gen_ref):
|
|||||||
reflection(reffile, True)
|
reflection(reffile, True)
|
||||||
|
|
||||||
|
|
||||||
def generateCommonFiles(out):
|
def gen_common_files(out):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -699,7 +718,8 @@ def generateCommonFiles(out):
|
|||||||
fcntl.flock(source_file, fcntl.LOCK_UN)
|
fcntl.flock(source_file, fcntl.LOCK_UN)
|
||||||
fcntl.flock(header_file, fcntl.LOCK_UN)
|
fcntl.flock(header_file, fcntl.LOCK_UN)
|
||||||
|
|
||||||
def handlerSingleFile(args, srcpath, gen_ref, schemapath):
|
|
||||||
|
def handle_single_file(args, srcpath, gen_ref, schemapath):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -715,7 +735,7 @@ def handlerSingleFile(args, srcpath, gen_ref, schemapath):
|
|||||||
for dirpath, dummy_dirnames, files in os.walk(schemapath.name):
|
for dirpath, dummy_dirnames, files in os.walk(schemapath.name):
|
||||||
for target_file in files:
|
for target_file in files:
|
||||||
if target_file.endswith(JSON_SUFFIX):
|
if target_file.endswith(JSON_SUFFIX):
|
||||||
schema_info = schemaFromFile(os.path.join(dirpath, target_file), \
|
schema_info = schema_from_file(os.path.join(dirpath, target_file), \
|
||||||
srcpath.name)
|
srcpath.name)
|
||||||
reflection(schema_info, gen_ref)
|
reflection(schema_info, gen_ref)
|
||||||
else:
|
else:
|
||||||
@ -723,17 +743,17 @@ def handlerSingleFile(args, srcpath, gen_ref, schemapath):
|
|||||||
for target_file in os.listdir(schemapath.name):
|
for target_file in os.listdir(schemapath.name):
|
||||||
fullpath = os.path.join(schemapath.name, target_file)
|
fullpath = os.path.join(schemapath.name, target_file)
|
||||||
if fullpath.endswith(JSON_SUFFIX) and os.path.isfile(fullpath):
|
if fullpath.endswith(JSON_SUFFIX) and os.path.isfile(fullpath):
|
||||||
schema_info = schemaFromFile(fullpath, srcpath.name)
|
schema_info = schema_from_file(fullpath, srcpath.name)
|
||||||
reflection(schema_info, gen_ref)
|
reflection(schema_info, gen_ref)
|
||||||
else:
|
else:
|
||||||
if schemapath.name.endswith(JSON_SUFFIX):
|
if schemapath.name.endswith(JSON_SUFFIX):
|
||||||
schema_info = schemaFromFile(schemapath.name, srcpath.name)
|
schema_info = schema_from_file(schemapath.name, srcpath.name)
|
||||||
reflection(schema_info, gen_ref)
|
reflection(schema_info, gen_ref)
|
||||||
else:
|
else:
|
||||||
print('File %s is not ends with .json') % schemapath.name
|
print('File %s is not ends with .json') % schemapath.name
|
||||||
|
|
||||||
|
|
||||||
def handlerFiles(args, srcpath):
|
def handle_files(args, srcpath):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -742,7 +762,8 @@ def handlerFiles(args, srcpath):
|
|||||||
for path in args.path:
|
for path in args.path:
|
||||||
gen_ref = args.gen_ref
|
gen_ref = args.gen_ref
|
||||||
schemapath = helpers.FilePath(path)
|
schemapath = helpers.FilePath(path)
|
||||||
handlerSingleFile(args, srcpath, gen_ref, schemapath)
|
handle_single_file(args, srcpath, gen_ref, schemapath)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""
|
"""
|
||||||
@ -795,8 +816,11 @@ def main():
|
|||||||
os.makedirs(srcpath.name)
|
os.makedirs(srcpath.name)
|
||||||
|
|
||||||
if args.gen_common:
|
if args.gen_common:
|
||||||
generateCommonFiles(srcpath.name)
|
gen_common_files(srcpath.name)
|
||||||
handlerFiles(args, srcpath)
|
handle_files(args, srcpath)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,7 @@ History: 2019-06-17
|
|||||||
#!/usr/bin/python -Es
|
#!/usr/bin/python -Es
|
||||||
import helpers
|
import helpers
|
||||||
|
|
||||||
def appendHeaderArray(obj, header, prefix):
|
def append_header_arr(obj, header, prefix):
|
||||||
'''
|
'''
|
||||||
Description: Write c header file of array
|
Description: Write c header file of array
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -30,28 +30,29 @@ def appendHeaderArray(obj, header, prefix):
|
|||||||
header.write("typedef struct {\n")
|
header.write("typedef struct {\n")
|
||||||
for i in obj.subtypobj:
|
for i in obj.subtypobj:
|
||||||
if i.typ == 'array':
|
if i.typ == 'array':
|
||||||
c_typ = helpers.getPrefixPointer(i.name, i.subtyp, prefix) or \
|
c_typ = helpers.get_prefixe_pointer(i.name, i.subtyp, prefix) or \
|
||||||
helpers.getMapCTypes(i.subtyp)
|
helpers.get_map_c_types(i.subtyp)
|
||||||
if i.subtypobj is not None:
|
if i.subtypobj is not None:
|
||||||
c_typ = helpers.getNameSubstr(i.name, prefix)
|
c_typ = helpers.get_name_substr(i.name, prefix)
|
||||||
|
|
||||||
if not helpers.judgeComplex(i.subtyp):
|
if not helpers.judge_complex(i.subtyp):
|
||||||
header.write(" %s%s*%s;\n" % (c_typ, " " if '*' not in c_typ else "", \
|
header.write(" %s%s*%s;\n" % (c_typ, " " if '*' not in c_typ else "", \
|
||||||
i.fixname))
|
i.fixname))
|
||||||
else:
|
else:
|
||||||
header.write(" %s **%s;\n" % (c_typ, i.fixname))
|
header.write(" %s **%s;\n" % (c_typ, i.fixname))
|
||||||
header.write(" size_t %s;\n\n" % (i.fixname + "_len"))
|
header.write(" size_t %s;\n\n" % (i.fixname + "_len"))
|
||||||
else:
|
else:
|
||||||
c_typ = helpers.getPrefixPointer(i.name, i.typ, prefix) or \
|
c_typ = helpers.get_prefixe_pointer(i.name, i.typ, prefix) or \
|
||||||
helpers.getMapCTypes(i.typ)
|
helpers.get_map_c_types(i.typ)
|
||||||
header.write(" %s%s%s;\n" % (c_typ, " " if '*' not in c_typ else "", i.fixname))
|
header.write(" %s%s%s;\n" % (c_typ, " " if '*' not in c_typ else "", i.fixname))
|
||||||
typename = helpers.getNameSubstr(obj.name, prefix)
|
typename = helpers.get_name_substr(obj.name, prefix)
|
||||||
header.write("}\n%s;\n\n" % typename)
|
header.write("}\n%s;\n\n" % typename)
|
||||||
header.write("void free_%s(%s *ptr);\n\n" % (typename, 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);"\
|
header.write("%s *make_%s(yajl_val tree, const struct parser_context *ctx, parser_error *err);"\
|
||||||
"\n\n" % (typename, typename))
|
"\n\n" % (typename, typename))
|
||||||
|
|
||||||
def appendHeaderMapStrObj(obj, header, prefix):
|
|
||||||
|
def append_header_map_str_obj(obj, header, prefix):
|
||||||
'''
|
'''
|
||||||
Description: Write c header file of mapStringObject
|
Description: Write c header file of mapStringObject
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -60,73 +61,76 @@ def appendHeaderMapStrObj(obj, header, prefix):
|
|||||||
child = obj.children[0]
|
child = obj.children[0]
|
||||||
header.write("typedef struct {\n")
|
header.write("typedef struct {\n")
|
||||||
header.write(" char **keys;\n")
|
header.write(" char **keys;\n")
|
||||||
if helpers.validBasicMapName(child.typ):
|
if helpers.valid_basic_map_name(child.typ):
|
||||||
c_typ = helpers.getPrefixPointer("", child.typ, "")
|
c_typ = helpers.get_prefixe_pointer("", child.typ, "")
|
||||||
elif child.subtypname:
|
elif child.subtypname:
|
||||||
c_typ = child.subtypname
|
c_typ = child.subtypname
|
||||||
else:
|
else:
|
||||||
c_typ = helpers.getPrefixPointer(child.name, child.typ, prefix)
|
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(" %s%s*%s;\n" % (c_typ, " " if '*' not in c_typ else "", child.fixname))
|
||||||
header.write(" size_t len;\n")
|
header.write(" size_t len;\n")
|
||||||
|
|
||||||
def appendHeaderChildArray(child, header, prefix):
|
|
||||||
|
def append_header_child_arr(child, header, prefix):
|
||||||
'''
|
'''
|
||||||
Description: Write c header file of array of child
|
Description: Write c header file of array of child
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
'''
|
'''
|
||||||
if helpers.getMapCTypes(child.subtyp) != "":
|
if helpers.get_map_c_types(child.subtyp) != "":
|
||||||
c_typ = helpers.getMapCTypes(child.subtyp)
|
c_typ = helpers.get_map_c_types(child.subtyp)
|
||||||
elif helpers.validBasicMapName(child.subtyp):
|
elif helpers.valid_basic_map_name(child.subtyp):
|
||||||
c_typ = '%s *' % helpers.makeBasicMapName(child.subtyp)
|
c_typ = '%s *' % helpers.make_basic_map_name(child.subtyp)
|
||||||
elif child.subtypname is not None:
|
elif child.subtypname is not None:
|
||||||
c_typ = child.subtypname
|
c_typ = child.subtypname
|
||||||
elif child.subtypobj is not None:
|
elif child.subtypobj is not None:
|
||||||
c_typ = helpers.getNameSubstr(child.name, prefix)
|
c_typ = helpers.get_name_substr(child.name, prefix)
|
||||||
else:
|
else:
|
||||||
c_typ = helpers.getPrefixPointer(child.name, child.subtyp, prefix)
|
c_typ = helpers.get_prefixe_pointer(child.name, child.subtyp, prefix)
|
||||||
|
|
||||||
if helpers.validBasicMapName(child.subtyp):
|
if helpers.valid_basic_map_name(child.subtyp):
|
||||||
header.write(" %s **%s;\n" % (helpers.makeBasicMapName(child.subtyp), child.fixname))
|
header.write(" %s **%s;\n" % (helpers.make_basic_map_name(child.subtyp), child.fixname))
|
||||||
elif not helpers.judgeComplex(child.subtyp):
|
elif not helpers.judge_complex(child.subtyp):
|
||||||
header.write(" %s%s*%s;\n" % (c_typ, " " if '*' not in c_typ else "", child.fixname))
|
header.write(" %s%s*%s;\n" % (c_typ, " " if '*' not in c_typ else "", child.fixname))
|
||||||
else:
|
else:
|
||||||
header.write(" %s%s**%s;\n" % (c_typ, " " if '*' not in c_typ else "", child.fixname))
|
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"))
|
header.write(" size_t %s;\n\n" % (child.fixname + "_len"))
|
||||||
|
|
||||||
def appendHeaderChildOthers(child, header, prefix):
|
|
||||||
|
def append_header_child_others(child, header, prefix):
|
||||||
'''
|
'''
|
||||||
Description: Write c header file of others of child
|
Description: Write c header file of others of child
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
'''
|
'''
|
||||||
if helpers.getMapCTypes(child.typ) != "":
|
if helpers.get_map_c_types(child.typ) != "":
|
||||||
c_typ = helpers.getMapCTypes(child.typ)
|
c_typ = helpers.get_map_c_types(child.typ)
|
||||||
elif helpers.validBasicMapName(child.typ):
|
elif helpers.valid_basic_map_name(child.typ):
|
||||||
c_typ = '%s *' % helpers.makeBasicMapName(child.typ)
|
c_typ = '%s *' % helpers.make_basic_map_name(child.typ)
|
||||||
elif child.subtypname:
|
elif child.subtypname:
|
||||||
c_typ = helpers.getPrefixPointer(child.subtypname, child.typ, "")
|
c_typ = helpers.get_prefixe_pointer(child.subtypname, child.typ, "")
|
||||||
else:
|
else:
|
||||||
c_typ = helpers.getPrefixPointer(child.name, child.typ, prefix)
|
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))
|
header.write(" %s%s%s;\n\n" % (c_typ, " " if '*' not in c_typ else "", child.fixname))
|
||||||
|
|
||||||
def appendTypeCHeader(obj, header, prefix):
|
|
||||||
|
def append_type_c_header(obj, header, prefix):
|
||||||
'''
|
'''
|
||||||
Description: Write c header file
|
Description: Write c header file
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
'''
|
'''
|
||||||
if not helpers.judgeComplex(obj.typ):
|
if not helpers.judge_complex(obj.typ):
|
||||||
return
|
return
|
||||||
|
|
||||||
if obj.typ == 'array':
|
if obj.typ == 'array':
|
||||||
appendHeaderArray(obj, header, prefix)
|
append_header_arr(obj, header, prefix)
|
||||||
return
|
return
|
||||||
|
|
||||||
if obj.typ == 'mapStringObject':
|
if obj.typ == 'mapStringObject':
|
||||||
if obj.subtypname is not None:
|
if obj.subtypname is not None:
|
||||||
return
|
return
|
||||||
appendHeaderMapStrObj(obj, header, prefix)
|
append_header_map_str_obj(obj, header, prefix)
|
||||||
elif obj.typ == 'object':
|
elif obj.typ == 'object':
|
||||||
if obj.subtypname is not None:
|
if obj.subtypname is not None:
|
||||||
return
|
return
|
||||||
@ -135,11 +139,11 @@ def appendTypeCHeader(obj, header, prefix):
|
|||||||
header.write(" char unuseful; // unuseful definition to avoid empty struct\n")
|
header.write(" char unuseful; // unuseful definition to avoid empty struct\n")
|
||||||
for i in obj.children or []:
|
for i in obj.children or []:
|
||||||
if i.typ == 'array':
|
if i.typ == 'array':
|
||||||
appendHeaderChildArray(i, header, prefix)
|
append_header_child_arr(i, header, prefix)
|
||||||
else:
|
else:
|
||||||
appendHeaderChildOthers(i, header, prefix)
|
append_header_child_others(i, header, prefix)
|
||||||
|
|
||||||
typename = helpers.getPrefixName(obj.name, prefix)
|
typename = helpers.get_prefixe_name(obj.name, prefix)
|
||||||
header.write("}\n%s;\n\n" % typename)
|
header.write("}\n%s;\n\n" % typename)
|
||||||
header.write("void free_%s(%s *ptr);\n\n" % (typename, 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)"\
|
header.write("%s *make_%s(yajl_val tree, const struct parser_context *ctx, parser_error *err)"\
|
||||||
@ -147,7 +151,8 @@ def appendTypeCHeader(obj, header, prefix):
|
|||||||
header.write("yajl_gen_status gen_%s(yajl_gen g, const %s *ptr, const struct parser_context "\
|
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))
|
"*ctx, parser_error *err);\n\n" % (typename, typename))
|
||||||
|
|
||||||
def headerReflection(structs, schema_info, header):
|
|
||||||
|
def header_reflect(structs, schema_info, header):
|
||||||
'''
|
'''
|
||||||
Description: Reflection header files
|
Description: Reflection header files
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -168,7 +173,7 @@ def headerReflection(structs, schema_info, header):
|
|||||||
header.write("#endif\n\n")
|
header.write("#endif\n\n")
|
||||||
|
|
||||||
for i in structs:
|
for i in structs:
|
||||||
appendTypeCHeader(i, header, prefix)
|
append_type_c_header(i, header, prefix)
|
||||||
length = len(structs)
|
length = len(structs)
|
||||||
toptype = structs[length - 1].typ if length != 0 else ""
|
toptype = structs[length - 1].typ if length != 0 else ""
|
||||||
if toptype == 'object':
|
if toptype == 'object':
|
||||||
@ -195,3 +200,4 @@ def headerReflection(structs, schema_info, header):
|
|||||||
header.write("}\n")
|
header.write("}\n")
|
||||||
header.write("#endif\n\n")
|
header.write("#endif\n\n")
|
||||||
header.write("#endif\n\n")
|
header.write("#endif\n\n")
|
||||||
|
|
||||||
|
|||||||
@ -20,16 +20,16 @@ History: 2019-06-17
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
def appendSeparator(subStr):
|
def append_separator(substr):
|
||||||
'''
|
'''
|
||||||
Description: append only '_' at last position of subStr
|
Description: append only '_' at last position of subStr
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-09-20
|
History: 2019-09-20
|
||||||
'''
|
'''
|
||||||
if subStr and subStr[-1] != '_':
|
if substr and substr[-1] != '_':
|
||||||
subStr.append('_')
|
substr.append('_')
|
||||||
|
|
||||||
def convertToCStyle(name):
|
def conv_to_c_style(name):
|
||||||
'''
|
'''
|
||||||
Description: convert name to linux c format
|
Description: convert name to linux c format
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -38,33 +38,33 @@ def convertToCStyle(name):
|
|||||||
if name is None or name == "":
|
if name is None or name == "":
|
||||||
return ""
|
return ""
|
||||||
name = name.replace('.', '_').replace('-', '_').replace('/', '_')
|
name = name.replace('.', '_').replace('-', '_').replace('/', '_')
|
||||||
subStr = []
|
substr = []
|
||||||
preindex = 0
|
preindex = 0
|
||||||
index = 0
|
index = 0
|
||||||
for index, char in enumerate(name):
|
for index, char in enumerate(name):
|
||||||
if char == '_':
|
if char == '_':
|
||||||
appendSeparator(subStr)
|
append_separator(substr)
|
||||||
subStr.append(name[preindex:index].lower())
|
substr.append(name[preindex:index].lower())
|
||||||
preindex = index + 1
|
preindex = index + 1
|
||||||
if not char.isupper() and name[preindex].isupper() and \
|
if not char.isupper() and name[preindex].isupper() and \
|
||||||
name[preindex + 1].isupper():
|
name[preindex + 1].isupper():
|
||||||
appendSeparator(subStr)
|
append_separator(substr)
|
||||||
subStr.append(name[preindex:index - 1].lower())
|
substr.append(name[preindex:index - 1].lower())
|
||||||
preindex = index - 1
|
preindex = index - 1
|
||||||
continue
|
continue
|
||||||
if char.isupper() and index > 0 and name[index - 1].islower():
|
if char.isupper() and index > 0 and name[index - 1].islower():
|
||||||
appendSeparator(subStr)
|
append_separator(substr)
|
||||||
subStr.append(name[preindex:index].lower())
|
substr.append(name[preindex:index].lower())
|
||||||
preindex = index
|
preindex = index
|
||||||
|
|
||||||
if preindex <= index and index >= 0 and name[index] != '_' and \
|
if preindex <= index and index >= 0 and name[index] != '_' and \
|
||||||
preindex != 0:
|
preindex != 0:
|
||||||
appendSeparator(subStr)
|
append_separator(substr)
|
||||||
subStr.append(name[preindex:index + 1].lower())
|
substr.append(name[preindex:index + 1].lower())
|
||||||
result = ''.join(subStr)
|
result = ''.join(substr)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def getMapCTypes(typ):
|
def get_map_c_types(typ):
|
||||||
'''
|
'''
|
||||||
Description: Get map c types
|
Description: Get map c types
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -103,7 +103,7 @@ def getMapCTypes(typ):
|
|||||||
return map_c_types[typ]
|
return map_c_types[typ]
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def validBasicMapName(typ):
|
def valid_basic_map_name(typ):
|
||||||
'''
|
'''
|
||||||
Description: Valid basic map name
|
Description: Valid basic map name
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -112,14 +112,14 @@ def validBasicMapName(typ):
|
|||||||
return typ != 'mapStringObject' and hasattr(typ, 'startswith') and \
|
return typ != 'mapStringObject' and hasattr(typ, 'startswith') and \
|
||||||
typ.startswith('map')
|
typ.startswith('map')
|
||||||
|
|
||||||
def makeBasicMapName(mapname):
|
def make_basic_map_name(mapname):
|
||||||
'''
|
'''
|
||||||
Description: Make basic map name
|
Description: Make basic map name
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
'''
|
'''
|
||||||
basic_map_types = ('string', 'int', 'bool')
|
basic_map_types = ('string', 'int', 'bool')
|
||||||
parts = convertToCStyle(mapname).split('_')
|
parts = conv_to_c_style(mapname).split('_')
|
||||||
if len(parts) != 3 or parts[0] != 'map' or \
|
if len(parts) != 3 or parts[0] != 'map' or \
|
||||||
(parts[1] not in basic_map_types) or \
|
(parts[1] not in basic_map_types) or \
|
||||||
(parts[2] not in basic_map_types):
|
(parts[2] not in basic_map_types):
|
||||||
@ -128,7 +128,7 @@ def makeBasicMapName(mapname):
|
|||||||
return "json_map_%s_%s" % (parts[1], parts[2])
|
return "json_map_%s_%s" % (parts[1], parts[2])
|
||||||
|
|
||||||
|
|
||||||
def getNameSubstr(name, prefix):
|
def get_name_substr(name, prefix):
|
||||||
'''
|
'''
|
||||||
Description: Make array name
|
Description: Make array name
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -137,7 +137,7 @@ def getNameSubstr(name, prefix):
|
|||||||
return "%s_element" % prefix if name is None or name == "" or prefix == name \
|
return "%s_element" % prefix if name is None or name == "" or prefix == name \
|
||||||
else "%s_%s_element" % (prefix, name)
|
else "%s_%s_element" % (prefix, name)
|
||||||
|
|
||||||
def getPrefixName(name, prefix):
|
def get_prefixe_name(name, prefix):
|
||||||
'''
|
'''
|
||||||
Description: Make name
|
Description: Make name
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -149,19 +149,19 @@ def getPrefixName(name, prefix):
|
|||||||
return "%s" % name
|
return "%s" % name
|
||||||
return "%s_%s" % (prefix, name)
|
return "%s_%s" % (prefix, name)
|
||||||
|
|
||||||
def getPrefixPointer(name, typ, prefix):
|
def get_prefixe_pointer(name, typ, prefix):
|
||||||
'''
|
'''
|
||||||
Description: Make pointer name
|
Description: Make pointer name
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
'''
|
'''
|
||||||
if typ != 'object' and typ != 'mapStringObject' and \
|
if typ != 'object' and typ != 'mapStringObject' and \
|
||||||
not validBasicMapName(typ):
|
not valid_basic_map_name(typ):
|
||||||
return ""
|
return ""
|
||||||
return '%s *' % makeBasicMapName(typ) if validBasicMapName(typ) \
|
return '%s *' % make_basic_map_name(typ) if valid_basic_map_name(typ) \
|
||||||
else "%s *" % getPrefixName(name, prefix)
|
else "%s *" % get_prefixe_name(name, prefix)
|
||||||
|
|
||||||
def judgeComplex(typ):
|
def judge_complex(typ):
|
||||||
'''
|
'''
|
||||||
Description: Check compound object
|
Description: Check compound object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -169,7 +169,7 @@ def judgeComplex(typ):
|
|||||||
'''
|
'''
|
||||||
return typ in ('object', 'array', 'mapStringObject')
|
return typ in ('object', 'array', 'mapStringObject')
|
||||||
|
|
||||||
def judgeDataType(typ):
|
def judge_data_type(typ):
|
||||||
'''
|
'''
|
||||||
Description: Check numeric type
|
Description: Check numeric type
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -180,7 +180,7 @@ def judgeDataType(typ):
|
|||||||
return True
|
return True
|
||||||
return typ in ("integer", "UID", "GID", "double")
|
return typ in ("integer", "UID", "GID", "double")
|
||||||
|
|
||||||
def judgeDataPointerType(typ):
|
def judge_data_pointer_type(typ):
|
||||||
'''
|
'''
|
||||||
Description: Check numeric pointer type
|
Description: Check numeric pointer type
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -190,7 +190,7 @@ def judgeDataPointerType(typ):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def obtainDataPointerType(typ):
|
def obtain_data_pointer_type(typ):
|
||||||
'''
|
'''
|
||||||
Description: Get numeric pointer type
|
Description: Get numeric pointer type
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -199,22 +199,22 @@ def obtainDataPointerType(typ):
|
|||||||
index = typ.find("Pointer")
|
index = typ.find("Pointer")
|
||||||
return typ[0:index] if index != -1 else ""
|
return typ[0:index] if index != -1 else ""
|
||||||
|
|
||||||
def obtainPointer(name, typ, prefix):
|
def obtain_pointer(name, typ, prefix):
|
||||||
'''
|
'''
|
||||||
Description: Obtain pointer string
|
Description: Obtain pointer string
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
'''
|
'''
|
||||||
ptr = getPrefixPointer(name, typ, prefix)
|
ptr = get_prefixe_pointer(name, typ, prefix)
|
||||||
if ptr != "":
|
if ptr != "":
|
||||||
return ptr
|
return ptr
|
||||||
|
|
||||||
return "char *" if typ == "string" else \
|
return "char *" if typ == "string" else \
|
||||||
("%s *" % typ if typ == "ArrayOfStrings" else "")
|
("%s *" % typ if typ == "ArrayOfStrings" else "")
|
||||||
|
|
||||||
class CombinationName(object):
|
class CombinateName(object):
|
||||||
'''
|
'''
|
||||||
Description: Store CombinationName information
|
Description: Store CombinateName information
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
'''
|
'''
|
||||||
@ -236,7 +236,7 @@ class CombinationName(object):
|
|||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
'''
|
'''
|
||||||
prefix_name = self.name + '_' if self.name != "" else ""
|
prefix_name = self.name + '_' if self.name != "" else ""
|
||||||
return CombinationName(prefix_name + leaf, leaf)
|
return CombinateName(prefix_name + leaf, leaf)
|
||||||
|
|
||||||
|
|
||||||
class Unite(object):
|
class Unite(object):
|
||||||
@ -253,9 +253,9 @@ class Unite(object):
|
|||||||
self.subtypobj = subtypobj
|
self.subtypobj = subtypobj
|
||||||
self.subtypname = subtypname
|
self.subtypname = subtypname
|
||||||
self.required = required
|
self.required = required
|
||||||
self.name = convertToCStyle(name.name.replace('.', '_'))
|
self.name = conv_to_c_style(name.name.replace('.', '_'))
|
||||||
self.origname = name.leaf or name.name
|
self.origname = name.leaf or name.name
|
||||||
self.fixname = convertToCStyle(self.origname.replace('.', '_'))
|
self.fixname = conv_to_c_style(self.origname.replace('.', '_'))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -297,7 +297,7 @@ class SchemaInfo(object):
|
|||||||
|
|
||||||
def __init__(self, name, header, source, prefix, filesdir, refs=None):
|
def __init__(self, name, header, source, prefix, filesdir, refs=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.fileprefix = convertToCStyle( \
|
self.fileprefix = conv_to_c_style( \
|
||||||
name.basename.replace('.', '_').replace('-', '_'))
|
name.basename.replace('.', '_').replace('-', '_'))
|
||||||
self.header = header
|
self.header = header
|
||||||
self.source = source
|
self.source = source
|
||||||
@ -311,3 +311,7 @@ class SchemaInfo(object):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.__repr__(self)
|
return self.__repr__(self)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -19,30 +19,31 @@ History: 2018-04-25 created
|
|||||||
import helpers
|
import helpers
|
||||||
|
|
||||||
|
|
||||||
def appendCCode(obj, c_file, prefix):
|
def append_c_code(obj, c_file, prefix):
|
||||||
"""
|
"""
|
||||||
Description: append c language code to file
|
Description: append c language code to file
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
parseJsonToC(obj, c_file, prefix)
|
parse_json_to_c(obj, c_file, prefix)
|
||||||
makeCFree(obj, c_file, prefix)
|
make_c_free(obj, c_file, prefix)
|
||||||
obtainCJson(obj, c_file, prefix)
|
get_c_json(obj, c_file, prefix)
|
||||||
|
|
||||||
def parseMapStringObject(obj, c_file, prefix, obj_typename):
|
|
||||||
|
def parse_map_string_obj(obj, c_file, prefix, obj_typename):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json map string object
|
Description: generate c language for parse json map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
child = obj.children[0]
|
child = obj.children[0]
|
||||||
if helpers.validBasicMapName(child.typ):
|
if helpers.valid_basic_map_name(child.typ):
|
||||||
childname = helpers.makeBasicMapName(child.typ)
|
childname = helpers.make_basic_map_name(child.typ)
|
||||||
else:
|
else:
|
||||||
if child.subtypname:
|
if child.subtypname:
|
||||||
childname = child.subtypname
|
childname = child.subtypname
|
||||||
else:
|
else:
|
||||||
childname = helpers.getPrefixName(child.name, prefix)
|
childname = helpers.get_prefixe_name(child.name, prefix)
|
||||||
c_file.write(' if (YAJL_GET_OBJECT(tree) != NULL && YAJL_GET_OBJECT(tree)->len > 0) {\n')
|
c_file.write(' if (YAJL_GET_OBJECT(tree) != NULL && YAJL_GET_OBJECT(tree)->len > 0) {\n')
|
||||||
c_file.write(' size_t i;\n')
|
c_file.write(' size_t i;\n')
|
||||||
c_file.write(' ret->len = YAJL_GET_OBJECT(tree)->len;\n')
|
c_file.write(' ret->len = YAJL_GET_OBJECT(tree)->len;\n')
|
||||||
@ -63,7 +64,8 @@ def parseMapStringObject(obj, c_file, prefix, obj_typename):
|
|||||||
c_file.write(' }\n')
|
c_file.write(' }\n')
|
||||||
c_file.write(' }\n')
|
c_file.write(' }\n')
|
||||||
|
|
||||||
def parseObjectType(obj, c_file, prefix, obj_typename):
|
|
||||||
|
def parse_obj_type(obj, c_file, prefix, obj_typename):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse object type
|
Description: generate c language for parse object type
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -71,34 +73,34 @@ def parseObjectType(obj, c_file, prefix, obj_typename):
|
|||||||
"""
|
"""
|
||||||
if obj.typ == 'string':
|
if obj.typ == 'string':
|
||||||
c_file.write(' {\n')
|
c_file.write(' {\n')
|
||||||
readValueGenerator(c_file, 2, 'get_val(tree, "%s", yajl_t_string)' % obj.origname, \
|
read_val_generator(c_file, 2, 'get_val(tree, "%s", yajl_t_string)' % obj.origname, \
|
||||||
"ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename)
|
"ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename)
|
||||||
c_file.write(' }\n')
|
c_file.write(' }\n')
|
||||||
elif helpers.judgeDataType(obj.typ):
|
elif helpers.judge_data_type(obj.typ):
|
||||||
c_file.write(' {\n')
|
c_file.write(' {\n')
|
||||||
readValueGenerator(c_file, 2, 'get_val(tree, "%s", yajl_t_number)' % obj.origname, \
|
read_val_generator(c_file, 2, 'get_val(tree, "%s", yajl_t_number)' % obj.origname, \
|
||||||
"ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename)
|
"ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename)
|
||||||
c_file.write(' }\n')
|
c_file.write(' }\n')
|
||||||
elif helpers.judgeDataPointerType(obj.typ):
|
elif helpers.judge_data_pointer_type(obj.typ):
|
||||||
c_file.write(' {\n')
|
c_file.write(' {\n')
|
||||||
readValueGenerator(c_file, 2, 'get_val(tree, "%s", yajl_t_number)' % obj.origname, \
|
read_val_generator(c_file, 2, 'get_val(tree, "%s", yajl_t_number)' % obj.origname, \
|
||||||
"ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename)
|
"ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename)
|
||||||
c_file.write(' }\n')
|
c_file.write(' }\n')
|
||||||
if obj.typ == 'boolean':
|
if obj.typ == 'boolean':
|
||||||
c_file.write(' {\n')
|
c_file.write(' {\n')
|
||||||
readValueGenerator(c_file, 2, 'get_val(tree, "%s", yajl_t_true)' % obj.origname, \
|
read_val_generator(c_file, 2, 'get_val(tree, "%s", yajl_t_true)' % obj.origname, \
|
||||||
"ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename)
|
"ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename)
|
||||||
c_file.write(' }\n')
|
c_file.write(' }\n')
|
||||||
if obj.typ == 'booleanPointer':
|
if obj.typ == 'booleanPointer':
|
||||||
c_file.write(' {\n')
|
c_file.write(' {\n')
|
||||||
readValueGenerator(c_file, 2, 'get_val(tree, "%s", yajl_t_true)' % obj.origname, \
|
read_val_generator(c_file, 2, 'get_val(tree, "%s", yajl_t_true)' % obj.origname, \
|
||||||
"ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename)
|
"ret->%s" % obj.fixname, obj.typ, obj.origname, obj_typename)
|
||||||
c_file.write(' }\n')
|
c_file.write(' }\n')
|
||||||
elif obj.typ == 'object' or obj.typ == 'mapStringObject':
|
elif obj.typ == 'object' or obj.typ == 'mapStringObject':
|
||||||
if obj.subtypname is not None:
|
if obj.subtypname is not None:
|
||||||
typename = obj.subtypname
|
typename = obj.subtypname
|
||||||
else:
|
else:
|
||||||
typename = helpers.getPrefixName(obj.name, prefix)
|
typename = helpers.get_prefixe_name(obj.name, prefix)
|
||||||
c_file.write(
|
c_file.write(
|
||||||
' ret->%s = make_%s(get_val(tree, "%s", yajl_t_object), ctx, err);\n' \
|
' ret->%s = make_%s(get_val(tree, "%s", yajl_t_object), ctx, err);\n' \
|
||||||
% (obj.fixname, typename, obj.origname))
|
% (obj.fixname, typename, obj.origname))
|
||||||
@ -110,7 +112,7 @@ def parseObjectType(obj, c_file, prefix, obj_typename):
|
|||||||
if obj.subtypname:
|
if obj.subtypname:
|
||||||
typename = obj.subtypname
|
typename = obj.subtypname
|
||||||
else:
|
else:
|
||||||
typename = helpers.getNameSubstr(obj.name, prefix)
|
typename = helpers.get_name_substr(obj.name, prefix)
|
||||||
c_file.write(' {\n')
|
c_file.write(' {\n')
|
||||||
c_file.write(' yajl_val tmp = get_val(tree, "%s", yajl_t_array);\n' \
|
c_file.write(' yajl_val tmp = get_val(tree, "%s", yajl_t_array);\n' \
|
||||||
% (obj.origname))
|
% (obj.origname))
|
||||||
@ -155,18 +157,18 @@ def parseObjectType(obj, c_file, prefix, obj_typename):
|
|||||||
' ret->%s = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) *' \
|
' ret->%s = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) *' \
|
||||||
' sizeof(*ret->%s));\n' % (obj.fixname, obj.fixname))
|
' sizeof(*ret->%s));\n' % (obj.fixname, obj.fixname))
|
||||||
c_file.write(' for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) {\n')
|
c_file.write(' for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) {\n')
|
||||||
readValueGenerator(c_file, 4, 'YAJL_GET_ARRAY(tmp)->values[i]', \
|
read_val_generator(c_file, 4, 'YAJL_GET_ARRAY(tmp)->values[i]', \
|
||||||
"ret->%s[i]" % obj.fixname, obj.subtyp, obj.origname, obj_typename)
|
"ret->%s[i]" % obj.fixname, obj.subtyp, obj.origname, obj_typename)
|
||||||
c_file.write(' }\n')
|
c_file.write(' }\n')
|
||||||
c_file.write(' }\n')
|
c_file.write(' }\n')
|
||||||
c_file.write(' }\n')
|
c_file.write(' }\n')
|
||||||
elif helpers.validBasicMapName(obj.typ):
|
elif helpers.valid_basic_map_name(obj.typ):
|
||||||
c_file.write(' {\n')
|
c_file.write(' {\n')
|
||||||
c_file.write(' yajl_val tmp = get_val(tree, "%s", yajl_t_object);\n' \
|
c_file.write(' yajl_val tmp = get_val(tree, "%s", yajl_t_object);\n' \
|
||||||
% (obj.origname))
|
% (obj.origname))
|
||||||
c_file.write(' if (tmp != NULL) {\n')
|
c_file.write(' if (tmp != NULL) {\n')
|
||||||
c_file.write(' ret->%s = make_%s(tmp, ctx, err);\n' \
|
c_file.write(' ret->%s = make_%s(tmp, ctx, err);\n' \
|
||||||
% (obj.fixname, helpers.makeBasicMapName(obj.typ)))
|
% (obj.fixname, helpers.make_basic_map_name(obj.typ)))
|
||||||
c_file.write(' if (ret->%s == NULL) {\n' % (obj.fixname))
|
c_file.write(' if (ret->%s == NULL) {\n' % (obj.fixname))
|
||||||
c_file.write(' char *new_error = NULL;\n')
|
c_file.write(' char *new_error = NULL;\n')
|
||||||
c_file.write(" if (asprintf(&new_error, \"Value error for key" \
|
c_file.write(" if (asprintf(&new_error, \"Value error for key" \
|
||||||
@ -182,20 +184,19 @@ def parseObjectType(obj, c_file, prefix, obj_typename):
|
|||||||
c_file.write(' }\n')
|
c_file.write(' }\n')
|
||||||
c_file.write(' }\n')
|
c_file.write(' }\n')
|
||||||
|
|
||||||
def parseObjectOrArrayObject(obj, c_file, prefix, obj_typename):
|
def parse_obj_arr_obj(obj, c_file, prefix, obj_typename):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse object or array object
|
Description: generate c language for parse object or array object
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
nodes = obj.children if obj.typ == 'object' else obj.subtypobj
|
nodes = obj.children if obj.typ == 'object' else obj.subtypobj
|
||||||
|
|
||||||
required_to_check = []
|
required_to_check = []
|
||||||
for i in nodes or []:
|
for i in nodes or []:
|
||||||
if obj.required and i.origname in obj.required and \
|
if obj.required and i.origname in obj.required and \
|
||||||
not helpers.judgeDataType(i.typ) and i.typ != 'boolean':
|
not helpers.judge_data_type(i.typ) and i.typ != 'boolean':
|
||||||
required_to_check.append(i)
|
required_to_check.append(i)
|
||||||
parseObjectType(i, c_file, prefix, obj_typename)
|
parse_obj_type(i, c_file, prefix, obj_typename)
|
||||||
|
|
||||||
for i in required_to_check:
|
for i in required_to_check:
|
||||||
c_file.write(' if (ret->%s == NULL) {\n' % i.fixname)
|
c_file.write(' if (ret->%s == NULL) {\n' % i.fixname)
|
||||||
@ -222,26 +223,24 @@ def parseObjectOrArrayObject(obj, c_file, prefix, obj_typename):
|
|||||||
}
|
}
|
||||||
""" % condition)
|
""" % condition)
|
||||||
|
|
||||||
def parseJsonToC(obj, c_file, prefix):
|
|
||||||
|
def parse_json_to_c(obj, c_file, prefix):
|
||||||
"""
|
"""
|
||||||
Description: generate c language for parse json file
|
Description: generate c language for parse json file
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
if not helpers.judgeComplex(obj.typ):
|
if not helpers.judge_complex(obj.typ):
|
||||||
return
|
return
|
||||||
|
|
||||||
if obj.typ == 'object' or obj.typ == 'mapStringObject':
|
if obj.typ == 'object' or obj.typ == 'mapStringObject':
|
||||||
if obj.subtypname:
|
if obj.subtypname:
|
||||||
return
|
return
|
||||||
obj_typename = typename = helpers.getPrefixName(obj.name, prefix)
|
obj_typename = typename = helpers.get_prefixe_name(obj.name, prefix)
|
||||||
|
|
||||||
if obj.typ == 'array':
|
if obj.typ == 'array':
|
||||||
obj_typename = typename = helpers.getNameSubstr(obj.name, prefix)
|
obj_typename = typename = helpers.get_name_substr(obj.name, prefix)
|
||||||
objs = obj.subtypobj
|
objs = obj.subtypobj
|
||||||
if objs is None or obj.subtypname:
|
if objs is None or obj.subtypname:
|
||||||
return
|
return
|
||||||
|
|
||||||
c_file.write("%s *make_%s(yajl_val tree, const struct parser_context *ctx, "\
|
c_file.write("%s *make_%s(yajl_val tree, const struct parser_context *ctx, "\
|
||||||
"parser_error *err) {\n" % (typename, typename))
|
"parser_error *err) {\n" % (typename, typename))
|
||||||
c_file.write(" %s *ret = NULL;\n" % (typename))
|
c_file.write(" %s *ret = NULL;\n" % (typename))
|
||||||
@ -249,31 +248,29 @@ def parseJsonToC(obj, c_file, prefix):
|
|||||||
c_file.write(" if (tree == NULL)\n")
|
c_file.write(" if (tree == NULL)\n")
|
||||||
c_file.write(" return ret;\n")
|
c_file.write(" return ret;\n")
|
||||||
c_file.write(" ret = safe_malloc(sizeof(*ret));\n")
|
c_file.write(" ret = safe_malloc(sizeof(*ret));\n")
|
||||||
|
|
||||||
if obj.typ == 'mapStringObject':
|
if obj.typ == 'mapStringObject':
|
||||||
parseMapStringObject(obj, c_file, prefix, obj_typename)
|
parse_map_string_obj(obj, c_file, prefix, obj_typename)
|
||||||
|
|
||||||
if obj.typ == 'object' or (obj.typ == 'array' and obj.subtypobj):
|
if obj.typ == 'object' or (obj.typ == 'array' and obj.subtypobj):
|
||||||
parseObjectOrArrayObject(obj, c_file, prefix, obj_typename)
|
parse_obj_arr_obj(obj, c_file, prefix, obj_typename)
|
||||||
|
|
||||||
c_file.write(' return ret;\n')
|
c_file.write(' return ret;\n')
|
||||||
c_file.write("}\n\n")
|
c_file.write("}\n\n")
|
||||||
|
|
||||||
|
|
||||||
def obtainMapStringObject(obj, c_file, prefix):
|
def get_map_string_obj(obj, c_file, prefix):
|
||||||
"""
|
"""
|
||||||
Description: c language generate map string object
|
Description: c language generate map string object
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
child = obj.children[0]
|
child = obj.children[0]
|
||||||
if helpers.validBasicMapName(child.typ):
|
if helpers.valid_basic_map_name(child.typ):
|
||||||
childname = helpers.makeBasicMapName(child.typ)
|
childname = helpers.make_basic_map_name(child.typ)
|
||||||
else:
|
else:
|
||||||
if child.subtypname:
|
if child.subtypname:
|
||||||
childname = child.subtypname
|
childname = child.subtypname
|
||||||
else:
|
else:
|
||||||
childname = helpers.getPrefixName(child.name, prefix)
|
childname = helpers.get_prefixe_name(child.name, prefix)
|
||||||
c_file.write(' size_t len = 0, i;\n')
|
c_file.write(' size_t len = 0, i;\n')
|
||||||
c_file.write(" if (ptr != NULL)\n")
|
c_file.write(" if (ptr != NULL)\n")
|
||||||
c_file.write(" len = ptr->len;\n")
|
c_file.write(" len = ptr->len;\n")
|
||||||
@ -286,7 +283,8 @@ def obtainMapStringObject(obj, c_file, prefix):
|
|||||||
% child.fixname)
|
% child.fixname)
|
||||||
c_file.write(' for (i = 0; i < len; i++) {\n')
|
c_file.write(' for (i = 0; i < len; i++) {\n')
|
||||||
c_file.write(' char *str = ptr->keys[i] ? ptr->keys[i] : "";\n')
|
c_file.write(' char *str = ptr->keys[i] ? ptr->keys[i] : "";\n')
|
||||||
c_file.write(' stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)str, strlen(str));\n')
|
c_file.write(' stat = yajl_gen_string((yajl_gen)g, \
|
||||||
|
(const unsigned char *)str, strlen(str));\n')
|
||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
c_file.write(' stat = gen_%s(g, ptr->%s[i], ctx, err);\n' \
|
c_file.write(' stat = gen_%s(g, ptr->%s[i], ctx, err);\n' \
|
||||||
@ -301,7 +299,8 @@ def obtainMapStringObject(obj, c_file, prefix):
|
|||||||
c_file.write(" if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n")
|
c_file.write(" if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n")
|
||||||
c_file.write(' yajl_gen_config(g, yajl_gen_beautify, 1);\n')
|
c_file.write(' yajl_gen_config(g, yajl_gen_beautify, 1);\n')
|
||||||
|
|
||||||
def obtainObjectOrArrayObject(obj, c_file, prefix):
|
|
||||||
|
def get_obj_arr_obj(obj, c_file, prefix):
|
||||||
"""
|
"""
|
||||||
Description: c language generate object or array object
|
Description: c language generate object or array object
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -311,17 +310,16 @@ def obtainObjectOrArrayObject(obj, c_file, prefix):
|
|||||||
c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \
|
c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \
|
||||||
' (ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
|
' (ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
|
||||||
c_file.write(' char *str = "";\n')
|
c_file.write(' char *str = "";\n')
|
||||||
c_file.write(' stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)("%s"), strlen("%s"));\n' \
|
c_file.write(' stat = yajl_gen_string((yajl_gen)g, \
|
||||||
% (obj.origname, obj.origname))
|
(const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
|
||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
c_file.write(" if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname)
|
c_file.write(" if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname)
|
||||||
c_file.write(" str = ptr->%s;\n" % obj.fixname)
|
c_file.write(" str = ptr->%s;\n" % obj.fixname)
|
||||||
c_file.write(" }\n")
|
c_file.write(" }\n")
|
||||||
jsonValueGenerator(c_file, 2, "str", 'g', 'ctx', obj.typ)
|
json_value_generator(c_file, 2, "str", 'g', 'ctx', obj.typ)
|
||||||
c_file.write(" }\n")
|
c_file.write(" }\n")
|
||||||
|
elif helpers.judge_data_type(obj.typ):
|
||||||
elif helpers.judgeDataType(obj.typ):
|
|
||||||
c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \
|
c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \
|
||||||
' (ptr != NULL && ptr->%s)) {\n' % obj.fixname)
|
' (ptr != NULL && ptr->%s)) {\n' % obj.fixname)
|
||||||
if obj.typ == 'double':
|
if obj.typ == 'double':
|
||||||
@ -331,55 +329,53 @@ def obtainObjectOrArrayObject(obj, c_file, prefix):
|
|||||||
else:
|
else:
|
||||||
numtyp = 'long long int'
|
numtyp = 'long long int'
|
||||||
c_file.write(' %s num = 0;\n' % numtyp)
|
c_file.write(' %s num = 0;\n' % numtyp)
|
||||||
c_file.write(' stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)("%s"), strlen("%s"));\n' \
|
c_file.write(' stat = yajl_gen_string((yajl_gen)g, \
|
||||||
% (obj.origname, obj.origname))
|
(const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
|
||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
c_file.write(" if (ptr != NULL && ptr->%s) {\n" % obj.fixname)
|
c_file.write(" if (ptr != NULL && ptr->%s) {\n" % obj.fixname)
|
||||||
c_file.write(" num = (%s)ptr->%s;\n" % (numtyp, obj.fixname))
|
c_file.write(" num = (%s)ptr->%s;\n" % (numtyp, obj.fixname))
|
||||||
c_file.write(" }\n")
|
c_file.write(" }\n")
|
||||||
jsonValueGenerator(c_file, 2, "num", 'g', 'ctx', obj.typ)
|
json_value_generator(c_file, 2, "num", 'g', 'ctx', obj.typ)
|
||||||
c_file.write(" }\n")
|
c_file.write(" }\n")
|
||||||
|
elif helpers.judge_data_pointer_type(obj.typ):
|
||||||
elif helpers.judgeDataPointerType(obj.typ):
|
|
||||||
c_file.write(' if ((ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
|
c_file.write(' if ((ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
|
||||||
numtyp = helpers.obtainDataPointerType(obj.typ)
|
numtyp = helpers.obtain_data_pointer_type(obj.typ)
|
||||||
if numtyp == "":
|
if numtyp == "":
|
||||||
return
|
return
|
||||||
c_file.write(' %s num = 0;\n' % helpers.getMapCTypes(numtyp))
|
c_file.write(' %s num = 0;\n' % helpers.get_map_c_types(numtyp))
|
||||||
c_file.write(' stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)("%s"), strlen("%s"));\n' \
|
c_file.write(' stat = yajl_gen_string((yajl_gen)g, \
|
||||||
% (obj.origname, obj.origname))
|
(const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
|
||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
c_file.write(" if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname)
|
c_file.write(" if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname)
|
||||||
c_file.write(" num = (%s)*(ptr->%s);\n" \
|
c_file.write(" num = (%s)*(ptr->%s);\n" \
|
||||||
% (helpers.getMapCTypes(numtyp), obj.fixname))
|
% (helpers.get_map_c_types(numtyp), obj.fixname))
|
||||||
c_file.write(" }\n")
|
c_file.write(" }\n")
|
||||||
jsonValueGenerator(c_file, 2, "num", 'g', 'ctx', numtyp)
|
json_value_generator(c_file, 2, "num", 'g', 'ctx', numtyp)
|
||||||
c_file.write(" }\n")
|
c_file.write(" }\n")
|
||||||
|
|
||||||
elif obj.typ == 'boolean':
|
elif obj.typ == 'boolean':
|
||||||
c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \
|
c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \
|
||||||
' (ptr != NULL && ptr->%s)) {\n' % obj.fixname)
|
' (ptr != NULL && ptr->%s)) {\n' % obj.fixname)
|
||||||
c_file.write(' bool b = false;\n')
|
c_file.write(' bool b = false;\n')
|
||||||
c_file.write(' stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)("%s"), strlen("%s"));\n' \
|
c_file.write(' stat = yajl_gen_string((yajl_gen)g, \
|
||||||
% (obj.origname, obj.origname))
|
(const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
|
||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
c_file.write(" if (ptr != NULL && ptr->%s) {\n" % obj.fixname)
|
c_file.write(" if (ptr != NULL && ptr->%s) {\n" % obj.fixname)
|
||||||
c_file.write(" b = ptr->%s;\n" % obj.fixname)
|
c_file.write(" b = ptr->%s;\n" % obj.fixname)
|
||||||
c_file.write(" }\n")
|
c_file.write(" }\n")
|
||||||
jsonValueGenerator(c_file, 2, "b", 'g', 'ctx', obj.typ)
|
json_value_generator(c_file, 2, "b", 'g', 'ctx', obj.typ)
|
||||||
c_file.write(" }\n")
|
c_file.write(" }\n")
|
||||||
elif obj.typ == 'object' or obj.typ == 'mapStringObject':
|
elif obj.typ == 'object' or obj.typ == 'mapStringObject':
|
||||||
if obj.subtypname:
|
if obj.subtypname:
|
||||||
typename = obj.subtypname
|
typename = obj.subtypname
|
||||||
else:
|
else:
|
||||||
typename = helpers.getPrefixName(obj.name, prefix)
|
typename = helpers.get_prefixe_name(obj.name, prefix)
|
||||||
c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \
|
c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) ||' \
|
||||||
' (ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
|
' (ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
|
||||||
c_file.write(' stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)("%s"), strlen("%s"));\n' \
|
c_file.write(' stat = yajl_gen_string((yajl_gen)g, \
|
||||||
% (obj.origname, obj.origname))
|
(const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
|
||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
c_file.write(' stat = gen_%s(g, ptr != NULL ? ptr->%s : NULL, ctx, err);\n' \
|
c_file.write(' stat = gen_%s(g, ptr != NULL ? ptr->%s : NULL, ctx, err);\n' \
|
||||||
@ -387,17 +383,16 @@ def obtainObjectOrArrayObject(obj, c_file, prefix):
|
|||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
c_file.write(" }\n")
|
c_file.write(" }\n")
|
||||||
|
|
||||||
elif obj.typ == 'array' and (obj.subtypobj or obj.subtyp == 'object'):
|
elif obj.typ == 'array' and (obj.subtypobj or obj.subtyp == 'object'):
|
||||||
if obj.subtypname:
|
if obj.subtypname:
|
||||||
typename = obj.subtypname
|
typename = obj.subtypname
|
||||||
else:
|
else:
|
||||||
typename = helpers.getNameSubstr(obj.name, prefix)
|
typename = helpers.get_name_substr(obj.name, prefix)
|
||||||
c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) || ' \
|
c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) || ' \
|
||||||
'(ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
|
'(ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
|
||||||
c_file.write(' size_t len = 0, i;\n')
|
c_file.write(' size_t len = 0, i;\n')
|
||||||
c_file.write(' stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)("%s"), strlen("%s"));\n' \
|
c_file.write(' stat = yajl_gen_string((yajl_gen)g, \
|
||||||
% (obj.origname, obj.origname))
|
(const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
|
||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
c_file.write(" if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname)
|
c_file.write(" if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname)
|
||||||
@ -426,15 +421,16 @@ def obtainObjectOrArrayObject(obj, c_file, prefix):
|
|||||||
% (obj.fixname, obj.fixname))
|
% (obj.fixname, obj.fixname))
|
||||||
c_file.write(' const char *str = "";\n')
|
c_file.write(' const char *str = "";\n')
|
||||||
c_file.write(' size_t len = 0;\n')
|
c_file.write(' size_t len = 0;\n')
|
||||||
c_file.write(' stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)("%s"), strlen("%s"));\n' \
|
c_file.write(' stat = yajl_gen_string((yajl_gen)g, \
|
||||||
% (obj.origname, obj.origname))
|
(const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
|
||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
c_file.write(" if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname)
|
c_file.write(" if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname)
|
||||||
c_file.write(" str = (const char *)ptr->%s;\n" % obj.fixname)
|
c_file.write(" str = (const char *)ptr->%s;\n" % obj.fixname)
|
||||||
c_file.write(" len = ptr->%s_len;\n" % obj.fixname)
|
c_file.write(" len = ptr->%s_len;\n" % obj.fixname)
|
||||||
c_file.write(" }\n")
|
c_file.write(" }\n")
|
||||||
c_file.write(' stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)str, len);\n')
|
c_file.write(' stat = yajl_gen_string((yajl_gen)g, \
|
||||||
|
(const unsigned char *)str, len);\n')
|
||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
c_file.write(" }\n")
|
c_file.write(" }\n")
|
||||||
@ -442,8 +438,8 @@ def obtainObjectOrArrayObject(obj, c_file, prefix):
|
|||||||
c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) || ' \
|
c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) || ' \
|
||||||
'(ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
|
'(ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
|
||||||
c_file.write(' size_t len = 0, i;\n')
|
c_file.write(' size_t len = 0, i;\n')
|
||||||
c_file.write(' stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)("%s"), strlen("%s"));\n' \
|
c_file.write(' stat = yajl_gen_string((yajl_gen)g, \
|
||||||
% (obj.origname, obj.origname))
|
(const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
|
||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
c_file.write(" if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname)
|
c_file.write(" if (ptr != NULL && ptr->%s != NULL) {\n" % obj.fixname)
|
||||||
@ -455,7 +451,7 @@ def obtainObjectOrArrayObject(obj, c_file, prefix):
|
|||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
c_file.write(' for (i = 0; i < len; i++) {\n')
|
c_file.write(' for (i = 0; i < len; i++) {\n')
|
||||||
jsonValueGenerator(c_file, 3, "ptr->%s[i]" % obj.fixname, 'g', 'ctx', obj.subtyp)
|
json_value_generator(c_file, 3, "ptr->%s[i]" % obj.fixname, 'g', 'ctx', obj.subtyp)
|
||||||
c_file.write(' }\n')
|
c_file.write(' }\n')
|
||||||
c_file.write(' stat = yajl_gen_array_close((yajl_gen)g);\n')
|
c_file.write(' stat = yajl_gen_array_close((yajl_gen)g);\n')
|
||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
@ -463,44 +459,42 @@ def obtainObjectOrArrayObject(obj, c_file, prefix):
|
|||||||
c_file.write(" if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n")
|
c_file.write(" if (!len && !(ctx->options & OPT_GEN_SIMPLIFY))\n")
|
||||||
c_file.write(' yajl_gen_config(g, yajl_gen_beautify, 1);\n')
|
c_file.write(' yajl_gen_config(g, yajl_gen_beautify, 1);\n')
|
||||||
c_file.write(' }\n')
|
c_file.write(' }\n')
|
||||||
|
elif helpers.valid_basic_map_name(obj.typ):
|
||||||
elif helpers.validBasicMapName(obj.typ):
|
|
||||||
c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) || ' \
|
c_file.write(' if ((ctx->options & OPT_GEN_KAY_VALUE) || ' \
|
||||||
'(ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
|
'(ptr != NULL && ptr->%s != NULL)) {\n' % obj.fixname)
|
||||||
c_file.write(' stat = yajl_gen_string((yajl_gen)g, (const unsigned char *)("%s"), strlen("%s"));\n' \
|
c_file.write(' stat = yajl_gen_string((yajl_gen)g, \
|
||||||
% (obj.origname, obj.origname))
|
(const unsigned char *)("%s"), strlen("%s"));\n' % (obj.origname, obj.origname))
|
||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
c_file.write(' stat = gen_%s(g, ptr ? ptr->%s : NULL, ctx, err);\n' \
|
c_file.write(' stat = gen_%s(g, ptr ? ptr->%s : NULL, ctx, err);\n' \
|
||||||
% (helpers.makeBasicMapName(obj.typ), obj.fixname))
|
% (helpers.make_basic_map_name(obj.typ), obj.fixname))
|
||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
c_file.write(" }\n")
|
c_file.write(" }\n")
|
||||||
|
|
||||||
def obtainCJson(obj, c_file, prefix):
|
|
||||||
|
def get_c_json(obj, c_file, prefix):
|
||||||
"""
|
"""
|
||||||
Description: c language generate json file
|
Description: c language generate json file
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
if not helpers.judgeComplex(obj.typ) or obj.subtypname:
|
if not helpers.judge_complex(obj.typ) or obj.subtypname:
|
||||||
return
|
return
|
||||||
if obj.typ == 'object' or obj.typ == 'mapStringObject':
|
if obj.typ == 'object' or obj.typ == 'mapStringObject':
|
||||||
obj_typename = typename = helpers.getPrefixName(obj.name, prefix)
|
typename = helpers.get_prefixe_name(obj.name, prefix)
|
||||||
elif obj.typ == 'array':
|
elif obj.typ == 'array':
|
||||||
obj_typename = typename = helpers.getNameSubstr(obj.name, prefix)
|
typename = helpers.get_name_substr(obj.name, prefix)
|
||||||
objs = obj.subtypobj
|
objs = obj.subtypobj
|
||||||
if objs is None:
|
if objs is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
c_file.write(
|
c_file.write(
|
||||||
"yajl_gen_status gen_%s(yajl_gen g, const %s *ptr, const struct parser_context " \
|
"yajl_gen_status gen_%s(yajl_gen g, const %s *ptr, const struct parser_context " \
|
||||||
"*ctx, parser_error *err) {\n" % (typename, typename))
|
"*ctx, parser_error *err) {\n" % (typename, typename))
|
||||||
c_file.write(" yajl_gen_status stat = yajl_gen_status_ok;\n")
|
c_file.write(" yajl_gen_status stat = yajl_gen_status_ok;\n")
|
||||||
c_file.write(" *err = 0;\n")
|
c_file.write(" *err = 0;\n")
|
||||||
|
|
||||||
if obj.typ == 'mapStringObject':
|
if obj.typ == 'mapStringObject':
|
||||||
obtainMapStringObject(obj, c_file, prefix)
|
get_map_string_obj(obj, c_file, prefix)
|
||||||
elif obj.typ == 'object' or (obj.typ == 'array' and obj.subtypobj):
|
elif obj.typ == 'object' or (obj.typ == 'array' and obj.subtypobj):
|
||||||
nodes = obj.children if obj.typ == 'object' else obj.subtypobj
|
nodes = obj.children if obj.typ == 'object' else obj.subtypobj
|
||||||
if nodes is None:
|
if nodes is None:
|
||||||
@ -510,10 +504,8 @@ def obtainCJson(obj, c_file, prefix):
|
|||||||
c_file.write(" stat = yajl_gen_map_open((yajl_gen)g);\n")
|
c_file.write(" stat = yajl_gen_map_open((yajl_gen)g);\n")
|
||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
|
|
||||||
for i in nodes or []:
|
for i in nodes or []:
|
||||||
obtainObjectOrArrayObject(i, c_file, prefix)
|
get_obj_arr_obj(i, c_file, prefix)
|
||||||
|
|
||||||
c_file.write(" stat = yajl_gen_map_close((yajl_gen)g);\n")
|
c_file.write(" stat = yajl_gen_map_close((yajl_gen)g);\n")
|
||||||
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
c_file.write(" if (yajl_gen_status_ok != stat)\n")
|
||||||
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
c_file.write(" GEN_SET_ERROR_AND_RETURN(stat, err);\n")
|
||||||
@ -524,17 +516,17 @@ def obtainCJson(obj, c_file, prefix):
|
|||||||
c_file.write("}\n\n")
|
c_file.write("}\n\n")
|
||||||
|
|
||||||
|
|
||||||
def readValueGenerator(c_file, level, src, dest, typ, keyname, obj_typename):
|
def read_val_generator(c_file, level, src, dest, typ, keyname, obj_typename):
|
||||||
"""
|
"""
|
||||||
Description: read value generateor
|
Description: read value generateor
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
if helpers.validBasicMapName(typ):
|
if helpers.valid_basic_map_name(typ):
|
||||||
c_file.write('%syajl_val val = %s;\n' % (' ' * level, src))
|
c_file.write('%syajl_val val = %s;\n' % (' ' * level, src))
|
||||||
c_file.write('%sif (val != NULL) {\n' % (' ' * level))
|
c_file.write('%sif (val != NULL) {\n' % (' ' * level))
|
||||||
c_file.write('%s%s = make_%s(val, ctx, err);\n' \
|
c_file.write('%s%s = make_%s(val, ctx, err);\n' \
|
||||||
% (' ' * (level + 1), dest, helpers.makeBasicMapName(typ)))
|
% (' ' * (level + 1), dest, helpers.make_basic_map_name(typ)))
|
||||||
c_file.write('%sif (%s == NULL) {\n' % (' ' * (level + 1), dest))
|
c_file.write('%sif (%s == NULL) {\n' % (' ' * (level + 1), dest))
|
||||||
c_file.write('%s char *new_error = NULL;\n' % (' ' * (level + 1)))
|
c_file.write('%s char *new_error = NULL;\n' % (' ' * (level + 1)))
|
||||||
c_file.write("%s if (asprintf(&new_error, \"Value error for key" \
|
c_file.write("%s if (asprintf(&new_error, \"Value error for key" \
|
||||||
@ -555,7 +547,7 @@ def readValueGenerator(c_file, level, src, dest, typ, keyname, obj_typename):
|
|||||||
c_file.write('%schar *str = YAJL_GET_STRING(val);\n' % (' ' * (level + 1)))
|
c_file.write('%schar *str = YAJL_GET_STRING(val);\n' % (' ' * (level + 1)))
|
||||||
c_file.write('%s%s = safe_strdup(str ? str : "");\n' % (' ' * (level + 1), dest))
|
c_file.write('%s%s = safe_strdup(str ? str : "");\n' % (' ' * (level + 1), dest))
|
||||||
c_file.write('%s}\n' % (' ' * level))
|
c_file.write('%s}\n' % (' ' * level))
|
||||||
elif helpers.judgeDataType(typ):
|
elif helpers.judge_data_type(typ):
|
||||||
c_file.write('%syajl_val val = %s;\n' % (' ' * (level), src))
|
c_file.write('%syajl_val val = %s;\n' % (' ' * (level), src))
|
||||||
c_file.write('%sif (val != NULL) {\n' % (' ' * (level)))
|
c_file.write('%sif (val != NULL) {\n' % (' ' * (level)))
|
||||||
if typ.startswith("uint") or \
|
if typ.startswith("uint") or \
|
||||||
@ -578,14 +570,14 @@ def readValueGenerator(c_file, level, src, dest, typ, keyname, obj_typename):
|
|||||||
c_file.write('%s return NULL;\n' % (' ' * (level + 1)))
|
c_file.write('%s return NULL;\n' % (' ' * (level + 1)))
|
||||||
c_file.write('%s}\n' % (' ' * (level + 1)))
|
c_file.write('%s}\n' % (' ' * (level + 1)))
|
||||||
c_file.write('%s}\n' % (' ' * (level)))
|
c_file.write('%s}\n' % (' ' * (level)))
|
||||||
elif helpers.judgeDataPointerType(typ):
|
elif helpers.judge_data_pointer_type(typ):
|
||||||
num_type = helpers.obtainDataPointerType(typ)
|
num_type = helpers.obtain_data_pointer_type(typ)
|
||||||
if num_type == "":
|
if num_type == "":
|
||||||
return
|
return
|
||||||
c_file.write('%syajl_val val = %s;\n' % (' ' * (level), src))
|
c_file.write('%syajl_val val = %s;\n' % (' ' * (level), src))
|
||||||
c_file.write('%sif (val != NULL) {\n' % (' ' * (level)))
|
c_file.write('%sif (val != NULL) {\n' % (' ' * (level)))
|
||||||
c_file.write('%s%s = safe_malloc(sizeof(%s));\n' %
|
c_file.write('%s%s = safe_malloc(sizeof(%s));\n' %
|
||||||
(' ' * (level + 1), dest, helpers.getMapCTypes(num_type)))
|
(' ' * (level + 1), dest, helpers.get_map_c_types(num_type)))
|
||||||
c_file.write('%sint invalid = common_safe_%s(YAJL_GET_NUMBER(val), %s);\n' \
|
c_file.write('%sint invalid = common_safe_%s(YAJL_GET_NUMBER(val), %s);\n' \
|
||||||
% (' ' * (level + 1), num_type, dest))
|
% (' ' * (level + 1), num_type, dest))
|
||||||
c_file.write('%sif (invalid) {\n' % (' ' * (level + 1)))
|
c_file.write('%sif (invalid) {\n' % (' ' * (level + 1)))
|
||||||
@ -617,76 +609,147 @@ def readValueGenerator(c_file, level, src, dest, typ, keyname, obj_typename):
|
|||||||
c_file.write('%s}\n' % (' ' * (level)))
|
c_file.write('%s}\n' % (' ' * (level)))
|
||||||
|
|
||||||
|
|
||||||
def jsonValueGenerator(c_file, level, src, dst, ptx, typ):
|
def json_value_generator(c_file, level, src, dst, ptx, typ):
|
||||||
"""
|
"""
|
||||||
Description: json value generateor
|
Description: json value generateor
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
if helpers.validBasicMapName(typ):
|
if helpers.valid_basic_map_name(typ):
|
||||||
c_file.write('%sstat = gen_%s(%s, %s, %s, err);\n' \
|
c_file.write('%sstat = gen_%s(%s, %s, %s, err);\n' \
|
||||||
% (' ' * (level), helpers.makeBasicMapName(typ), dst, src, ptx))
|
% (' ' * (level), helpers.make_basic_map_name(typ), dst, src, ptx))
|
||||||
c_file.write("%sif (yajl_gen_status_ok != stat)\n" % (' ' * (level)))
|
c_file.write("%sif (yajl_gen_status_ok != stat)\n" % (' ' * (level)))
|
||||||
c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" % (' ' * (level + 1)))
|
c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" % (' ' * (level + 1)))
|
||||||
elif typ == 'string':
|
elif typ == 'string':
|
||||||
c_file.write('%sstat = yajl_gen_string((yajl_gen)%s, (const unsigned char *)(%s), strlen(%s));\n' \
|
c_file.write('%sstat = yajl_gen_string((yajl_gen)%s, \
|
||||||
% (' ' * (level), dst, src, src))
|
(const unsigned char *)(%s), strlen(%s));\n' % (' ' * (level), dst, src, src))
|
||||||
c_file.write("%sif (yajl_gen_status_ok != stat)\n" % (' ' * (level)))
|
c_file.write("%sif (yajl_gen_status_ok != stat)\n" % (' ' * (level)))
|
||||||
c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" % (' ' * (level + 1)))
|
c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" % (' ' * (level + 1)))
|
||||||
|
elif helpers.judge_data_type(typ):
|
||||||
elif helpers.judgeDataType(typ):
|
|
||||||
if typ == 'double':
|
if typ == 'double':
|
||||||
c_file.write('%sstat = yajl_gen_double((yajl_gen)%s, %s);\n' % (' ' * (level), dst, src))
|
c_file.write('%sstat = yajl_gen_double((yajl_gen)%s, %s);\n' \
|
||||||
|
% (' ' * (level), dst, src))
|
||||||
elif typ.startswith("uint") or typ == 'GID' or typ == 'UID':
|
elif typ.startswith("uint") or typ == 'GID' or typ == 'UID':
|
||||||
c_file.write('%sstat = map_uint(%s, %s);\n' % (' ' * (level), dst, src))
|
c_file.write('%sstat = map_uint(%s, %s);\n' % (' ' * (level), dst, src))
|
||||||
else:
|
else:
|
||||||
c_file.write('%sstat = map_int(%s, %s);\n' % (' ' * (level), dst, src))
|
c_file.write('%sstat = map_int(%s, %s);\n' % (' ' * (level), dst, src))
|
||||||
c_file.write("%sif (yajl_gen_status_ok != stat)\n" % (' ' * (level)))
|
c_file.write("%sif (yajl_gen_status_ok != stat)\n" % (' ' * (level)))
|
||||||
c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" % (' ' * (level + 1)))
|
c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" \
|
||||||
|
% (' ' * (level + 1)))
|
||||||
elif typ == 'boolean':
|
elif typ == 'boolean':
|
||||||
c_file.write('%sstat = yajl_gen_bool((yajl_gen)%s, (int)(%s));\n' % (' ' * (level), dst, src))
|
c_file.write('%sstat = yajl_gen_bool((yajl_gen)%s, (int)(%s));\n' \
|
||||||
|
% (' ' * (level), dst, src))
|
||||||
c_file.write("%sif (yajl_gen_status_ok != stat)\n" % (' ' * (level)))
|
c_file.write("%sif (yajl_gen_status_ok != stat)\n" % (' ' * (level)))
|
||||||
c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" % (' ' * (level + 1)))
|
c_file.write("%sGEN_SET_ERROR_AND_RETURN(stat, err);\n" % (' ' * (level + 1)))
|
||||||
|
|
||||||
|
|
||||||
def makeCFree(obj, c_file, prefix):
|
def make_c_free(obj, c_file, prefix):
|
||||||
"""
|
"""
|
||||||
Description: generate c free function
|
Description: generate c free function
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
if not helpers.judgeComplex(obj.typ) or obj.subtypname:
|
if not helpers.judge_complex(obj.typ) or obj.subtypname:
|
||||||
return
|
return
|
||||||
|
typename = helpers.get_prefixe_name(obj.name, prefix)
|
||||||
typename = helpers.getPrefixName(obj.name, prefix)
|
|
||||||
|
|
||||||
case = obj.typ
|
case = obj.typ
|
||||||
result = {
|
result = {'mapStringObject': lambda x: [], 'object': lambda x: x.children,
|
||||||
'mapStringObject': lambda x: [],
|
'array': lambda x: x.subtypobj}[case](obj)
|
||||||
'object': lambda x: x.children,
|
|
||||||
'array': lambda x: x.subtypobj
|
|
||||||
}[case](obj)
|
|
||||||
|
|
||||||
objs = result
|
objs = result
|
||||||
if obj.typ == 'array':
|
if obj.typ == 'array':
|
||||||
if objs is None:
|
if objs is None:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
typename = helpers.getNameSubstr(obj.name, prefix)
|
typename = helpers.get_name_substr(obj.name, prefix)
|
||||||
|
|
||||||
c_file.write("void free_%s(%s *ptr) {\n" % (typename, typename))
|
c_file.write("void free_%s(%s *ptr) {\n" % (typename, typename))
|
||||||
c_file.write(" if (ptr == NULL)\n")
|
c_file.write(" if (ptr == NULL)\n")
|
||||||
c_file.write(" return;\n")
|
c_file.write(" return;\n")
|
||||||
if obj.typ == 'mapStringObject':
|
if obj.typ == 'mapStringObject':
|
||||||
child = obj.children[0]
|
child = obj.children[0]
|
||||||
if helpers.validBasicMapName(child.typ):
|
if helpers.valid_basic_map_name(child.typ):
|
||||||
childname = helpers.makeBasicMapName(child.typ)
|
childname = helpers.make_basic_map_name(child.typ)
|
||||||
else:
|
else:
|
||||||
if child.subtypname:
|
if child.subtypname:
|
||||||
childname = child.subtypname
|
childname = child.subtypname
|
||||||
else:
|
else:
|
||||||
childname = helpers.getPrefixName(child.name, prefix)
|
childname = helpers.get_prefixe_name(child.name, prefix)
|
||||||
|
c_file_map_str(c_file, child, childname)
|
||||||
|
for i in objs or []:
|
||||||
|
if helpers.valid_basic_map_name(i.typ):
|
||||||
|
free_func = helpers.make_basic_map_name(i.typ)
|
||||||
|
c_file.write(" free_%s(ptr->%s);\n" % (free_func, i.fixname))
|
||||||
|
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
||||||
|
if i.typ == 'mapStringObject':
|
||||||
|
if i.subtypname:
|
||||||
|
free_func = i.subtypname
|
||||||
|
else:
|
||||||
|
free_func = helpers.get_prefixe_name(i.name, prefix)
|
||||||
|
c_file.write(" free_%s(ptr->%s);\n" % (free_func, i.fixname))
|
||||||
|
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
||||||
|
elif i.typ == 'array':
|
||||||
|
if helpers.valid_basic_map_name(i.subtyp):
|
||||||
|
free_func = helpers.make_basic_map_name(i.subtyp)
|
||||||
|
c_file.write(" if (ptr->%s != NULL) {\n" % i.fixname)
|
||||||
|
c_file.write(" size_t i;\n")
|
||||||
|
c_file.write(" for (i = 0; i < ptr->%s_len; i++) {\n" % i.fixname)
|
||||||
|
c_file.write(" if (ptr->%s[i] != NULL) {\n" % (i.fixname))
|
||||||
|
c_file.write(" free_%s(ptr->%s[i]);\n" % (free_func, i.fixname))
|
||||||
|
c_file.write(" ptr->%s[i] = NULL;\n" % (i.fixname))
|
||||||
|
c_file.write(" }\n")
|
||||||
|
c_file.write(" }\n")
|
||||||
|
c_file.write(" free(ptr->%s);\n" % (i.fixname))
|
||||||
|
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
||||||
|
c_file.write(" }\n")
|
||||||
|
elif i.subtyp == 'string':
|
||||||
|
c_file_str(c_file, i)
|
||||||
|
elif not helpers.judge_complex(i.subtyp):
|
||||||
|
c_file.write(" free(ptr->%s);\n" % (i.fixname))
|
||||||
|
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
||||||
|
elif i.subtyp == 'object' or i.subtypobj is not None:
|
||||||
|
if i.subtypname is not None:
|
||||||
|
free_func = i.subtypname
|
||||||
|
else:
|
||||||
|
free_func = helpers.get_name_substr(i.name, prefix)
|
||||||
|
c_file.write(" if (ptr->%s != NULL) {\n" % i.fixname)
|
||||||
|
c_file.write(" size_t i;\n")
|
||||||
|
c_file.write(" for (i = 0; i < ptr->%s_len; i++)\n" % i.fixname)
|
||||||
|
c_file.write(" if (ptr->%s[i] != NULL) {\n" % (i.fixname))
|
||||||
|
c_file.write(" free_%s(ptr->%s[i]);\n" % (free_func, i.fixname))
|
||||||
|
c_file.write(" ptr->%s[i] = NULL;\n" % (i.fixname))
|
||||||
|
c_file.write(" }\n")
|
||||||
|
c_file.write(" free(ptr->%s);\n" % i.fixname)
|
||||||
|
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
||||||
|
c_file.write(" }\n")
|
||||||
|
c_typ = helpers.obtain_pointer(i.name, i.subtypobj, prefix)
|
||||||
|
if c_typ == "":
|
||||||
|
continue
|
||||||
|
if i.subobj is not None:
|
||||||
|
c_typ = c_typ + "_element"
|
||||||
|
c_file.write(" free_%s(ptr->%s);\n" % (c_typ, i.fixname))
|
||||||
|
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
||||||
|
else:
|
||||||
|
typename = helpers.get_prefixe_name(i.name, prefix)
|
||||||
|
if i.typ == 'string' or i.typ == 'booleanPointer' or \
|
||||||
|
helpers.judge_data_pointer_type(i.typ):
|
||||||
|
c_file.write(" free(ptr->%s);\n" % (i.fixname))
|
||||||
|
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
||||||
|
elif i.typ == 'object':
|
||||||
|
if i.subtypname is not None:
|
||||||
|
typename = i.subtypname
|
||||||
|
c_file.write(" if (ptr->%s != NULL) {\n" % (i.fixname))
|
||||||
|
c_file.write(" free_%s(ptr->%s);\n" % (typename, i.fixname))
|
||||||
|
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
||||||
|
c_file.write(" }\n")
|
||||||
|
c_file.write(" free(ptr);\n")
|
||||||
|
c_file.write("}\n\n")
|
||||||
|
|
||||||
|
|
||||||
|
def c_file_map_str(c_file, child, childname):
|
||||||
|
"""
|
||||||
|
Description: generate c code for map string
|
||||||
|
Interface: None
|
||||||
|
History: 2019-10-31
|
||||||
|
"""
|
||||||
c_file.write(" if (ptr->keys != NULL && ptr->%s != NULL) {\n" % child.fixname)
|
c_file.write(" if (ptr->keys != NULL && ptr->%s != NULL) {\n" % child.fixname)
|
||||||
c_file.write(" size_t i;\n")
|
c_file.write(" size_t i;\n")
|
||||||
c_file.write(" for (i = 0; i < ptr->len; i++) {\n")
|
c_file.write(" for (i = 0; i < ptr->len; i++) {\n")
|
||||||
@ -701,33 +764,13 @@ def makeCFree(obj, c_file, prefix):
|
|||||||
c_file.write(" ptr->%s = NULL;\n" % (child.fixname))
|
c_file.write(" ptr->%s = NULL;\n" % (child.fixname))
|
||||||
c_file.write(" }\n")
|
c_file.write(" }\n")
|
||||||
|
|
||||||
for i in objs or []:
|
|
||||||
if helpers.validBasicMapName(i.typ):
|
def c_file_str(c_file, i):
|
||||||
free_func = helpers.makeBasicMapName(i.typ)
|
"""
|
||||||
c_file.write(" free_%s(ptr->%s);\n" % (free_func, i.fixname))
|
Description: generate c code template
|
||||||
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
Interface: None
|
||||||
if i.typ == 'mapStringObject':
|
History: 2019-10-31
|
||||||
if i.subtypname:
|
"""
|
||||||
free_func = i.subtypname
|
|
||||||
else:
|
|
||||||
free_func = helpers.getPrefixName(i.name, prefix)
|
|
||||||
c_file.write(" free_%s(ptr->%s);\n" % (free_func, i.fixname))
|
|
||||||
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
|
||||||
elif i.typ == 'array':
|
|
||||||
if helpers.validBasicMapName(i.subtyp):
|
|
||||||
free_func = helpers.makeBasicMapName(i.subtyp)
|
|
||||||
c_file.write(" if (ptr->%s != NULL) {\n" % i.fixname)
|
|
||||||
c_file.write(" size_t i;\n")
|
|
||||||
c_file.write(" for (i = 0; i < ptr->%s_len; i++) {\n" % i.fixname)
|
|
||||||
c_file.write(" if (ptr->%s[i] != NULL) {\n" % (i.fixname))
|
|
||||||
c_file.write(" free_%s(ptr->%s[i]);\n" % (free_func, i.fixname))
|
|
||||||
c_file.write(" ptr->%s[i] = NULL;\n" % (i.fixname))
|
|
||||||
c_file.write(" }\n")
|
|
||||||
c_file.write(" }\n")
|
|
||||||
c_file.write(" free(ptr->%s);\n" % (i.fixname))
|
|
||||||
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
|
||||||
c_file.write(" }\n")
|
|
||||||
elif i.subtyp == 'string':
|
|
||||||
c_file.write(" if (ptr->%s != NULL) {\n" % i.fixname)
|
c_file.write(" if (ptr->%s != NULL) {\n" % i.fixname)
|
||||||
c_file.write(" size_t i;\n")
|
c_file.write(" size_t i;\n")
|
||||||
c_file.write(" for (i = 0; i < ptr->%s_len; i++) {\n" % i.fixname)
|
c_file.write(" for (i = 0; i < ptr->%s_len; i++) {\n" % i.fixname)
|
||||||
@ -739,61 +782,16 @@ def makeCFree(obj, c_file, prefix):
|
|||||||
c_file.write(" free(ptr->%s);\n" % (i.fixname))
|
c_file.write(" free(ptr->%s);\n" % (i.fixname))
|
||||||
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
||||||
c_file.write(" }\n")
|
c_file.write(" }\n")
|
||||||
elif not helpers.judgeComplex(i.subtyp):
|
|
||||||
c_file.write(" free(ptr->%s);\n" % (i.fixname))
|
|
||||||
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
|
||||||
elif i.subtyp == 'object' or i.subtypobj is not None:
|
|
||||||
if i.subtypname is not None:
|
|
||||||
free_func = i.subtypname
|
|
||||||
else:
|
|
||||||
free_func = helpers.getNameSubstr(i.name, prefix)
|
|
||||||
c_file.write(" if (ptr->%s != NULL) {\n" % i.fixname)
|
|
||||||
c_file.write(" size_t i;\n")
|
|
||||||
c_file.write(" for (i = 0; i < ptr->%s_len; i++)\n" % i.fixname)
|
|
||||||
c_file.write(" if (ptr->%s[i] != NULL) {\n" % (i.fixname))
|
|
||||||
c_file.write(" free_%s(ptr->%s[i]);\n" % (free_func, i.fixname))
|
|
||||||
c_file.write(" ptr->%s[i] = NULL;\n" % (i.fixname))
|
|
||||||
c_file.write(" }\n")
|
|
||||||
c_file.write(" free(ptr->%s);\n" % i.fixname)
|
|
||||||
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
|
||||||
c_file.write(" }\n")
|
|
||||||
|
|
||||||
c_typ = helpers.obtainPointer(i.name, i.subtypobj, prefix)
|
|
||||||
if c_typ == "":
|
|
||||||
continue
|
|
||||||
if i.subobj is not None:
|
|
||||||
c_typ = c_typ + "_element"
|
|
||||||
c_file.write(" free_%s(ptr->%s);\n" % (c_typ, i.fixname))
|
|
||||||
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
|
||||||
else: # not array
|
|
||||||
typename = helpers.getPrefixName(i.name, prefix)
|
|
||||||
if i.typ == 'string':
|
|
||||||
c_file.write(" free(ptr->%s);\n" % (i.fixname))
|
|
||||||
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
|
||||||
elif i.typ == 'booleanPointer':
|
|
||||||
c_file.write(" free(ptr->%s);\n" % (i.fixname))
|
|
||||||
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
|
||||||
elif helpers.judgeDataPointerType(i.typ):
|
|
||||||
c_file.write(" free(ptr->%s);\n" % (i.fixname))
|
|
||||||
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
|
||||||
elif i.typ == 'object':
|
|
||||||
if i.subtypname is not None:
|
|
||||||
typename = i.subtypname
|
|
||||||
c_file.write(" if (ptr->%s != NULL) {\n" % (i.fixname))
|
|
||||||
c_file.write(" free_%s(ptr->%s);\n" % (typename, i.fixname))
|
|
||||||
c_file.write(" ptr->%s = NULL;\n" % (i.fixname))
|
|
||||||
c_file.write(" }\n")
|
|
||||||
c_file.write(" free(ptr);\n")
|
|
||||||
c_file.write("}\n\n")
|
|
||||||
|
|
||||||
|
|
||||||
def sourceReflection(structs, schema_info, c_file, root_typ):
|
def src_reflect(structs, schema_info, c_file, root_typ):
|
||||||
"""
|
"""
|
||||||
Description: reflect code
|
Description: reflect code
|
||||||
Interface: None
|
Interface: None
|
||||||
History: 2019-06-17
|
History: 2019-06-17
|
||||||
"""
|
"""
|
||||||
c_file.write("// Generated from %s. Do not edit!\n" % (schema_info.name.basename))
|
c_file.write("// Generated from %s. Do not edit!\n" \
|
||||||
|
% (schema_info.name.basename))
|
||||||
c_file.write("#ifndef _GNU_SOURCE\n")
|
c_file.write("#ifndef _GNU_SOURCE\n")
|
||||||
c_file.write("#define _GNU_SOURCE\n")
|
c_file.write("#define _GNU_SOURCE\n")
|
||||||
c_file.write("#endif\n")
|
c_file.write("#endif\n")
|
||||||
@ -801,14 +799,12 @@ def sourceReflection(structs, schema_info, c_file, root_typ):
|
|||||||
c_file.write('#include <read_file.h>\n')
|
c_file.write('#include <read_file.h>\n')
|
||||||
c_file.write('#include "securec.h"\n')
|
c_file.write('#include "securec.h"\n')
|
||||||
c_file.write('#include "%s"\n\n' % schema_info.header.basename)
|
c_file.write('#include "%s"\n\n' % schema_info.header.basename)
|
||||||
|
|
||||||
for i in structs:
|
for i in structs:
|
||||||
appendCCode(i, c_file, schema_info.prefix)
|
append_c_code(i, c_file, schema_info.prefix)
|
||||||
|
get_c_epilog(c_file, schema_info.prefix, root_typ)
|
||||||
obtainCEpilogue(c_file, schema_info.prefix, root_typ)
|
|
||||||
|
|
||||||
|
|
||||||
def obtainCEpilogue(c_file, prefix, typ):
|
def get_c_epilog(c_file, prefix, typ):
|
||||||
"""
|
"""
|
||||||
Description: generate c language epilogue
|
Description: generate c language epilogue
|
||||||
Interface: None
|
Interface: None
|
||||||
@ -816,7 +812,6 @@ def obtainCEpilogue(c_file, prefix, typ):
|
|||||||
"""
|
"""
|
||||||
if typ != 'array' and typ != 'object':
|
if typ != 'array' and typ != 'object':
|
||||||
return
|
return
|
||||||
|
|
||||||
if typ == 'array':
|
if typ == 'array':
|
||||||
c_file.write("""\n
|
c_file.write("""\n
|
||||||
%s_element **make_%s(yajl_val tree, const struct parser_context *ctx, parser_error *err, size_t *len) {
|
%s_element **make_%s(yajl_val tree, const struct parser_context *ctx, parser_error *err, size_t *len) {
|
||||||
@ -877,13 +872,11 @@ yajl_gen_status gen_%s(yajl_gen g, const %s_element **ptr, size_t len, const str
|
|||||||
return yajl_gen_status_ok;
|
return yajl_gen_status_ok;
|
||||||
}
|
}
|
||||||
""" % (prefix, prefix, prefix))
|
""" % (prefix, prefix, prefix))
|
||||||
|
|
||||||
c_file.write("""
|
c_file.write("""
|
||||||
%s%s*%s_parse_file(const char *filename, const struct parser_context *ctx, parser_error *err%s) {
|
%s%s*%s_parse_file(const char *filename, const struct parser_context *ctx, parser_error *err%s) {
|
||||||
%s%s*ptr = NULL;""" % (prefix, ' ' if typ == 'object' else '_element *', \
|
%s%s*ptr = NULL;""" % (prefix, ' ' if typ == 'object' else '_element *', \
|
||||||
prefix, '' if typ == 'object' else ', size_t *len', \
|
prefix, '' if typ == 'object' else ', size_t *len', \
|
||||||
prefix, ' ' if typ == 'object' else '_element *'))
|
prefix, ' ' if typ == 'object' else '_element *'))
|
||||||
|
|
||||||
c_file.write("""
|
c_file.write("""
|
||||||
size_t filesize;
|
size_t filesize;
|
||||||
char *content = NULL;
|
char *content = NULL;
|
||||||
@ -903,13 +896,11 @@ yajl_gen_status gen_%s(yajl_gen g, const %s_element **ptr, size_t len, const str
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
""" % (prefix, '' if typ == 'object' else ', len'))
|
""" % (prefix, '' if typ == 'object' else ', len'))
|
||||||
|
|
||||||
c_file.write("""
|
c_file.write("""
|
||||||
%s%s*%s_parse_file_stream(FILE *stream, const struct parser_context *ctx, parser_error *err%s) {
|
%s%s*%s_parse_file_stream(FILE *stream, const struct parser_context *ctx, parser_error *err%s) {
|
||||||
%s%s*ptr = NULL;""" % (prefix, ' ' if typ == 'object' else '_element *', \
|
%s%s*ptr = NULL;""" % (prefix, ' ' if typ == 'object' else '_element *', \
|
||||||
prefix, '' if typ == 'object' else ', size_t *len', \
|
prefix, '' if typ == 'object' else ', size_t *len', \
|
||||||
prefix, ' ' if typ == 'object' else '_element *'))
|
prefix, ' ' if typ == 'object' else '_element *'))
|
||||||
|
|
||||||
c_file.write("""
|
c_file.write("""
|
||||||
size_t filesize;
|
size_t filesize;
|
||||||
char *content = NULL ;
|
char *content = NULL ;
|
||||||
@ -928,13 +919,11 @@ yajl_gen_status gen_%s(yajl_gen g, const %s_element **ptr, size_t len, const str
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
""" % (prefix, '' if typ == 'object' else ', len'))
|
""" % (prefix, '' if typ == 'object' else ', len'))
|
||||||
|
|
||||||
c_file.write("""
|
c_file.write("""
|
||||||
%s%s*%s_parse_data(const char *jsondata, const struct parser_context *ctx, parser_error *err%s) {
|
%s%s*%s_parse_data(const char *jsondata, const struct parser_context *ctx, parser_error *err%s) {
|
||||||
%s%s*ptr = NULL;""" % (prefix, ' ' if typ == 'object' else '_element *', \
|
%s%s*ptr = NULL;""" % (prefix, ' ' if typ == 'object' else '_element *', \
|
||||||
prefix, '' if typ == 'object' else ', size_t *len', \
|
prefix, '' if typ == 'object' else ', size_t *len', \
|
||||||
prefix, ' ' if typ == 'object' else '_element *'))
|
prefix, ' ' if typ == 'object' else '_element *'))
|
||||||
|
|
||||||
c_file.write("""
|
c_file.write("""
|
||||||
yajl_val tree;
|
yajl_val tree;
|
||||||
char errbuf[1024];
|
char errbuf[1024];
|
||||||
@ -958,12 +947,10 @@ yajl_gen_status gen_%s(yajl_gen g, const %s_element **ptr, size_t len, const str
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
""" % (prefix, '' if typ == 'object' else ', len'))
|
""" % (prefix, '' if typ == 'object' else ', len'))
|
||||||
|
|
||||||
c_file.write("char *%s_generate_json(const %s%s*ptr%s, const struct parser_context *ctx," \
|
c_file.write("char *%s_generate_json(const %s%s*ptr%s, const struct parser_context *ctx," \
|
||||||
" parser_error *err) {" % (prefix, prefix, \
|
" parser_error *err) {" % (prefix, prefix, \
|
||||||
' ' if typ == 'object' else '_element *', \
|
' ' if typ == 'object' else '_element *', \
|
||||||
'' if typ == 'object' else ', size_t len'))
|
'' if typ == 'object' else ', size_t len'))
|
||||||
|
|
||||||
c_file.write("""
|
c_file.write("""
|
||||||
yajl_gen g = NULL;
|
yajl_gen g = NULL;
|
||||||
struct parser_context tmp_ctx = { 0 };
|
struct parser_context tmp_ctx = { 0 };
|
||||||
@ -1011,3 +998,5 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
""" % (prefix, '' if typ == 'object' else ', len'))
|
""" % (prefix, '' if typ == 'object' else ', len'))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -436,7 +436,7 @@ static bool mount_get_bundle_file(char **bundle, const char *container_name, con
|
|||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Mount file
|
* Mount file
|
||||||
**/
|
*/
|
||||||
static bool mount_file(oci_runtime_spec *container, const char *bundle, const char *filename, const char *targetdir)
|
static bool mount_file(oci_runtime_spec *container, const char *bundle, const char *filename, const char *targetdir)
|
||||||
{
|
{
|
||||||
char dest[PATH_MAX] = { 0 };
|
char dest[PATH_MAX] = { 0 };
|
||||||
@ -513,7 +513,8 @@ static bool mount_hostname(oci_runtime_spec *container, const struct lxc_contain
|
|||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
/* 2.generate hostname file that need to mount */
|
/* 2.generate hostname file that need to mount */
|
||||||
ret = util_write_file(bundle, container->hostname, strlen(container->hostname), true);
|
ret = util_write_file(bundle, container->hostname, strlen(container->hostname),
|
||||||
|
true, NETWORK_MOUNT_FILE_MODE);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
@ -557,11 +558,11 @@ static bool mount_network_file(oci_runtime_spec *container, const struct lxc_con
|
|||||||
}
|
}
|
||||||
// 2. copy /etc/hosts into container hosts file that need to mount
|
// 2. copy /etc/hosts into container hosts file that need to mount
|
||||||
if (file_exists(full_path)) {
|
if (file_exists(full_path)) {
|
||||||
ret = util_copy_file(full_path, bundle);
|
ret = util_copy_file(full_path, bundle, NETWORK_MOUNT_FILE_MODE);
|
||||||
} else {
|
} else {
|
||||||
// write default value into bundle
|
// write default value into bundle
|
||||||
if (default_str != NULL && strlen(default_str) > 0) {
|
if (default_str != NULL && strlen(default_str) > 0) {
|
||||||
ret = util_write_file(bundle, default_str, strlen(default_str), false);
|
ret = util_write_file(bundle, default_str, strlen(default_str), false, NETWORK_MOUNT_FILE_MODE);
|
||||||
} else {
|
} else {
|
||||||
ret = false;
|
ret = false;
|
||||||
ERROR("Default value is NULL");
|
ERROR("Default value is NULL");
|
||||||
@ -626,16 +627,17 @@ static bool mount_hosts(oci_runtime_spec *container, const struct lxc_container
|
|||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
/* 5.generate hosts file that need to mount */
|
/* 5.generate hosts file that need to mount */
|
||||||
ret = util_write_file(bundle, content, strlen(content), false);
|
ret = util_write_file(bundle, content, strlen(content), false, NETWORK_MOUNT_FILE_MODE);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
/* 3.Add one mount nodes to container->mounts */
|
/* 6.Add one mount nodes to container->mounts */
|
||||||
ret = mount_file(container, bundle, filename, targetdir);
|
ret = mount_file(container, bundle, filename, targetdir);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
ERROR("mount hostname file failed");
|
ERROR("mount hostname file failed");
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_free:
|
out_free:
|
||||||
free(bundle);
|
free(bundle);
|
||||||
free(content);
|
free(content);
|
||||||
@ -669,7 +671,7 @@ static bool copy_host_file_to_bundle(const struct lxc_container *c, const char *
|
|||||||
if (!ret) {
|
if (!ret) {
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
ret = util_copy_file(full_path, bundle);
|
ret = util_copy_file(full_path, bundle, NETWORK_MOUNT_FILE_MODE);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
@ -797,68 +799,6 @@ static inline bool is_root(const char *path)
|
|||||||
return strcmp(path, "/") == 0;
|
return strcmp(path, "/") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool create_spec(struct lxc_container *c, const char *dist, const char *container_rootfs)
|
|
||||||
{
|
|
||||||
bool ret = false;
|
|
||||||
char config[PATH_MAX] = { 0 };
|
|
||||||
int nret = 0;
|
|
||||||
struct lcr_list *lcr_conf = NULL;
|
|
||||||
char *seccomp_conf = NULL;
|
|
||||||
|
|
||||||
INFO("Create new specification file");
|
|
||||||
nret = sprintf_s(config, sizeof(config), "%s/%s/config", c->config_path, c->name);
|
|
||||||
if (nret < 0) {
|
|
||||||
ERROR("Failed to print string");
|
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
lcr_conf = lcr_dist2spec(dist, &seccomp_conf);
|
|
||||||
if (lcr_conf == NULL) {
|
|
||||||
ERROR("Create distribution specific configuration failed");
|
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lcr_save_spec(c->name, c->config_path, lcr_conf, seccomp_conf)) {
|
|
||||||
ERROR("Failed to save configuration");
|
|
||||||
goto out_free_conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reload the config to update the hwaddr in `config` */
|
|
||||||
c->clear_config(c);
|
|
||||||
|
|
||||||
if (!c->load_config(c, config)) {
|
|
||||||
ERROR("Failed to load config %s", config);
|
|
||||||
goto out_free_conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* NOTE: update (clear and set) container's utsname
|
|
||||||
* will result in two 'lxc.uts.name' in config file due to lxc's problem,
|
|
||||||
* But they override each other in the order specified.
|
|
||||||
*/
|
|
||||||
c->clear_config_item(c, "lxc.uts.name");
|
|
||||||
c->set_config_item(c, "lxc.uts.name", c->name);
|
|
||||||
|
|
||||||
c->clear_config_item(c, "lxc.rootfs.path");
|
|
||||||
if (!is_root(container_rootfs)) {
|
|
||||||
c->set_config_item(c, "lxc.rootfs.path", container_rootfs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!c->save_config(c, config)) {
|
|
||||||
ERROR("Save configuration failed\n");
|
|
||||||
goto out_free_conf;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = true;
|
|
||||||
|
|
||||||
out_free_conf:
|
|
||||||
lcr_free_config(lcr_conf);
|
|
||||||
free(lcr_conf);
|
|
||||||
|
|
||||||
err_out:
|
|
||||||
free(seccomp_conf);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int create_partial(const struct lxc_container *c)
|
static int create_partial(const struct lxc_container *c)
|
||||||
{
|
{
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
@ -991,46 +931,25 @@ static struct lxc_container *lcr_create_new_container(const char *name, const ch
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool is_spec_dist_none(const char *spec_dist)
|
|
||||||
{
|
|
||||||
return strcmp(spec_dist, "none") == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool lcr_create_spec_dist(struct lxc_container *c, const char *real_rootfs, const char *spec_dist,
|
static bool lcr_create_spec(const struct lxc_container *c, const char *real_rootfs, const char *oci_config_data)
|
||||||
const char *oci_config_data)
|
|
||||||
{
|
{
|
||||||
/* NOTE: a special value can be assigned to `dist`, when it's value
|
|
||||||
* is `none`, we will not create default config
|
|
||||||
*/
|
|
||||||
if (!is_spec_dist_none(spec_dist)) {
|
|
||||||
if (oci_config_data != NULL) {
|
|
||||||
// Translate oci config
|
// Translate oci config
|
||||||
DEBUG("Translate oci config...\n");
|
DEBUG("Translate oci config...\n");
|
||||||
if (!translate_spec(c, oci_config_data, real_rootfs)) {
|
if (!translate_spec(c, oci_config_data, real_rootfs)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
DEBUG("Translate oci config... done\n");
|
DEBUG("Translate oci config... done\n");
|
||||||
} else {
|
|
||||||
// Generate default config
|
|
||||||
DEBUG("Generate default config...\n");
|
|
||||||
if (!create_spec(c, spec_dist, real_rootfs)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
DEBUG("Generate default config... done\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lcr_create(const char *name, const char *lcrpath, const char *rootfs, const char *dist,
|
bool lcr_create(const char *name, const char *lcrpath, const char *rootfs, const void *oci_config_data)
|
||||||
const void *oci_config_data)
|
|
||||||
{
|
{
|
||||||
struct lxc_container *c = NULL;
|
struct lxc_container *c = NULL;
|
||||||
int partial_fd = -1;
|
int partial_fd = -1;
|
||||||
bool bret = false;
|
bool bret = false;
|
||||||
char *real_rootfs = NULL; /* the real rootfs used by the container */
|
char *real_rootfs = NULL; /* the real rootfs used by the container */
|
||||||
const char *tmp_path = lcrpath ? lcrpath : LCRPATH;
|
const char *tmp_path = lcrpath ? lcrpath : LCRPATH;
|
||||||
const char *spec_dist = dist ? dist : "ubuntu";
|
|
||||||
|
|
||||||
clear_error_message(&g_lcr_error);
|
clear_error_message(&g_lcr_error);
|
||||||
engine_set_log_prefix(name);
|
engine_set_log_prefix(name);
|
||||||
@ -1054,7 +973,7 @@ bool lcr_create(const char *name, const char *lcrpath, const char *rootfs, const
|
|||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lcr_create_spec_dist(c, real_rootfs, spec_dist, oci_config_data)) {
|
if (!lcr_create_spec(c, real_rootfs, oci_config_data)) {
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1237,9 +1156,7 @@ bool lcr_start(const struct lcr_start_request *request)
|
|||||||
close(pipefd[0]);
|
close(pipefd[0]);
|
||||||
dup2(pipefd[1], 2);
|
dup2(pipefd[1], 2);
|
||||||
|
|
||||||
execute_lxc_start(request->name, path, request->logpath, request->loglevel, request->daemonize, request->tty,
|
execute_lxc_start(request->name, path, request);
|
||||||
request->open_stdin, request->pidfile, request->console_fifos, request->console_logpath,
|
|
||||||
request->share_ns, request->start_timeout, request->container_pidfile, request->exit_fifo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close(pipefd[1]);
|
close(pipefd[1]);
|
||||||
@ -1384,71 +1301,23 @@ out_put:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lcr_exec(const char *name, const char *lcrpath, int argc, char * const *argv, pid_t *pid)
|
bool lcr_exec(const struct lcr_exec_request *request, int *exit_code)
|
||||||
{
|
{
|
||||||
|
const char *name = NULL;
|
||||||
struct lxc_container *c = NULL;
|
struct lxc_container *c = NULL;
|
||||||
const char *path = lcrpath ? lcrpath : LCRPATH;
|
const char *tmp_path = NULL;
|
||||||
int r = 0;
|
|
||||||
bool ret = false;
|
|
||||||
lxc_attach_options_t options = LXC_ATTACH_OPTIONS_DEFAULT;
|
|
||||||
lxc_attach_command_t command = (lxc_attach_command_t) {
|
|
||||||
.program = NULL
|
|
||||||
};
|
|
||||||
if (argc > 0) {
|
|
||||||
command.program = argv[0];
|
|
||||||
command.argv = (char **)argv;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name == NULL) {
|
|
||||||
ERROR("Missing container name");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
engine_set_log_prefix(name);
|
|
||||||
if (geteuid()) {
|
|
||||||
if (access(path, O_RDONLY) < 0) {
|
|
||||||
ERROR("You lack access to %s", path);
|
|
||||||
engine_free_log_prefix();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c = lxc_container_new(name, path);
|
|
||||||
if (c == NULL) {
|
|
||||||
ERROR("Failed to delete container.");
|
|
||||||
engine_free_log_prefix();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lcr_check_container_running(c, name)) {
|
|
||||||
goto out_put;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command.program != NULL) {
|
|
||||||
r = c->attach(c, lxc_attach_run_command, &command, &options, pid);
|
|
||||||
} else {
|
|
||||||
r = c->attach(c, lxc_attach_run_shell, NULL, &options, pid);
|
|
||||||
}
|
|
||||||
if (r < 0) {
|
|
||||||
goto out_put;
|
|
||||||
}
|
|
||||||
ret = true;
|
|
||||||
out_put:
|
|
||||||
lxc_container_put(c);
|
|
||||||
engine_free_log_prefix();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lcr_attach(const char *name, const char *lcrpath, const char *logpath, const char *loglevel,
|
|
||||||
const char *console_fifos[], char * const argv[], char * const env[], int64_t timeout,
|
|
||||||
pid_t *exec_pid, int *exit_code)
|
|
||||||
{
|
|
||||||
struct lxc_container *c = NULL;
|
|
||||||
const char *tmp_path = lcrpath ? lcrpath : LCRPATH;
|
|
||||||
bool bret = false;
|
bool bret = false;
|
||||||
|
|
||||||
clear_error_message(&g_lcr_error);
|
clear_error_message(&g_lcr_error);
|
||||||
|
|
||||||
|
if (request == NULL || exit_code == NULL) {
|
||||||
|
ERROR("Invalid input arguments");
|
||||||
|
return bret;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = request->name;
|
||||||
|
tmp_path = request->lcrpath ? request->lcrpath : LCRPATH;
|
||||||
|
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
ERROR("Missing container name");
|
ERROR("Missing container name");
|
||||||
return bret;
|
return bret;
|
||||||
@ -1476,9 +1345,7 @@ bool lcr_attach(const char *name, const char *lcrpath, const char *logpath, cons
|
|||||||
lxc_container_put(c);
|
lxc_container_put(c);
|
||||||
|
|
||||||
/* do attach to wait exit code */
|
/* do attach to wait exit code */
|
||||||
bret = do_attach(name, lcrpath, logpath, loglevel, console_fifos, (const char * const *)argv,
|
bret = do_attach(name, tmp_path, request, exit_code);
|
||||||
(const char * const *)env, timeout, exec_pid, exit_code);
|
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
out_put:
|
out_put:
|
||||||
@ -1490,13 +1357,6 @@ out:
|
|||||||
|
|
||||||
static bool lcr_check_container_stopped(struct lxc_container *c, const char *name)
|
static bool lcr_check_container_stopped(struct lxc_container *c, const char *name)
|
||||||
{
|
{
|
||||||
if (!is_container_exists(c)) {
|
|
||||||
ERROR("No such container");
|
|
||||||
lcr_set_error_message(LCR_ERR_RUNTIME, "No such container:%s or the configuration files has been corrupted",
|
|
||||||
name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_container_can_control(c)) {
|
if (!is_container_can_control(c)) {
|
||||||
ERROR("Insufficent privileges to control");
|
ERROR("Insufficent privileges to control");
|
||||||
return false;
|
return false;
|
||||||
@ -1539,6 +1399,13 @@ bool lcr_clean(const char *name, const char *lcrpath, const char *logpath, const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if container do not exist, just return true. */
|
||||||
|
if (!is_container_exists(c)) {
|
||||||
|
WARN("No such container: %s", name);
|
||||||
|
bret = true;
|
||||||
|
goto out_put;
|
||||||
|
}
|
||||||
|
|
||||||
if (!lcr_check_container_stopped(c, name)) {
|
if (!lcr_check_container_stopped(c, name)) {
|
||||||
bret = false;
|
bret = false;
|
||||||
goto out_put;
|
goto out_put;
|
||||||
@ -2045,7 +1912,7 @@ bool translate_spec(const struct lxc_container *c, const char *oci_json_data, co
|
|||||||
|
|
||||||
lcr_conf = lcr_oci2lcr(c, container_rootfs, container, &seccomp_conf);
|
lcr_conf = lcr_oci2lcr(c, container_rootfs, container, &seccomp_conf);
|
||||||
if (lcr_conf == NULL) {
|
if (lcr_conf == NULL) {
|
||||||
ERROR("Create distribution specific configuration failed");
|
ERROR("Create specific configuration failed");
|
||||||
goto out_free_conf;
|
goto out_free_conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -142,12 +142,9 @@ void lcr_containers_info_free(struct lcr_container_info **info_arr, size_t size)
|
|||||||
* param name : container name
|
* param name : container name
|
||||||
* param lcrpath: container path
|
* param lcrpath: container path
|
||||||
* param rootfs : the path of rootfs used for the container
|
* param rootfs : the path of rootfs used for the container
|
||||||
* param dist : the distribution for generate specification
|
|
||||||
* NOTE: if the dist is `none`, it will not create default spec
|
|
||||||
* param oci_config_data : json string of oci config data
|
* param oci_config_data : json string of oci config data
|
||||||
*/
|
*/
|
||||||
bool lcr_create(const char *name, const char *lcrpath, const char *rootfs,
|
bool lcr_create(const char *name, const char *lcrpath, const char *rootfs, const void *oci_config_data);
|
||||||
const char *dist, const void *oci_config_data);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start a container
|
* Start a container
|
||||||
@ -179,9 +176,7 @@ struct lcr_start_request {
|
|||||||
bool daemonize;
|
bool daemonize;
|
||||||
bool tty;
|
bool tty;
|
||||||
bool open_stdin;
|
bool open_stdin;
|
||||||
const char *pidfile;
|
|
||||||
const char **console_fifos;
|
const char **console_fifos;
|
||||||
const char *console_logpath;
|
|
||||||
uint32_t start_timeout;
|
uint32_t start_timeout;
|
||||||
const char *container_pidfile;
|
const char *container_pidfile;
|
||||||
const char *exit_fifo;
|
const char *exit_fifo;
|
||||||
@ -190,8 +185,6 @@ struct lcr_start_request {
|
|||||||
gid_t gid;
|
gid_t gid;
|
||||||
gid_t *additional_gids;
|
gid_t *additional_gids;
|
||||||
size_t additional_gids_len;
|
size_t additional_gids_len;
|
||||||
|
|
||||||
const char **share_ns;
|
|
||||||
};
|
};
|
||||||
bool lcr_start(const struct lcr_start_request *request);
|
bool lcr_start(const struct lcr_start_request *request);
|
||||||
|
|
||||||
@ -211,17 +204,6 @@ bool lcr_kill(const char *name, const char *lcrpath, uint32_t signal);
|
|||||||
*/
|
*/
|
||||||
bool lcr_delete(const char *name, const char *lcrpath);
|
bool lcr_delete(const char *name, const char *lcrpath);
|
||||||
|
|
||||||
/*
|
|
||||||
* Execute process inside a container
|
|
||||||
* param name : container name, required.
|
|
||||||
* param lcrpath : container path, set to NULL if you want use default lcrpath.
|
|
||||||
* param argc : the size of the argv array
|
|
||||||
* param argv : array of arguments to be execute inside container
|
|
||||||
* param pid : ID of process running inside container
|
|
||||||
*/
|
|
||||||
bool lcr_exec(const char *name, const char *lcrpath, int argc, char * const * argv, pid_t *pid);
|
|
||||||
|
|
||||||
|
|
||||||
bool lcr_clean(const char *name, const char *lcrpath, const char *logpath, const char *loglevel, pid_t pid);
|
bool lcr_clean(const char *name, const char *lcrpath, const char *logpath, const char *loglevel, pid_t pid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -275,26 +257,28 @@ void lcr_free_console_config(struct lcr_console_config *config);
|
|||||||
int lcr_log_init(const char *name, const char *file, const char *priority,
|
int lcr_log_init(const char *name, const char *file, const char *priority,
|
||||||
const char *prefix, int quiet, const char *lcrpath);
|
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;
|
||||||
|
};
|
||||||
/*
|
/*
|
||||||
* Execute process inside a container
|
* Execute process inside a container
|
||||||
* param name : container name, required.
|
|
||||||
* param lcrpath : container path, set to NULL if you want use default lcrpath.
|
|
||||||
* param stdinfd : stdinfd
|
|
||||||
* param stdoutfd : stdoutfd
|
|
||||||
* param stderrfd : stderrfd
|
|
||||||
* param escape : prefix for escape command, for example if escape equals 1 means the escape
|
|
||||||
* prefix is <CTRL+a>, you can type <CTRL+a q> to exit the console.
|
|
||||||
* -1 means never exit console by hand.
|
|
||||||
* param argc : the size of the argv array
|
|
||||||
* param argv : array of arguments to be execute inside container(terminated with "NULL")
|
|
||||||
* param env : array of environment variables to be set inside container(terminated with "NULL")
|
|
||||||
* param timeout : Timeout in seconds for attach container
|
|
||||||
* param pid : ID of process running inside container
|
|
||||||
* param exit_code : exit_code of process running inside container
|
|
||||||
*/
|
*/
|
||||||
bool lcr_attach(const char *name, const char *lcrpath, const char *logpath, const char *loglevel,
|
bool lcr_exec(const struct lcr_exec_request *request, int *exit_code);
|
||||||
const char *console_fifos[], char * const argv[], char * const env[],
|
|
||||||
int64_t timeout, pid_t *pid, int *exit_code);
|
|
||||||
|
|
||||||
bool lcr_update(const char *name, const char *lcrpath, const struct lcr_cgroup_resources *cr);
|
bool lcr_update(const char *name, const char *lcrpath, const struct lcr_cgroup_resources *cr);
|
||||||
|
|
||||||
|
|||||||
@ -887,27 +887,20 @@ void do_lcr_state(struct lxc_container *c, struct lcr_container_state *lcs)
|
|||||||
|
|
||||||
#define ExitSignalOffset 128
|
#define ExitSignalOffset 128
|
||||||
|
|
||||||
static void execute_lxc_attach(const char *name, const char *path, const char *logpath, const char *loglevel,
|
static void execute_lxc_attach(const char *name, const char *path, const struct lcr_exec_request *request)
|
||||||
const char *console_fifos[], const char * const argv[], const char * const env[],
|
|
||||||
int64_t timeout)
|
|
||||||
{
|
{
|
||||||
// should check the size of params when add new params.
|
// should check the size of params when add new params.
|
||||||
char **params = NULL;
|
char **params = NULL;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
size_t j = 0;
|
||||||
size_t args_len = PARAM_NUM;
|
size_t args_len = PARAM_NUM;
|
||||||
const char * const *tmp = NULL;
|
|
||||||
|
|
||||||
if (util_check_inherited(true, -1) != 0) {
|
if (util_check_inherited(true, -1) != 0) {
|
||||||
COMMAND_ERROR("Close inherited fds failed");
|
COMMAND_ERROR("Close inherited fds failed");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (tmp = env; tmp != NULL && *tmp != NULL; tmp++) {
|
args_len = args_len + request->args_len + request->env_len;
|
||||||
args_len++;
|
|
||||||
}
|
|
||||||
for (tmp = argv; tmp != NULL && *tmp != NULL; tmp++) {
|
|
||||||
args_len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args_len > (SIZE_MAX / sizeof(char *))) {
|
if (args_len > (SIZE_MAX / sizeof(char *))) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -924,29 +917,34 @@ static void execute_lxc_attach(const char *name, const char *path, const char *l
|
|||||||
add_array_elem(params, args_len, &i, "-P");
|
add_array_elem(params, args_len, &i, "-P");
|
||||||
add_array_elem(params, args_len, &i, path);
|
add_array_elem(params, args_len, &i, path);
|
||||||
add_array_elem(params, args_len, &i, "--clear-env");
|
add_array_elem(params, args_len, &i, "--clear-env");
|
||||||
add_array_kv(params, args_len, &i, "--logfile", logpath);
|
add_array_kv(params, args_len, &i, "--logfile", request->logpath);
|
||||||
add_array_kv(params, args_len, &i, "-l", loglevel);
|
add_array_kv(params, args_len, &i, "-l", request->loglevel);
|
||||||
add_array_kv(params, args_len, &i, "--in-fifo", console_fifos[0]);
|
add_array_kv(params, args_len, &i, "--in-fifo", request->console_fifos[0]);
|
||||||
add_array_kv(params, args_len, &i, "--out-fifo", console_fifos[1]);
|
add_array_kv(params, args_len, &i, "--out-fifo", request->console_fifos[1]);
|
||||||
for (tmp = env; tmp && *tmp; tmp++) {
|
for (j = 0; j < request->env_len; j++) {
|
||||||
add_array_elem(params, args_len, &i, "-v");
|
add_array_elem(params, args_len, &i, "-v");
|
||||||
add_array_elem(params, args_len, &i, *tmp);
|
add_array_elem(params, args_len, &i, request->env[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeout != 0) {
|
if (request->timeout != 0) {
|
||||||
char timeout_str[LCR_NUMSTRLEN64] = { 0 };
|
char timeout_str[LCR_NUMSTRLEN64] = { 0 };
|
||||||
add_array_elem(params, args_len, &i, "--timeout");
|
add_array_elem(params, args_len, &i, "--timeout");
|
||||||
if (sprintf_s(timeout_str, LCR_NUMSTRLEN64, "%lld", (long long)timeout) < 0) {
|
if (sprintf_s(timeout_str, LCR_NUMSTRLEN64, "%lld", (long long)request->timeout) < 0) {
|
||||||
COMMAND_ERROR("Invaild attach timeout value :%lld", (long long)timeout);
|
COMMAND_ERROR("Invaild attach timeout value :%lld", (long long)request->timeout);
|
||||||
free(params);
|
free(params);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
add_array_elem(params, args_len, &i, timeout_str);
|
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_elem(params, args_len, &i, "--");
|
add_array_elem(params, args_len, &i, "--");
|
||||||
for (tmp = argv; tmp && *tmp; tmp++) {
|
for (j = 0; j < request->args_len; j++) {
|
||||||
add_array_elem(params, args_len, &i, *tmp);
|
add_array_elem(params, args_len, &i, request->args[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
execvp("lxc-attach", params);
|
execvp("lxc-attach", params);
|
||||||
@ -974,9 +972,7 @@ static int do_attach_get_exit_code(int status)
|
|||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool do_attach(const char *name, const char *path, const char *logpath, const char *loglevel,
|
bool do_attach(const char *name, const char *path, const struct lcr_exec_request *request, int *exit_code)
|
||||||
const char *console_fifos[], const char * const argv[], const char * const env[], int64_t timeout,
|
|
||||||
pid_t *exec_pid, int *exit_code)
|
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
pid_t pid = 0;
|
pid_t pid = 0;
|
||||||
@ -1009,7 +1005,7 @@ bool do_attach(const char *name, const char *path, const char *logpath, const ch
|
|||||||
close(pipefd[0]);
|
close(pipefd[0]);
|
||||||
dup2(pipefd[1], 2);
|
dup2(pipefd[1], 2);
|
||||||
|
|
||||||
execute_lxc_attach(name, path, logpath, loglevel, console_fifos, argv, env, timeout);
|
execute_lxc_attach(name, path, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(pipefd[1]);
|
close(pipefd[1]);
|
||||||
@ -1039,10 +1035,7 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute_lxc_start(const char *name, const char *path, const char *logpath, const char *loglevel,
|
void execute_lxc_start(const char *name, const char *path, const struct lcr_start_request *request)
|
||||||
bool daemonize, bool tty, bool open_stdin, const char *pidfile,
|
|
||||||
const char *console_fifos[], const char *console_logpath, const char *share_ns[],
|
|
||||||
uint32_t start_timeout, const char *container_pidfile, const char *exit_fifo)
|
|
||||||
{
|
{
|
||||||
// should check the size of params when add new params.
|
// should check the size of params when add new params.
|
||||||
char *params[PARAM_NUM] = { NULL };
|
char *params[PARAM_NUM] = { NULL };
|
||||||
@ -1058,28 +1051,26 @@ void execute_lxc_start(const char *name, const char *path, const char *logpath,
|
|||||||
add_array_elem(params, PARAM_NUM, &i, "-P");
|
add_array_elem(params, PARAM_NUM, &i, "-P");
|
||||||
add_array_elem(params, PARAM_NUM, &i, path);
|
add_array_elem(params, PARAM_NUM, &i, path);
|
||||||
add_array_elem(params, PARAM_NUM, &i, "--quiet");
|
add_array_elem(params, PARAM_NUM, &i, "--quiet");
|
||||||
add_array_kv(params, PARAM_NUM, &i, "--logfile", logpath);
|
add_array_kv(params, PARAM_NUM, &i, "--logfile", request->logpath);
|
||||||
add_array_kv(params, PARAM_NUM, &i, "-l", loglevel);
|
add_array_kv(params, PARAM_NUM, &i, "-l", request->loglevel);
|
||||||
add_array_kv(params, PARAM_NUM, &i, "--in-fifo", console_fifos[0]);
|
add_array_kv(params, PARAM_NUM, &i, "--in-fifo", request->console_fifos[0]);
|
||||||
add_array_kv(params, PARAM_NUM, &i, "--out-fifo", console_fifos[1]);
|
add_array_kv(params, PARAM_NUM, &i, "--out-fifo", request->console_fifos[1]);
|
||||||
add_array_kv(params, PARAM_NUM, &i, "--err-fifo", console_fifos[2]);
|
add_array_kv(params, PARAM_NUM, &i, "--err-fifo", request->console_fifos[2]);
|
||||||
if (!tty) {
|
if (!request->tty) {
|
||||||
add_array_elem(params, PARAM_NUM, &i, "--disable-pty");
|
add_array_elem(params, PARAM_NUM, &i, "--disable-pty");
|
||||||
}
|
}
|
||||||
if (open_stdin) {
|
if (request->open_stdin) {
|
||||||
add_array_elem(params, PARAM_NUM, &i, "--open-stdin");
|
add_array_elem(params, PARAM_NUM, &i, "--open-stdin");
|
||||||
}
|
}
|
||||||
add_array_elem(params, PARAM_NUM, &i, daemonize ? "-d" : "-F");
|
add_array_elem(params, PARAM_NUM, &i, request->daemonize ? "-d" : "-F");
|
||||||
add_array_kv(params, PARAM_NUM, &i, "-p", pidfile);
|
add_array_kv(params, PARAM_NUM, &i, "--container-pidfile", request->container_pidfile);
|
||||||
add_array_kv(params, PARAM_NUM, &i, "-L", console_logpath);
|
add_array_kv(params, PARAM_NUM, &i, "--exit-fifo", request->exit_fifo);
|
||||||
add_array_kv(params, PARAM_NUM, &i, "--container-pidfile", container_pidfile);
|
|
||||||
add_array_kv(params, PARAM_NUM, &i, "--exit-fifo", exit_fifo);
|
|
||||||
|
|
||||||
if (start_timeout != 0) {
|
if (request->start_timeout != 0) {
|
||||||
char start_timeout_str[LCR_NUMSTRLEN64] = { 0 };
|
char start_timeout_str[LCR_NUMSTRLEN64] = { 0 };
|
||||||
add_array_elem(params, PARAM_NUM, &i, "--start-timeout");
|
add_array_elem(params, PARAM_NUM, &i, "--start-timeout");
|
||||||
if (sprintf_s(start_timeout_str, LCR_NUMSTRLEN64, "%u", start_timeout) < 0) {
|
if (sprintf_s(start_timeout_str, LCR_NUMSTRLEN64, "%u", request->start_timeout) < 0) {
|
||||||
COMMAND_ERROR("Invaild start timeout value: %u", start_timeout);
|
COMMAND_ERROR("Invaild start timeout value: %u", request->start_timeout);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
add_array_elem(params, PARAM_NUM, &i, start_timeout_str);
|
add_array_elem(params, PARAM_NUM, &i, start_timeout_str);
|
||||||
|
|||||||
@ -25,14 +25,9 @@ bool do_update(struct lxc_container *c, const char *name, const char *lcrpath, c
|
|||||||
|
|
||||||
void do_lcr_state(struct lxc_container *c, struct lcr_container_state *lcs);
|
void do_lcr_state(struct lxc_container *c, struct lcr_container_state *lcs);
|
||||||
|
|
||||||
bool do_attach(const char *name, const char *path, const char *logpath, const char *loglevel,
|
bool do_attach(const char *name, const char *path, const struct lcr_exec_request *request, int *exit_code);
|
||||||
const char *console_fifos[], const char * const argv[], const char * const env[], int64_t timeout,
|
|
||||||
pid_t *exec_pid, int *exit_code);
|
|
||||||
|
|
||||||
void execute_lxc_start(const char *name, const char *path, const char *logpath, const char *loglevel,
|
void execute_lxc_start(const char *name, const char *path, const struct lcr_start_request *request);
|
||||||
bool daemonize, bool tty, bool open_stdin, const char *pidfile,
|
|
||||||
const char *console_fifos[], const char *console_logpath, const char *share_ns[],
|
|
||||||
uint32_t start_timeout, const char *container_pidfile, const char *exit_fifo);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,142 +34,6 @@
|
|||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
|
|
||||||
#define COMMON_CONFIG_ITEMS \
|
|
||||||
{ .name = "lxc.tty.dir", .value = "lxc" /* Setup the LXC devices in /dev/lxc */ }, \
|
|
||||||
{ .name = "lxc.pty.max", .value = "1024" /* Allow for 1024 pseudo terminals */ }, \
|
|
||||||
{ .name = "lxc.tty.max", .value = "4" /* Setup 4 tty devices */ }, /* Drop some harmful capabilities */ \
|
|
||||||
{ .name = "lxc.cap.drop", .value = "mac_admin mac_override sys_time sys_module sys_rawio" }, \
|
|
||||||
{ .name = "lxc.cgroup.devices.deny", \
|
|
||||||
.value = "a" /* CGroup whitelist */ }, /* Allow any mknod (but not reading/writing the node */ \
|
|
||||||
{ .name = "lxc.cgroup.devices.allow", \
|
|
||||||
.value = "c *:* m" }, /* Allow any mknod (but not reading/writing the node */ \
|
|
||||||
{ .name = "lxc.cgroup.devices.allow", .value = "b *:* m" }, \
|
|
||||||
{ .name = "lxc.cgroup.devices.allow", .value = "c 1:3 rwm" /* Allow /dev/null */ }, \
|
|
||||||
{ .name = "lxc.cgroup.devices.allow", .value = "c 1:5 rwm" /* Allow /dev/zero */ }, \
|
|
||||||
{ .name = "lxc.cgroup.devices.allow", .value = "c 1:7 rwm" /* Allow /dev/full */ }, \
|
|
||||||
{ .name = "lxc.cgroup.devices.allow", .value = "c 5:0 rwm" /* Allow /dev/tty */ }, \
|
|
||||||
{ .name = "lxc.cgroup.devices.allow", .value = "c 5:1 rwm" /* Allow /dev/console */ }, \
|
|
||||||
{ .name = "lxc.cgroup.devices.allow", .value = "c 5:2 rwm" /* Allow /dev/ptmx */ }, \
|
|
||||||
{ .name = "lxc.cgroup.devices.allow", .value = "c 1:8 rwm" /* Allow /dev/random */ }, \
|
|
||||||
{ .name = "lxc.cgroup.devices.allow", .value = "c 1:9 rwm" /* Allow /dev/urandom */ }, \
|
|
||||||
{ .name = "lxc.cgroup.devices.allow", .value = "c 136:* rwm" /* Allow /dev/pts */ }, \
|
|
||||||
{ .name = "lxc.cgroup.devices.allow", .value = "c 10:229 rwm" /* Allow fuse */ }, \
|
|
||||||
{ .name = "lxc.mount.auto", .value = "cgroup:mixed proc:mixed sys:mixed" /* default mounts */ }, \
|
|
||||||
{ .name = "lxc.mount.entry", \
|
|
||||||
.value = "/sys/fs/fuse/connections sys/fs/fuse/connections non bind,optional 0 0" }, \
|
|
||||||
{ NULL, NULL }
|
|
||||||
|
|
||||||
static const lcr_config_item_t g_app_config_items[] = {
|
|
||||||
/* Container specific configuration */
|
|
||||||
{
|
|
||||||
.name = "lxc.arch",
|
|
||||||
.value = "x86_64",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "lxc.uts.name",
|
|
||||||
.value = "app",
|
|
||||||
},
|
|
||||||
/* Extra mount entries */
|
|
||||||
{
|
|
||||||
.name = "lxc.mount.entry",
|
|
||||||
.value = "/dev dev none ro,bind 0 0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "lxc.mount.entry",
|
|
||||||
.value = "/lib lib none ro,bind 0 0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "lxc.mount.entry",
|
|
||||||
.value = "/bin bin none ro,bind 0 0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "lxc.mount.entry",
|
|
||||||
.value = "/usr usr none ro,bind 0 0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "lxc.mount.entry",
|
|
||||||
.value = "/sbin sbin none ro,bind 0 0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "lxc.mount.entry",
|
|
||||||
.value = "tmpfs var/run tmpfs mode=0644 0 0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "lxc.mount.entry",
|
|
||||||
.value = "proc proc proc nodev,noexec,nosuid 0 0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "lxc.mount.entry",
|
|
||||||
.value = "sysfs sys sysfs ro,bind 0 0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "lxc.mount.entry",
|
|
||||||
.value = "/lib64 lib64 none ro,bind 0 0",
|
|
||||||
},
|
|
||||||
/* Include common config */
|
|
||||||
COMMON_CONFIG_ITEMS
|
|
||||||
};
|
|
||||||
|
|
||||||
static const lcr_config_item_t g_ubuntu_config_items[] = {
|
|
||||||
/* Container specific configuration */
|
|
||||||
{
|
|
||||||
.name = "lxc.arch",
|
|
||||||
.value = "x86_64"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "lxc.uts.name",
|
|
||||||
.value = "ubuntu",
|
|
||||||
},
|
|
||||||
/* Extra mount entries */
|
|
||||||
{
|
|
||||||
.name = "lxc.mount.entry",
|
|
||||||
.value = "/sys/kernel/debug sys/kernel/debug none bind,optional 0 0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "lxc.mount.entry",
|
|
||||||
.value = "/sys/kernel/security sys/kernel/security none bind,optional 0 0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "lxc.mount.entry",
|
|
||||||
.value = "/sys/fs/pstore sys/fs/pstore none bind,optional 0 0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "lxc.mount.entry",
|
|
||||||
.value = "mqueue dev/mqueue mqueue rw,realtime,create=dir,optional 0 0",
|
|
||||||
},
|
|
||||||
/* Extra cgroup device access */
|
|
||||||
{
|
|
||||||
.name = "lxc.cgroup.devices.allow",
|
|
||||||
.value = "c 254:0 rm",
|
|
||||||
}, /* rtc */
|
|
||||||
{
|
|
||||||
.name = "lxc.cgroup.devices.allow",
|
|
||||||
.value = "c 10:200 rwm",
|
|
||||||
}, /* tun */
|
|
||||||
{
|
|
||||||
.name = "lxc.cgroup.devices.allow",
|
|
||||||
.value = "c 10:228 rwm",
|
|
||||||
}, /* hpet */
|
|
||||||
{
|
|
||||||
.name = "lxc.cgroup.devices.allow",
|
|
||||||
.value = "c 10:232 rwm",
|
|
||||||
}, /* kvm */
|
|
||||||
/* Include common config */
|
|
||||||
COMMON_CONFIG_ITEMS
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char g_common_seccomp[] = "\
|
|
||||||
2\n\
|
|
||||||
blacklist\n\
|
|
||||||
reject_force_umount # comment this to allow umount -f; not recommended\n\
|
|
||||||
[all]\n\
|
|
||||||
kexec_load errno 1\n\
|
|
||||||
open_by_handle_at errno 1\n\
|
|
||||||
init_module errno 1\n\
|
|
||||||
finit_module errno 1\n\
|
|
||||||
delete_module errno 1\n\
|
|
||||||
";
|
|
||||||
|
|
||||||
static struct lxc_container *lcr_new_container(const char *name, const char *path)
|
static struct lxc_container *lcr_new_container(const char *name, const char *path)
|
||||||
{
|
{
|
||||||
struct lxc_container *c = lxc_container_new(name, path);
|
struct lxc_container *c = lxc_container_new(name, path);
|
||||||
@ -861,69 +725,6 @@ out_free:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool is_distribution_ubuntu(const char *distribution)
|
|
||||||
{
|
|
||||||
return strcmp("ubuntu", distribution) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool is_distribution_app(const char *distribution)
|
|
||||||
{
|
|
||||||
return strcmp("app", distribution) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct lcr_list *lcr_dist2spec(const char *distribution, char **seccomp_conf)
|
|
||||||
{
|
|
||||||
const lcr_config_item_t *items = NULL;
|
|
||||||
const lcr_config_item_t *i = NULL;
|
|
||||||
struct lcr_list *lcr_conf = NULL;
|
|
||||||
struct lcr_list *tmp = NULL;
|
|
||||||
|
|
||||||
if (seccomp_conf == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(*seccomp_conf);
|
|
||||||
*seccomp_conf = NULL;
|
|
||||||
|
|
||||||
/* get distribution specific configuration */
|
|
||||||
if (is_distribution_ubuntu(distribution)) {
|
|
||||||
items = g_ubuntu_config_items;
|
|
||||||
*seccomp_conf = util_strdup_s(g_common_seccomp);
|
|
||||||
} else if (is_distribution_app(distribution)) {
|
|
||||||
items = g_app_config_items;
|
|
||||||
} else {
|
|
||||||
ERROR("Distribution \"%s\" is not supported", distribution);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize the config list */
|
|
||||||
lcr_conf = util_common_calloc_s(sizeof(*lcr_conf));
|
|
||||||
if (lcr_conf == NULL) {
|
|
||||||
goto out_free;
|
|
||||||
}
|
|
||||||
lcr_list_init(lcr_conf);
|
|
||||||
|
|
||||||
/* add other config items to `lcr_conf` list */
|
|
||||||
for (i = items; i->name; i++) {
|
|
||||||
tmp = create_lcr_list_node(i->name, i->value);
|
|
||||||
if (tmp == NULL) {
|
|
||||||
goto out_free;
|
|
||||||
}
|
|
||||||
lcr_list_add_tail(lcr_conf, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return lcr_conf;
|
|
||||||
|
|
||||||
out_free:
|
|
||||||
ERROR("Failed translate dist to spec");
|
|
||||||
free(*seccomp_conf);
|
|
||||||
*seccomp_conf = NULL;
|
|
||||||
|
|
||||||
lcr_free_config(lcr_conf);
|
|
||||||
free(lcr_conf);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lcr_open_config_file(const char *bundle)
|
static int lcr_open_config_file(const char *bundle)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -69,14 +69,6 @@ struct lcr_list *lcr_oci2lcr(const struct lxc_container *c, const char *containe
|
|||||||
oci_runtime_spec *new_container,
|
oci_runtime_spec *new_container,
|
||||||
char **seccomp);
|
char **seccomp);
|
||||||
|
|
||||||
/*
|
|
||||||
* Generate lcr_config_info according to distribution.
|
|
||||||
* param distribution : system distribution, now support: ubuntu
|
|
||||||
* param seccomp_conf [out] : return seccomp configuration if needed.
|
|
||||||
* return: a linked list
|
|
||||||
*/
|
|
||||||
struct lcr_list *lcr_dist2spec(const char *distribution, char **seccomp_conf);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a new specification file
|
* Create a new specification file
|
||||||
* param name : container name, required.
|
* param name : container name, required.
|
||||||
|
|||||||
180
src/log.c
180
src/log.c
@ -34,6 +34,20 @@ const char * const g_engine_log_prio_name[] = {
|
|||||||
"NOTICE", "INFO", "DEBUG", "TRACE"
|
"NOTICE", "INFO", "DEBUG", "TRACE"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* predefined priorities. */
|
||||||
|
enum engine_log_priority {
|
||||||
|
LOG_PRIORITY_FATAL = LOG_EMERG,
|
||||||
|
LOG_PRIORITY_ALERT = LOG_ALERT,
|
||||||
|
LOG_PRIORITY_CRIT = LOG_CRIT,
|
||||||
|
LOG_PRIORITY_ERROR = LOG_ERR,
|
||||||
|
LOG_PRIORITY_WARN = LOG_WARNING,
|
||||||
|
LOG_PRIORITY_NOTICE = LOG_NOTICE,
|
||||||
|
LOG_PRIORITY_INFO = LOG_INFO,
|
||||||
|
LOG_PRIORITY_DEBUG = LOG_DEBUG,
|
||||||
|
LOG_PRIORITY_TRACE,
|
||||||
|
LOG_PRIORITY_MAX
|
||||||
|
};
|
||||||
|
|
||||||
#define MAX_MSG_LENGTH 4096
|
#define MAX_MSG_LENGTH 4096
|
||||||
#define MAX_LOG_PREFIX_LENGTH 15
|
#define MAX_LOG_PREFIX_LENGTH 15
|
||||||
|
|
||||||
@ -41,7 +55,7 @@ static __thread char *g_engine_log_prefix = NULL;
|
|||||||
|
|
||||||
static char *g_engine_log_vmname = NULL;
|
static char *g_engine_log_vmname = NULL;
|
||||||
static bool g_engine_log_quiet = false;
|
static bool g_engine_log_quiet = false;
|
||||||
static int g_engine_log_level = ENGINE_LOG_DEBUG;
|
static int g_engine_log_level = LOG_PRIORITY_DEBUG;
|
||||||
static int g_engine_log_driver = LOG_DRIVER_STDOUT;
|
static int g_engine_log_driver = LOG_DRIVER_STDOUT;
|
||||||
int g_engine_log_fd = -1;
|
int g_engine_log_fd = -1;
|
||||||
|
|
||||||
@ -67,8 +81,9 @@ void engine_free_log_prefix()
|
|||||||
|
|
||||||
ssize_t write_nointr(int fd, const void *buf, size_t count);
|
ssize_t write_nointr(int fd, const void *buf, size_t count);
|
||||||
|
|
||||||
void log_append_logfile(const struct engine_log_object_metadata *meta, const char *timestamp, const char *msg);
|
void log_append_logfile(const struct engine_log_event *event, const char *timestamp, const char *msg);
|
||||||
void log_append_stderr(const struct engine_log_object_metadata *meta, const char *timestamp, const char *msg);
|
void log_append_stderr(const struct engine_log_event *event, const char *timestamp, const char *msg);
|
||||||
|
int engine_unix_trans_to_utc(char *buf, size_t bufsize, const struct timespec *time);
|
||||||
|
|
||||||
/* engine change str logdriver to enum */
|
/* engine change str logdriver to enum */
|
||||||
int engine_change_str_logdriver_to_enum(const char *driver)
|
int engine_change_str_logdriver_to_enum(const char *driver)
|
||||||
@ -129,14 +144,14 @@ static int init_log_driver(const struct engine_log_config *log)
|
|||||||
{
|
{
|
||||||
int i, driver;
|
int i, driver;
|
||||||
|
|
||||||
for (i = ENGINE_LOG_FATAL; i < ENGINE_LOG_MAX; i++) {
|
for (i = LOG_PRIORITY_FATAL; i < LOG_PRIORITY_MAX; i++) {
|
||||||
if (!strcasecmp(g_engine_log_prio_name[i], log->priority)) {
|
if (!strcasecmp(g_engine_log_prio_name[i], log->priority)) {
|
||||||
g_engine_log_level = i;
|
g_engine_log_level = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == ENGINE_LOG_MAX) {
|
if (i == LOG_PRIORITY_MAX) {
|
||||||
fprintf(stderr, "Unable to parse logging level:%s\n", log->priority);
|
fprintf(stderr, "Unable to parse logging level:%s\n", log->priority);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -209,43 +224,14 @@ out:
|
|||||||
return nret;
|
return nret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *parse_timespec_to_human()
|
|
||||||
{
|
|
||||||
struct timespec timestamp;
|
|
||||||
struct tm ptm = { 0 };
|
|
||||||
char date_time[ENGINE_LOG_TIME_SIZE] = { 0 };
|
|
||||||
int nret;
|
|
||||||
|
|
||||||
if (clock_gettime(CLOCK_REALTIME, ×tamp) == -1) {
|
|
||||||
fprintf(stderr, "Failed to get real time\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (localtime_r(&(timestamp.tv_sec), &ptm) == NULL) {
|
|
||||||
SYSERROR("Transfer timespec failed");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
nret = sprintf_s(date_time, ENGINE_LOG_TIME_SIZE, "%04d%02d%02d%02d%02d%02d.%03ld",
|
|
||||||
ptm.tm_year + 1900, ptm.tm_mon + 1, ptm.tm_mday, ptm.tm_hour, ptm.tm_min, ptm.tm_sec,
|
|
||||||
timestamp.tv_nsec / 1000000);
|
|
||||||
|
|
||||||
if (nret < 0) {
|
|
||||||
COMMAND_ERROR("Sprintf failed");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return util_strdup_s(date_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* engine log append */
|
/* engine log append */
|
||||||
int engine_log_append(const struct engine_log_object_metadata *meta, const char *format, ...)
|
int engine_log_append(const struct engine_log_event *event, const char *format, ...)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
va_list args;
|
va_list args;
|
||||||
char msg[MAX_MSG_LENGTH] = { 0 };
|
char msg[MAX_MSG_LENGTH] = { 0 };
|
||||||
char *date_time = NULL;
|
char date_time[ENGINE_LOG_TIME_SIZE] = { 0 };
|
||||||
int ret = 0;
|
struct timespec timestamp;
|
||||||
|
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
rc = vsprintf_s(msg, MAX_MSG_LENGTH, format, args);
|
rc = vsprintf_s(msg, MAX_MSG_LENGTH, format, args);
|
||||||
@ -257,9 +243,12 @@ int engine_log_append(const struct engine_log_object_metadata *meta, const char
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
date_time = parse_timespec_to_human();
|
if (clock_gettime(CLOCK_REALTIME, ×tamp) == -1) {
|
||||||
if (date_time == NULL) {
|
fprintf(stderr, "Failed to get real time\n");
|
||||||
goto out;
|
return 0;
|
||||||
|
}
|
||||||
|
if (engine_unix_trans_to_utc(date_time, ENGINE_LOG_TIME_SIZE, ×tamp) < 0) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (g_engine_log_driver) {
|
switch (g_engine_log_driver) {
|
||||||
@ -267,31 +256,27 @@ int engine_log_append(const struct engine_log_object_metadata *meta, const char
|
|||||||
if (g_engine_log_quiet) {
|
if (g_engine_log_quiet) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
log_append_stderr(meta, date_time, msg);
|
log_append_stderr(event, date_time, msg);
|
||||||
break;
|
break;
|
||||||
case LOG_DRIVER_FIFO:
|
case LOG_DRIVER_FIFO:
|
||||||
if (g_engine_log_fd == -1) {
|
if (g_engine_log_fd == -1) {
|
||||||
fprintf(stderr, "Do not set log file\n");
|
fprintf(stderr, "Do not set log file\n");
|
||||||
ret = -1;
|
return -1;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
log_append_logfile(meta, date_time, msg);
|
log_append_logfile(event, date_time, msg);
|
||||||
break;
|
break;
|
||||||
case LOG_DRIVER_NOSET:
|
case LOG_DRIVER_NOSET:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Invalid log driver\n");
|
fprintf(stderr, "Invalid log driver\n");
|
||||||
ret = -1;
|
return -1;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
return 0;
|
||||||
free(date_time);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* log append logfile */
|
/* log append logfile */
|
||||||
void log_append_logfile(const struct engine_log_object_metadata *meta, const char *timestamp, const char *msg)
|
void log_append_logfile(const struct engine_log_event *event, const char *timestamp, const char *msg)
|
||||||
{
|
{
|
||||||
char log_buffer[ENGINE_LOG_BUFFER_SIZE] = { 0 };
|
char log_buffer[ENGINE_LOG_BUFFER_SIZE] = { 0 };
|
||||||
int log_fd = -1;
|
int log_fd = -1;
|
||||||
@ -299,7 +284,7 @@ void log_append_logfile(const struct engine_log_object_metadata *meta, const cha
|
|||||||
size_t size;
|
size_t size;
|
||||||
char *tmp_prefix = NULL;
|
char *tmp_prefix = NULL;
|
||||||
|
|
||||||
if (meta->level > g_engine_log_level) {
|
if (event->priority > g_engine_log_level) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log_fd = g_engine_log_fd;
|
log_fd = g_engine_log_fd;
|
||||||
@ -312,15 +297,15 @@ void log_append_logfile(const struct engine_log_object_metadata *meta, const cha
|
|||||||
tmp_prefix = tmp_prefix + (strlen(tmp_prefix) - MAX_LOG_PREFIX_LENGTH);
|
tmp_prefix = tmp_prefix + (strlen(tmp_prefix) - MAX_LOG_PREFIX_LENGTH);
|
||||||
}
|
}
|
||||||
nret = sprintf_s(log_buffer, sizeof(log_buffer), "%15s %s %-8s %s - %s:%s:%d - %s", tmp_prefix ? tmp_prefix : "",
|
nret = sprintf_s(log_buffer, sizeof(log_buffer), "%15s %s %-8s %s - %s:%s:%d - %s", tmp_prefix ? tmp_prefix : "",
|
||||||
timestamp, g_engine_log_prio_name[meta->level],
|
timestamp, g_engine_log_prio_name[event->priority],
|
||||||
g_engine_log_vmname ? g_engine_log_vmname : "engine", meta->file, meta->func,
|
g_engine_log_vmname ? g_engine_log_vmname : "engine", event->locinfo->file, event->locinfo->func,
|
||||||
meta->line, msg);
|
event->locinfo->line, msg);
|
||||||
|
|
||||||
if (nret < 0) {
|
if (nret < 0) {
|
||||||
nret = sprintf_s(log_buffer, sizeof(log_buffer), "%15s %s %-8s %s - %s:%s:%d - %s",
|
nret = sprintf_s(log_buffer, sizeof(log_buffer), "%15s %s %-8s %s - %s:%s:%d - %s",
|
||||||
tmp_prefix ? tmp_prefix : "", timestamp, g_engine_log_prio_name[meta->level],
|
tmp_prefix ? tmp_prefix : "", timestamp, g_engine_log_prio_name[event->priority],
|
||||||
g_engine_log_vmname ? g_engine_log_vmname : "engine", meta->file,
|
g_engine_log_vmname ? g_engine_log_vmname : "engine", event->locinfo->file,
|
||||||
meta->func, meta->line, "Large log message");
|
event->locinfo->func, event->locinfo->line, "Large log message");
|
||||||
if (nret < 0) {
|
if (nret < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -339,10 +324,10 @@ void log_append_logfile(const struct engine_log_object_metadata *meta, const cha
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* log append stderr */
|
/* log append stderr */
|
||||||
void log_append_stderr(const struct engine_log_object_metadata *meta, const char *timestamp, const char *msg)
|
void log_append_stderr(const struct engine_log_event *event, const char *timestamp, const char *msg)
|
||||||
{
|
{
|
||||||
char *tmp_prefix = NULL;
|
char *tmp_prefix = NULL;
|
||||||
if (meta->level > g_engine_log_level) {
|
if (event->priority > g_engine_log_level) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,13 +335,86 @@ void log_append_stderr(const struct engine_log_object_metadata *meta, const char
|
|||||||
if (tmp_prefix != NULL && strlen(tmp_prefix) > MAX_LOG_PREFIX_LENGTH) {
|
if (tmp_prefix != NULL && strlen(tmp_prefix) > MAX_LOG_PREFIX_LENGTH) {
|
||||||
tmp_prefix = tmp_prefix + (strlen(tmp_prefix) - MAX_LOG_PREFIX_LENGTH);
|
tmp_prefix = tmp_prefix + (strlen(tmp_prefix) - MAX_LOG_PREFIX_LENGTH);
|
||||||
}
|
}
|
||||||
fprintf(stderr, "%15s %s %-8s ", tmp_prefix ? tmp_prefix : "", timestamp, g_engine_log_prio_name[meta->level]);
|
fprintf(stderr, "%15s %s %-8s ", tmp_prefix ? tmp_prefix : "", timestamp, g_engine_log_prio_name[event->priority]);
|
||||||
fprintf(stderr, "%s - ", g_engine_log_vmname ? g_engine_log_vmname : "engine");
|
fprintf(stderr, "%s - ", g_engine_log_vmname ? g_engine_log_vmname : "engine");
|
||||||
fprintf(stderr, "%s:%s:%d - ", meta->file, meta->func, meta->line);
|
fprintf(stderr, "%s:%s:%d - ", event->locinfo->file, event->locinfo->func, event->locinfo->line);
|
||||||
fprintf(stderr, "%s", msg);
|
fprintf(stderr, "%s", msg);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* engine unix trans to utc */
|
||||||
|
int engine_unix_trans_to_utc(char *buf, size_t bufsize, const struct timespec *time)
|
||||||
|
{
|
||||||
|
int64_t trans_to_days, all_days, age, doa, yoa, doy, nom, hours_to_sec, trans_to_sec;
|
||||||
|
int64_t real_year, real_day, real_month, real_hours, real_minutes, real_seconds;
|
||||||
|
char ns[LCR_NUMSTRLEN64] = { 0 };
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Transtate seconds to number of days. */
|
||||||
|
trans_to_days = time->tv_sec / 86400;
|
||||||
|
|
||||||
|
/* Calculate days from 0000-03-01 to 1970-01-01.Days base it */
|
||||||
|
all_days = trans_to_days + 719468;
|
||||||
|
|
||||||
|
/* compute the age.One age means 400 years(146097 days) */
|
||||||
|
age = (all_days >= 0 ? all_days : all_days - 146096) / 146097;
|
||||||
|
|
||||||
|
/* The day-of-age (doa) can then be found by subtracting the genumber */
|
||||||
|
doa = (all_days - age * 146097);
|
||||||
|
|
||||||
|
/* Calculate year-of-age (yoa, range [0, 399]) */
|
||||||
|
yoa = ((doa - doa / 1460) + (doa / 36524 - doa / 146096)) / 365;
|
||||||
|
|
||||||
|
/* Compute the year this moment */
|
||||||
|
real_year = yoa + age * 400;
|
||||||
|
|
||||||
|
/* Calculate the day-of-year */
|
||||||
|
doy = doa - (365 * yoa + yoa / 4 - yoa / 100);
|
||||||
|
|
||||||
|
/* Compute the month number. */
|
||||||
|
nom = (5 * doy + 2) / 153;
|
||||||
|
|
||||||
|
/* Compute the real_day. */
|
||||||
|
real_day = (doy - (153 * nom + 2) / 5) + 1;
|
||||||
|
|
||||||
|
/* Compute the correct month. */
|
||||||
|
real_month = nom + (nom < 10 ? 3 : -9);
|
||||||
|
|
||||||
|
/* Add one year before March */
|
||||||
|
if (real_month < 3) {
|
||||||
|
real_year++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Translate days in the age to seconds. */
|
||||||
|
trans_to_sec = trans_to_days * 86400;
|
||||||
|
|
||||||
|
/* Compute the real_hours */
|
||||||
|
real_hours = (time->tv_sec - trans_to_sec) / 3600;
|
||||||
|
|
||||||
|
/* Translate the real hours to seconds. */
|
||||||
|
hours_to_sec = real_hours * 3600;
|
||||||
|
|
||||||
|
/* Calculate the real minutes */
|
||||||
|
real_minutes = ((time->tv_sec - trans_to_sec) - hours_to_sec) / 60;
|
||||||
|
|
||||||
|
/* Calculate the real seconds */
|
||||||
|
real_seconds = (((time->tv_sec - trans_to_sec) - hours_to_sec) - (real_minutes * 60));
|
||||||
|
|
||||||
|
ret = sprintf_s(ns, LCR_NUMSTRLEN64, "%ld", time->tv_nsec);
|
||||||
|
if (ret < 0 || ret >= LCR_NUMSTRLEN64) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the final timestamp */
|
||||||
|
ret = sprintf_s(buf, bufsize, "%" PRId64 "%02" PRId64 "%02" PRId64 "%02" PRId64 "%02" PRId64 "%02" PRId64 ".%.3s",
|
||||||
|
real_year, real_month, real_day, real_hours, real_minutes, real_seconds, ns);
|
||||||
|
if (ret < 0 || (size_t)ret >= bufsize) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* write nointr */
|
/* write nointr */
|
||||||
ssize_t write_nointr(int fd, const void *buf, size_t count)
|
ssize_t write_nointr(int fd, const void *buf, size_t count)
|
||||||
{
|
{
|
||||||
|
|||||||
111
src/log.h
111
src/log.h
@ -15,7 +15,9 @@
|
|||||||
#ifndef __LCR_LOG_H
|
#ifndef __LCR_LOG_H
|
||||||
#define __LCR_LOG_H
|
#define __LCR_LOG_H
|
||||||
|
|
||||||
|
#include <syslog.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
@ -44,22 +46,10 @@ extern "C" {
|
|||||||
#define DAEMON_ERROR_GRPC_CONNENCT_STR "Can not connect with server.Is the docker dameon running on the host?"
|
#define DAEMON_ERROR_GRPC_CONNENCT_STR "Can not connect with server.Is the docker dameon running on the host?"
|
||||||
#define DAEMON_ERROR_GRPC_SERVER_STR "Server internal error"
|
#define DAEMON_ERROR_GRPC_SERVER_STR "Server internal error"
|
||||||
|
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
enum g_engine_log_driver {
|
enum g_engine_log_driver {
|
||||||
LOG_DRIVER_STDOUT,
|
LOG_DRIVER_STDOUT,
|
||||||
LOG_DRIVER_FIFO,
|
LOG_DRIVER_FIFO,
|
||||||
|
LOG_DRIVER_SYSLOG,
|
||||||
LOG_DRIVER_NOSET,
|
LOG_DRIVER_NOSET,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -72,21 +62,23 @@ struct engine_log_config {
|
|||||||
bool quiet;
|
bool quiet;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ENGINE_LOG_LOCINFO_INIT \
|
/* location information of the logging event */
|
||||||
{ \
|
struct engine_log_locinfo {
|
||||||
.file = __FILE__, .func = __func__, .line = __LINE__, \
|
|
||||||
}
|
|
||||||
|
|
||||||
/* brief logging object metadata */
|
|
||||||
struct engine_log_object_metadata {
|
|
||||||
int level;
|
|
||||||
|
|
||||||
/* location information of the logging item */
|
|
||||||
const char *file;
|
const char *file;
|
||||||
const char *func;
|
const char *func;
|
||||||
int line;
|
int line;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define ENGINE_LOG_LOCINFO_INIT \
|
||||||
|
{ \
|
||||||
|
.file = __FILE__, .func = __func__, .line = __LINE__, \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* brief logging event object */
|
||||||
|
struct engine_log_event {
|
||||||
|
int priority;
|
||||||
|
struct engine_log_locinfo *locinfo;
|
||||||
|
};
|
||||||
extern void engine_close_log_file();
|
extern void engine_close_log_file();
|
||||||
int log_enable(const struct engine_log_config *log);
|
int log_enable(const struct engine_log_config *log);
|
||||||
|
|
||||||
@ -96,38 +88,79 @@ void engine_free_log_prefix();
|
|||||||
|
|
||||||
int engine_change_str_logdriver_to_enum(const char *driver);
|
int engine_change_str_logdriver_to_enum(const char *driver);
|
||||||
|
|
||||||
int engine_log_append(const struct engine_log_object_metadata *event, const char *format, ...);
|
int engine_log_append(const struct engine_log_event *event, const char *format, ...);
|
||||||
|
|
||||||
#define COMMON_LOG(loglevel, format, ...) \
|
|
||||||
do { \
|
|
||||||
struct engine_log_object_metadata meta = ENGINE_LOG_LOCINFO_INIT; \
|
|
||||||
meta.level = loglevel; \
|
|
||||||
(void)engine_log_append(&meta, format, ##__VA_ARGS__); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define DEBUG(format, ...) \
|
#define DEBUG(format, ...) \
|
||||||
COMMON_LOG(ENGINE_LOG_FATAL, format, ##__VA_ARGS__);
|
do { \
|
||||||
|
struct engine_log_locinfo locinfo = ENGINE_LOG_LOCINFO_INIT; \
|
||||||
|
struct engine_log_event event; \
|
||||||
|
event.locinfo = &locinfo; \
|
||||||
|
event.priority = LOG_DEBUG; \
|
||||||
|
(void)engine_log_append(&event, format, ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define INFO(format, ...) \
|
#define INFO(format, ...) \
|
||||||
COMMON_LOG(ENGINE_LOG_INFO, format, ##__VA_ARGS__);
|
do { \
|
||||||
|
struct engine_log_locinfo locinfo = ENGINE_LOG_LOCINFO_INIT; \
|
||||||
|
struct engine_log_event event; \
|
||||||
|
event.locinfo = &locinfo; \
|
||||||
|
event.priority = LOG_INFO; \
|
||||||
|
(void)engine_log_append(&event, format, ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define NOTICE(format, ...) \
|
#define NOTICE(format, ...) \
|
||||||
COMMON_LOG(ENGINE_LOG_NOTICE, format, ##__VA_ARGS__);
|
do { \
|
||||||
|
struct engine_log_locinfo locinfo = ENGINE_LOG_LOCINFO_INIT; \
|
||||||
|
struct engine_log_event event; \
|
||||||
|
event.locinfo = &locinfo; \
|
||||||
|
event.priority = LOG_NOTICE; \
|
||||||
|
(void)engine_log_append(&event, format, ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define WARN(format, ...) \
|
#define WARN(format, ...) \
|
||||||
COMMON_LOG(ENGINE_LOG_WARN, format, ##__VA_ARGS__);
|
do { \
|
||||||
|
struct engine_log_locinfo locinfo = ENGINE_LOG_LOCINFO_INIT; \
|
||||||
|
struct engine_log_event event; \
|
||||||
|
event.locinfo = &locinfo; \
|
||||||
|
event.priority = LOG_WARNING; \
|
||||||
|
(void)engine_log_append(&event, format, ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define ERROR(format, ...) \
|
#define ERROR(format, ...) \
|
||||||
COMMON_LOG(ENGINE_LOG_ERROR, format, ##__VA_ARGS__);
|
do { \
|
||||||
|
struct engine_log_locinfo locinfo = ENGINE_LOG_LOCINFO_INIT; \
|
||||||
|
struct engine_log_event event; \
|
||||||
|
event.locinfo = &locinfo; \
|
||||||
|
event.priority = LOG_ERR; \
|
||||||
|
(void)engine_log_append(&event, format, ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define CRIT(format, ...) \
|
#define CRIT(format, ...) \
|
||||||
COMMON_LOG(ENGINE_LOG_CRIT, format, ##__VA_ARGS__);
|
do { \
|
||||||
|
struct engine_log_locinfo locinfo = ENGINE_LOG_LOCINFO_INIT; \
|
||||||
|
struct engine_log_event event; \
|
||||||
|
event.locinfo = &locinfo; \
|
||||||
|
event.priority = LOG_CRIT; \
|
||||||
|
(void)engine_log_append(&event, format, ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define ALERT(format, ...) \
|
#define ALERT(format, ...) \
|
||||||
COMMON_LOG(ENGINE_LOG_ALERT, format, ##__VA_ARGS__);
|
do { \
|
||||||
|
struct engine_log_locinfo locinfo = ENGINE_LOG_LOCINFO_INIT; \
|
||||||
|
struct engine_log_event event; \
|
||||||
|
event.locinfo = &locinfo; \
|
||||||
|
event.priority = LOG_ALERT; \
|
||||||
|
(void)engine_log_append(&event, format, ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define FATAL(format, ...) \
|
#define FATAL(format, ...) \
|
||||||
COMMON_LOG(ENGINE_LOG_FATAL, format, ##__VA_ARGS__);
|
do { \
|
||||||
|
struct engine_log_locinfo locinfo = ENGINE_LOG_LOCINFO_INIT; \
|
||||||
|
struct engine_log_event event; \
|
||||||
|
event.locinfo = &locinfo; \
|
||||||
|
event.priority = LOG_EMERG; \
|
||||||
|
(void)engine_log_append(&event, format, ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define SYSERROR(format, ...) \
|
#define SYSERROR(format, ...) \
|
||||||
do { \
|
do { \
|
||||||
|
|||||||
20
src/utils.c
20
src/utils.c
@ -1003,27 +1003,26 @@ FILE *util_fopen(const char *filename, const char *mode)
|
|||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* util safe int*/
|
int util_safe_int(const char *num_str, int *converted)
|
||||||
int util_safe_int(const char *numstr, int *converted)
|
|
||||||
{
|
{
|
||||||
char *err_str = NULL;
|
char *err_str = NULL;
|
||||||
signed long int li;
|
signed long int li;
|
||||||
|
|
||||||
if (numstr == NULL || converted == NULL) {
|
if (num_str == NULL || converted == NULL) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
li = strtol(numstr, &err_str, 0);
|
li = strtol(num_str, &err_str, 0);
|
||||||
if (errno > 0) {
|
if (errno > 0) {
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_invalid_error_str(err_str, numstr)) {
|
if (is_invalid_error_str(err_str, num_str)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (li > INT_MAX) {
|
if (li > INT_MAX || li < INT_MIN) {
|
||||||
return -ERANGE;
|
return -ERANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1251,7 +1250,6 @@ void util_free_array(char **array)
|
|||||||
{
|
{
|
||||||
char **p = NULL;
|
char **p = NULL;
|
||||||
|
|
||||||
/* free a null pointer may cause codex error */
|
|
||||||
if (array == NULL) {
|
if (array == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1480,7 +1478,7 @@ int util_null_stdfds(void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool util_copy_file(const char *src_file, const char *dst_file)
|
bool util_copy_file(const char *src_file, const char *dst_file, mode_t mode)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
char *nret = NULL;
|
char *nret = NULL;
|
||||||
@ -1502,7 +1500,7 @@ bool util_copy_file(const char *src_file, const char *dst_file)
|
|||||||
ERROR("Open src file: %s, failed: %s", real_src_file, strerror(errno));
|
ERROR("Open src file: %s, failed: %s", real_src_file, strerror(errno));
|
||||||
goto free_out;
|
goto free_out;
|
||||||
}
|
}
|
||||||
dst_fd = util_open(dst_file, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_SECURE_FILE_MODE);
|
dst_fd = util_open(dst_file, O_WRONLY | O_CREAT | O_TRUNC, mode);
|
||||||
if (dst_fd < 0) {
|
if (dst_fd < 0) {
|
||||||
ERROR("Creat file: %s, failed: %s", dst_file, strerror(errno));
|
ERROR("Creat file: %s, failed: %s", dst_file, strerror(errno));
|
||||||
goto free_out;
|
goto free_out;
|
||||||
@ -1531,7 +1529,7 @@ free_out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool util_write_file(const char *filepath, const char *content, size_t len, bool add_newline)
|
bool util_write_file(const char *filepath, const char *content, size_t len, bool add_newline, mode_t mode)
|
||||||
{
|
{
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
int rfd = -1;
|
int rfd = -1;
|
||||||
@ -1540,7 +1538,7 @@ bool util_write_file(const char *filepath, const char *content, size_t len, bool
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rfd = util_open(filepath, O_CREAT | O_TRUNC | O_WRONLY, CONFIG_FILE_MODE);
|
rfd = util_open(filepath, O_CREAT | O_TRUNC | O_WRONLY, mode);
|
||||||
if (rfd == -1) {
|
if (rfd == -1) {
|
||||||
ERROR("Create file %s failed: %s", filepath, strerror(errno));
|
ERROR("Create file %s failed: %s", filepath, strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -198,9 +198,9 @@ int util_safe_llong(const char *numstr, long long *converted);
|
|||||||
char *util_strdup_s(const char *src);
|
char *util_strdup_s(const char *src);
|
||||||
int util_null_stdfds(void);
|
int util_null_stdfds(void);
|
||||||
|
|
||||||
bool util_copy_file(const char *src_file, const char *dst_file);
|
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);
|
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);
|
int util_atomic_write_file(const char *filepath, const char *content);
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2019-2019. All rights reserved.
|
* Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved.
|
||||||
* lcr licensed under the Mulan PSL v1.
|
* lcr licensed under the Mulan PSL v1.
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
* You may obtain a copy of Mulan PSL v1 at:
|
||||||
|
|||||||
14
test/llt.sh
14
test/llt.sh
@ -1,3 +1,17 @@
|
|||||||
|
#######################################################################
|
||||||
|
##- @Copyright (C) Huawei Technologies., Ltd. 2019. All rights reserved.
|
||||||
|
# - lcr licensed under the Mulan PSL v1.
|
||||||
|
# - You can use this software according to the terms and conditions of the Mulan PSL v1.
|
||||||
|
# - You may obtain a copy of Mulan PSL v1 at:
|
||||||
|
# - http://license.coscl.org.cn/MulanPSL
|
||||||
|
# - 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 v1 for more details.
|
||||||
|
##- @Description: generate cetification
|
||||||
|
##- @Author: wujing
|
||||||
|
##- @Create: 2019-04-25
|
||||||
|
#######################################################################
|
||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
|
|
||||||
#set -xe
|
#set -xe
|
||||||
|
|||||||
@ -6,6 +6,7 @@ add_executable(${EXE}
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/../../src/utils.c
|
${CMAKE_CURRENT_SOURCE_DIR}/../../src/utils.c
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/../../src/log.c
|
${CMAKE_CURRENT_SOURCE_DIR}/../../src/log.c
|
||||||
${CMAKE_BINARY_DIR}/json/json_common.c
|
${CMAKE_BINARY_DIR}/json/json_common.c
|
||||||
|
utils_convert_llt.cc
|
||||||
utils_llt.cc)
|
utils_llt.cc)
|
||||||
|
|
||||||
target_include_directories(${EXE} PUBLIC
|
target_include_directories(${EXE} PUBLIC
|
||||||
|
|||||||
186
test/utils/utils_convert_llt.cc
Normal file
186
test/utils/utils_convert_llt.cc
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved.
|
||||||
|
* lcr licensed under the Mulan PSL v1.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
||||||
|
* You may obtain a copy of Mulan PSL v1 at:
|
||||||
|
* http://license.coscl.org.cn/MulanPSL
|
||||||
|
* 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 v1 for more details.
|
||||||
|
* Description: utils_convert llt
|
||||||
|
* Author: tanyifeng
|
||||||
|
* Create: 2019-07-08
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <climits>
|
||||||
|
#include <securec.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include "mock.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
TEST(utils_convert, test_util_safe_int)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int converted;
|
||||||
|
ret = util_safe_int("123456", &converted);
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
ASSERT_EQ(converted, 123456);
|
||||||
|
|
||||||
|
ret = util_safe_int("123456", NULL);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_int("-123456", &converted);
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
ASSERT_EQ(converted, -123456);
|
||||||
|
|
||||||
|
ret = util_safe_int("0", &converted);
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
ASSERT_EQ(converted, 0);
|
||||||
|
|
||||||
|
ret = util_safe_int("1.23", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_int("1x", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_int(std::to_string((long long)INT_MIN - 1).c_str(), &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_int(std::to_string((long long)INT_MAX + 1).c_str(), &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_int("NULL", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(utils_convert, test_util_safe_uint)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
unsigned int converted;
|
||||||
|
ret = util_safe_uint("123456", &converted);
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
ASSERT_EQ(converted, 123456);
|
||||||
|
|
||||||
|
ret = util_safe_uint("123456", NULL);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_uint("-123456", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_uint("0", &converted);
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
ASSERT_EQ(converted, 0);
|
||||||
|
|
||||||
|
ret = util_safe_uint("1.23", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_uint("1x", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_uint(std::to_string((long long)UINT_MAX + 1).c_str(), &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_uint("NULL", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(utils_convert, test_util_safe_llong)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
long long converted;
|
||||||
|
ret = util_safe_llong("123456", &converted);
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
ASSERT_EQ(converted, 123456);
|
||||||
|
|
||||||
|
ret = util_safe_llong("123456", NULL);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_llong("-123456", &converted);
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
ASSERT_EQ(converted, -123456);
|
||||||
|
|
||||||
|
ret = util_safe_llong("0", &converted);
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
ASSERT_EQ(converted, 0);
|
||||||
|
|
||||||
|
ret = util_safe_llong("1.23", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_llong("1x", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_llong("-9223372036854775809", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_llong("9223372036854775808", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_llong("NULL", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(utils_convert, test_util_safe_ullong)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
unsigned long long converted;
|
||||||
|
ret = util_safe_ullong("123456", &converted);
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
ASSERT_EQ(converted, 123456);
|
||||||
|
|
||||||
|
ret = util_safe_ullong("123456", NULL);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_ullong("-123456", &converted);
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
ASSERT_EQ(converted, -123456);
|
||||||
|
|
||||||
|
ret = util_safe_ullong("0", &converted);
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
ASSERT_EQ(converted, 0);
|
||||||
|
|
||||||
|
ret = util_safe_ullong("1.23", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_ullong("1x", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_ullong("18446744073709551616", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_ullong("NULL", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(utils_convert, test_util_safe_strtod)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
double converted;
|
||||||
|
ret = util_safe_strtod("123456", &converted);
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
ASSERT_DOUBLE_EQ(converted, 123456);
|
||||||
|
|
||||||
|
ret = util_safe_strtod("123456", NULL);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_strtod("-123456", &converted);
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
ASSERT_DOUBLE_EQ(converted, -123456);
|
||||||
|
|
||||||
|
ret = util_safe_strtod("0", &converted);
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
ASSERT_DOUBLE_EQ(converted, 0);
|
||||||
|
|
||||||
|
ret = util_safe_strtod("123.456", &converted);
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
ASSERT_DOUBLE_EQ(converted, 123.456);
|
||||||
|
|
||||||
|
ret = util_safe_strtod("1x", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
|
||||||
|
ret = util_safe_strtod("NULL", &converted);
|
||||||
|
ASSERT_NE(ret, 0);
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) Huawei Technologies Co., Ltd. 2019-2019. All rights reserved.
|
* Copyright (c) Huawei Technologies Co., Ltd. 2019. All rights reserved.
|
||||||
* lcr licensed under the Mulan PSL v1.
|
* lcr licensed under the Mulan PSL v1.
|
||||||
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
||||||
* You may obtain a copy of Mulan PSL v1 at:
|
* You may obtain a copy of Mulan PSL v1 at:
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#######################################################################
|
#######################################################################
|
||||||
##- @Copyright (C) Huawei Technologies., Ltd. 2017-2019. All rights reserved.
|
##- @Copyright (C) Huawei Technologies., Ltd. 2019. All rights reserved.
|
||||||
# - lcr licensed under the Mulan PSL v1.
|
# - lcr licensed under the Mulan PSL v1.
|
||||||
# - You can use this software according to the terms and conditions of the Mulan PSL v1.
|
# - You can use this software according to the terms and conditions of the Mulan PSL v1.
|
||||||
# - You may obtain a copy of Mulan PSL v1 at:
|
# - You may obtain a copy of Mulan PSL v1 at:
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#######################################################################
|
#######################################################################
|
||||||
##- @Copyright (C) Huawei Technologies., Ltd. 2017-2019. All rights reserved.
|
##- @Copyright (C) Huawei Technologies., Ltd. 2019. All rights reserved.
|
||||||
# - lcr licensed under the Mulan PSL v1.
|
# - lcr licensed under the Mulan PSL v1.
|
||||||
# - You can use this software according to the terms and conditions of the Mulan PSL v1.
|
# - You can use this software according to the terms and conditions of the Mulan PSL v1.
|
||||||
# - You may obtain a copy of Mulan PSL v1 at:
|
# - You may obtain a copy of Mulan PSL v1 at:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user