From fc2fc11d6985f14aea41021f9c4e85b664bcbbaf Mon Sep 17 00:00:00 2001
From: liuhao <liuhao27@huawei.com>
Date: Thu, 2 May 2019 11:23:50 +0800
Subject: [PATCH 093/131] optimize isulad_kit operator

parse group add start container

Signed-off-by: liuhao <liuhao27@huawei.com>
Signed-off-by: LiFeng <lifeng68@huawei.com>
---
 src/lxc/Makefile.am                           |   2 +
 .../json/container_start_generate_config.c    | 245 ++++++++++++++++++
 .../json/container_start_generate_config.h    |  43 +++
 src/lxc/tools/lxc_start.c                     |  58 +++++
 4 files changed, 348 insertions(+)
 create mode 100644 src/lxc/json/container_start_generate_config.c
 create mode 100644 src/lxc/json/container_start_generate_config.h

diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 698f8f95..4ec20812 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -45,6 +45,7 @@ noinst_HEADERS = attach.h \
 		 storage/storage_utils.h \
 		 json/defs.h \
 		 json/json_common.h \
+		 json/container_start_generate_config.h \
 		 json/oci_runtime_hooks.h \
 		 json/oci_runtime_spec.h \
 		 json/logger_json_file.h \
@@ -152,6 +153,7 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \
 		    json/oci_runtime_hooks.c json/oci_runtime_hooks.h \
 		    json/logger_json_file.c json/logger_json_file.h \
 		    json/oci_runtime_spec.c json/oci_runtime_spec.h \
+		    json/container_start_generate_config.c json/container_start_generate_config.h \
 		    json/read-file.c json/read-file.h \
 		    $(LSM_SOURCES)
 
diff --git a/src/lxc/json/container_start_generate_config.c b/src/lxc/json/container_start_generate_config.c
new file mode 100644
index 00000000..5ec83114
--- /dev/null
+++ b/src/lxc/json/container_start_generate_config.c
@@ -0,0 +1,245 @@
+// Generated from start-generate-config.json. Do not edit!
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <string.h>
+#include "read-file.h"
+#include "container_start_generate_config.h"
+
+container_start_generate_config *make_container_start_generate_config(yajl_val tree, struct parser_context *ctx, parser_error *err) {
+    container_start_generate_config *ret = NULL;
+    *err = 0;
+    if (tree == NULL)
+        return ret;
+    ret = safe_malloc(sizeof(*ret));
+    {
+        yajl_val val = get_val(tree, "uid", yajl_t_number);
+        if (val != NULL) {
+            int invalid = common_safe_uint(YAJL_GET_NUMBER(val), (unsigned int *)&ret->uid);
+            if (invalid) {
+                if (asprintf(err, "Invalid value '%s' with type 'UID' for key 'uid': %s", YAJL_GET_NUMBER(val), strerror(-invalid)) < 0)
+                    *err = safe_strdup("error allocating memory");
+                free_container_start_generate_config(ret);
+                return NULL;
+            }
+        }
+    }
+    {
+        yajl_val val = get_val(tree, "gid", yajl_t_number);
+        if (val != NULL) {
+            int invalid = common_safe_uint(YAJL_GET_NUMBER(val), (unsigned int *)&ret->gid);
+            if (invalid) {
+                if (asprintf(err, "Invalid value '%s' with type 'GID' for key 'gid': %s", YAJL_GET_NUMBER(val), strerror(-invalid)) < 0)
+                    *err = safe_strdup("error allocating memory");
+                free_container_start_generate_config(ret);
+                return NULL;
+            }
+        }
+    }
+    {
+        yajl_val tmp = get_val(tree, "additionalGids", yajl_t_array);
+        if (tmp != NULL && YAJL_GET_ARRAY(tmp) != NULL && YAJL_GET_ARRAY(tmp)->len > 0) {
+            size_t i;
+            ret->additional_gids_len = YAJL_GET_ARRAY(tmp)->len;
+            ret->additional_gids = safe_malloc((YAJL_GET_ARRAY(tmp)->len + 1) * sizeof(*ret->additional_gids));
+            for (i = 0; i < YAJL_GET_ARRAY(tmp)->len; i++) {
+                yajl_val val = YAJL_GET_ARRAY(tmp)->values[i];
+                if (val != NULL) {
+                    int invalid = common_safe_uint(YAJL_GET_NUMBER(val), (unsigned int *)&ret->additional_gids[i]);
+                    if (invalid) {
+                        if (asprintf(err, "Invalid value '%s' with type 'GID' for key 'additionalGids': %s", YAJL_GET_NUMBER(val), strerror(-invalid)) < 0)
+                            *err = safe_strdup("error allocating memory");
+                        free_container_start_generate_config(ret);
+                        return NULL;
+                    }
+                }
+            }
+        }
+    }
+
+    if (tree->type == yajl_t_object && (ctx->options & PARSE_OPTIONS_STRICT)) {
+        int i;
+        for (i = 0; i < tree->u.object.len; i++)
+            if (strcmp(tree->u.object.keys[i], "uid") &&
+                strcmp(tree->u.object.keys[i], "gid") &&
+                strcmp(tree->u.object.keys[i], "additionalGids")) {
+                if (ctx->stderr > 0)
+                    fprintf(ctx->stderr, "WARNING: unknown key found: %s\n", tree->u.object.keys[i]);
+            }
+        }
+    return ret;
+}
+
+void free_container_start_generate_config(container_start_generate_config *ptr) {
+    if (ptr == NULL)
+        return;
+    free(ptr->additional_gids);
+    ptr->additional_gids = NULL;
+    free(ptr);
+}
+
+yajl_gen_status gen_container_start_generate_config(yajl_gen g, container_start_generate_config *ptr, struct parser_context *ctx, parser_error *err) {
+    yajl_gen_status stat = yajl_gen_status_ok;
+    *err = 0;
+    stat = reformat_start_map(g);
+    if (yajl_gen_status_ok != stat)
+        GEN_SET_ERROR_AND_RETURN(stat, err);
+    if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr != NULL && ptr->uid)) {
+        long long unsigned int num = 0;
+        stat = reformat_map_key(g, "uid", strlen("uid"));
+        if (yajl_gen_status_ok != stat)
+            GEN_SET_ERROR_AND_RETURN(stat, err);
+        if (ptr != NULL && ptr->uid) {
+            num = (long long unsigned int)ptr->uid;
+        }
+        stat = reformat_uint(g, num);
+        if (yajl_gen_status_ok != stat)
+            GEN_SET_ERROR_AND_RETURN(stat, err);
+    }
+    if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) ||(ptr != NULL && ptr->gid)) {
+        long long unsigned int num = 0;
+        stat = reformat_map_key(g, "gid", strlen("gid"));
+        if (yajl_gen_status_ok != stat)
+            GEN_SET_ERROR_AND_RETURN(stat, err);
+        if (ptr != NULL && ptr->gid) {
+            num = (long long unsigned int)ptr->gid;
+        }
+        stat = reformat_uint(g, num);
+        if (yajl_gen_status_ok != stat)
+            GEN_SET_ERROR_AND_RETURN(stat, err);
+    }
+    if ((ctx->options & GEN_OPTIONS_ALLKEYVALUE) || (ptr != NULL && ptr->additional_gids != NULL)) {
+        size_t len = 0, i;
+        stat = reformat_map_key(g, "additionalGids", strlen("additionalGids"));
+        if (yajl_gen_status_ok != stat)
+            GEN_SET_ERROR_AND_RETURN(stat, err);
+        if (ptr != NULL && ptr->additional_gids != NULL) {
+            len = ptr->additional_gids_len;
+        }
+        if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY))
+            yajl_gen_config(g, yajl_gen_beautify, 0);
+        stat = reformat_start_array(g);
+        if (yajl_gen_status_ok != stat)
+            GEN_SET_ERROR_AND_RETURN(stat, err);
+        for (i = 0; i < len; i++) {
+            stat = reformat_uint(g, ptr->additional_gids[i]);
+            if (yajl_gen_status_ok != stat)
+                GEN_SET_ERROR_AND_RETURN(stat, err);
+        }
+        stat = reformat_end_array(g);
+        if (yajl_gen_status_ok != stat)
+            GEN_SET_ERROR_AND_RETURN(stat, err);
+        if (!len && !(ctx->options & GEN_OPTIONS_SIMPLIFY))
+            yajl_gen_config(g, yajl_gen_beautify, 1);
+    }
+    stat = reformat_end_map(g);
+    if (yajl_gen_status_ok != stat)
+        GEN_SET_ERROR_AND_RETURN(stat, err);
+    return yajl_gen_status_ok;
+}
+
+
+container_start_generate_config *container_start_generate_config_parse_file(const char *filename, struct parser_context *ctx, parser_error *err) {
+    container_start_generate_config *ptr = NULL;
+    size_t filesize;
+    char *content = NULL;
+
+    if (filename == NULL || err == NULL)
+        return NULL;
+
+    *err = NULL;
+    content = read_file(filename, &filesize);
+    if (content == NULL) {
+        if (asprintf(err, "cannot read the file: %s", filename) < 0)
+            *err = safe_strdup("error allocating memory");
+        return NULL;
+    }
+    ptr = container_start_generate_config_parse_data(content, ctx, err);
+    free(content);
+    return ptr;
+}
+
+container_start_generate_config *container_start_generate_config_parse_file_stream(FILE *stream, struct parser_context *ctx, parser_error *err) {
+    container_start_generate_config *ptr = NULL;
+    size_t filesize;
+    char *content = NULL ;
+
+    if (stream == NULL || err == NULL)
+        return NULL;
+
+    *err = NULL;
+    content = fread_file(stream, &filesize);
+    if (content == NULL) {
+        *err = safe_strdup("cannot read the file");
+        return NULL;
+    }
+    ptr = container_start_generate_config_parse_data(content, ctx, err);
+    free(content);
+    return ptr;
+}
+
+container_start_generate_config *container_start_generate_config_parse_data(const char *jsondata, struct parser_context *ctx, parser_error *err) {
+    container_start_generate_config *ptr = NULL;
+    yajl_val tree;
+    char errbuf[1024];
+    struct parser_context tmp_ctx;
+
+    if (jsondata == NULL || err == NULL)
+        return NULL;
+
+    *err = NULL;
+    if (ctx == NULL) {
+       ctx = &tmp_ctx;
+        (void)memset(&tmp_ctx, 0, sizeof(tmp_ctx));
+    }
+    tree = yajl_tree_parse(jsondata, errbuf, sizeof(errbuf));
+    if (tree == NULL) {
+        if (asprintf(err, "cannot parse the data: %s", errbuf) < 0)
+            *err = safe_strdup("error allocating memory");
+        return NULL;
+    }
+    ptr = make_container_start_generate_config(tree, ctx, err);
+    yajl_tree_free(tree);
+    return ptr;
+}
+char *container_start_generate_config_generate_json(container_start_generate_config *ptr, struct parser_context *ctx, parser_error *err) {
+    yajl_gen g = NULL;
+    struct parser_context tmp_ctx;
+    const unsigned char *gen_buf = NULL;
+    char *json_buf = NULL;
+    size_t gen_len = 0;
+
+    if (ptr == NULL || err == NULL)
+        return NULL;
+
+    *err = NULL;
+    if (ctx == NULL) {
+        ctx = &tmp_ctx;
+        (void)memset(&tmp_ctx, 0, sizeof(tmp_ctx));
+    }
+
+    if (!json_gen_init(&g, ctx)) {
+        *err = safe_strdup("Json_gen init failed");
+        goto out;
+    }
+    if (yajl_gen_status_ok != gen_container_start_generate_config(g, ptr, ctx, err)) {
+        if (*err == NULL)
+            *err = safe_strdup("Failed to generate json");
+        goto free_out;
+    }
+    yajl_gen_get_buf(g, &gen_buf, &gen_len);
+    if (gen_buf == NULL) {
+        *err = safe_strdup("Error to get generated json");
+        goto free_out;
+    }
+
+    json_buf = safe_malloc(gen_len + 1);
+	(void)memcpy(json_buf, gen_buf, gen_len);
+    json_buf[gen_len] = '\0';
+
+free_out:
+    yajl_gen_clear(g);
+    yajl_gen_free(g);
+out:
+    return json_buf;
+}
diff --git a/src/lxc/json/container_start_generate_config.h b/src/lxc/json/container_start_generate_config.h
new file mode 100644
index 00000000..e1dcf56f
--- /dev/null
+++ b/src/lxc/json/container_start_generate_config.h
@@ -0,0 +1,43 @@
+// Generated from start-generate-config.json. Do not edit!
+#ifndef CONTAINER_START_GENERATE_CONFIG_SCHEMA_H
+#define CONTAINER_START_GENERATE_CONFIG_SCHEMA_H
+
+#include <sys/types.h>
+#include <stdint.h>
+#include "json_common.h"
+#include "defs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    uid_t uid;
+
+    gid_t gid;
+
+    gid_t *additional_gids;
+    size_t additional_gids_len;
+
+}
+container_start_generate_config;
+
+void free_container_start_generate_config(container_start_generate_config *ptr);
+
+container_start_generate_config *make_container_start_generate_config(yajl_val tree, struct parser_context *ctx, parser_error *err);
+
+yajl_gen_status gen_container_start_generate_config(yajl_gen g, container_start_generate_config *ptr, struct parser_context *ctx, parser_error *err);
+
+container_start_generate_config *container_start_generate_config_parse_file(const char *filename, struct parser_context *ctx, parser_error *err);
+
+container_start_generate_config *container_start_generate_config_parse_file_stream(FILE *stream, struct parser_context *ctx, parser_error *err);
+
+container_start_generate_config *container_start_generate_config_parse_data(const char *jsondata, struct parser_context *ctx, parser_error *err);
+
+char *container_start_generate_config_generate_json(container_start_generate_config *ptr, struct parser_context *ctx, parser_error *err);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lxc/tools/lxc_start.c b/src/lxc/tools/lxc_start.c
index af63f581..4069204f 100644
--- a/src/lxc/tools/lxc_start.c
+++ b/src/lxc/tools/lxc_start.c
@@ -50,6 +50,7 @@
 #include "confile.h"
 #include "log.h"
 #include "utils.h"
+#include "container_start_generate_config.h"
 
 lxc_log_define(lxc_start, lxc);
 
@@ -213,6 +214,57 @@ static int ensure_path(char **confpath, const char *path)
 	return 0;
 }
 
+static int set_start_extral_configs(const char *lxcpath, const char *name, struct lxc_container *c)
+{
+#define START_GENERATE_CONFIG "start_generate_config.json"
+	char fpath[PATH_MAX] = {0};
+	parser_error jerr = NULL;
+	int ret = -1;
+	container_start_generate_config *start_conf = NULL;
+	struct lxc_conf *lconf = c->lxc_conf;
+	size_t i = 0;
+
+	if (sprintf(fpath, "%s/%s/%s", lxcpath, name, START_GENERATE_CONFIG) < 0) {
+		ERROR("Sprintf config path failed");
+		return -1;
+	}
+	if (!file_exists(fpath)) {
+		return 0;
+	}
+	start_conf = container_start_generate_config_parse_file(fpath, NULL, &jerr);
+	if (start_conf == NULL) {
+		ERROR("Parse start generate config file: %s failed", fpath);
+		goto out;
+	}
+	if (start_conf->uid != 0) {
+		lconf->init_uid = start_conf->uid;
+	}
+	if (start_conf->gid != 0) {
+		lconf->init_gid = start_conf->gid;
+	}
+	if (start_conf->additional_gids != NULL && start_conf->additional_gids_len > 0) {
+		gid_t *tmp;
+		tmp = realloc(lconf->init_groups, (lconf->init_groups_len + start_conf->additional_gids_len) * sizeof(gid_t));
+		if (tmp == NULL) {
+			ERROR("Out of memory");
+			goto out;
+		}
+		lconf->init_groups = tmp;
+		for (; i < start_conf->additional_gids_len; i++) {
+			tmp[lconf->init_groups_len] = start_conf->additional_gids[i];
+			lconf->init_groups_len++;
+		}
+	}
+
+	ret = 0;
+out:
+	free(jerr);
+	if (start_conf != NULL) {
+		free_container_start_generate_config(start_conf);
+	}
+	return ret;
+}
+
 int main(int argc, char *argv[])
 {
 	const char *lxcpath;
@@ -358,6 +410,12 @@ int main(int argc, char *argv[])
 		}
 	}
 
+	/* isulad: load extral config for start container */
+	if (set_start_extral_configs(lxcpath, my_args.name, c) != 0) {
+		ERROR("Failed to load extral config for container");
+		goto out;
+	}
+
 	/* isulad: fifo used to monitor state of monitor process */
 	if (my_args.exit_monitor_fifo != NULL) {
 		c->exit_fifo = strdup(my_args.exit_monitor_fifo);
-- 
2.23.0

