iSulad/src/image/image.c

1174 lines
28 KiB
C
Raw Normal View History

2019-09-30 10:53:41 -04:00
/******************************************************************************
* Copyright (c) Huawei Technologies Co., Ltd. 2017-2019. All rights reserved.
* iSulad 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: tanyifeng
* Create: 2017-11-22
* Description: provide image functions
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h>
#include <limits.h>
#include <sys/utsname.h>
#include <ctype.h>
#include "securec.h"
#include "image.h"
#include "liblcrd.h"
#include "log.h"
#include "utils.h"
#include "ext_image.h"
#ifdef ENABLE_OCI_IMAGE
#include "oci_image.h"
#include "oci_image_status.h"
#include "oci_image_load.h"
#include "oci_login.h"
#include "oci_logout.h"
#endif
#ifdef ENABLE_EMBEDDED_IMAGE
#include "embedded_image.h"
#include "db_all.h"
/* embedded */
static const struct bim_ops g_embedded_ops = {
.init = embedded_init,
.detect = embedded_detect,
.prepare_rf = embedded_prepare_rf,
.mount_rf = embedded_mount_rf,
.umount_rf = embedded_umount_rf,
.delete_rf = embedded_delete_rf,
.merge_conf = embedded_merge_conf,
.get_user_conf = embedded_get_user_conf,
.list_ims = embedded_list_images,
.rm_image = embedded_remove_image,
.inspect_image = embedded_inspect_image,
.resolve_image_name = embedded_resolve_image_name,
.filesystem_usage = embedded_filesystem_usage,
.load_image = embedded_load_image,
.pull_image = NULL,
};
#endif
#ifdef ENABLE_OCI_IMAGE
/* oci */
static const struct bim_ops g_oci_ops = {
.init = oci_init,
.detect = oci_detect,
.prepare_rf = oci_prepare_rf,
.mount_rf = oci_mount_rf,
.umount_rf = oci_umount_rf,
.delete_rf = oci_delete_rf,
.merge_conf = oci_merge_conf,
.get_user_conf = oci_get_user_conf,
.list_ims = oci_list_images,
.rm_image = oci_remove_image,
.inspect_image = oci_inspect_image,
.resolve_image_name = oci_resolve_image_name,
.filesystem_usage = oci_filesystem_usage,
.load_image = oci_load_image,
.pull_image = oci_pull_image,
.login = oci_login,
.logout = oci_logout,
};
#endif
/* external */
static const struct bim_ops g_ext_ops = {
.init = ext_init,
.detect = ext_detect,
.prepare_rf = ext_prepare_rf,
.mount_rf = ext_mount_rf,
.umount_rf = ext_umount_rf,
.delete_rf = ext_delete_rf,
.merge_conf = ext_merge_conf,
.get_user_conf = ext_get_user_conf,
.list_ims = ext_list_images,
.rm_image = ext_remove_image,
.inspect_image = ext_inspect_image,
.resolve_image_name = ext_resolve_image_name,
.filesystem_usage = ext_filesystem_usage,
.load_image = ext_load_image,
.pull_image = NULL,
.login = ext_login,
.logout = ext_logout,
};
static const struct bim_type g_bims[] = {
#ifdef ENABLE_OCI_IMAGE
{
.image_type = IMAGE_TYPE_OCI,
.ops = &g_oci_ops,
},
#endif
{ .image_type = IMAGE_TYPE_EXTERNAL, .ops = &g_ext_ops },
#ifdef ENABLE_EMBEDDED_IMAGE
{ .image_type = IMAGE_TYPE_EMBEDDED, .ops = &g_embedded_ops },
#endif
};
static const size_t g_numbims = sizeof(g_bims) / sizeof(struct bim_type);
static const struct bim_type *bim_query(const char *image_name)
{
size_t i;
char *temp = NULL;
for (i = 0; i < g_numbims; i++) {
temp = g_bims[i].ops->resolve_image_name(image_name);
if (temp == NULL) {
lcrd_append_error_message("Failed to resovle image name%s", image_name);
return NULL;
}
int r = g_bims[i].ops->detect(temp);
free(temp);
temp = NULL;
if (r != 0) {
break;
}
}
if (i == g_numbims) {
return NULL;
}
return &g_bims[i];
}
static const struct bim_type *get_bim_by_type(const char *image_type)
{
size_t i;
for (i = 0; i < g_numbims; i++) {
if (strcmp(g_bims[i].image_type, image_type) == 0) {
return &g_bims[i];
}
}
ERROR("Backing store %s unknown but not caught earlier\n", image_type);
return NULL;
}
static void bim_put(struct bim *bim)
{
if (bim == NULL) {
return;
}
free(bim->image_name);
bim->image_name = NULL;
free(bim->ext_config_image);
bim->ext_config_image = NULL;
free(bim->container_id);
bim->container_id = NULL;
free(bim);
}
static struct bim *bim_get(const char *image_type, const char *image_name, const char *ext_config_image,
const char *container_id)
{
struct bim *bim = NULL;
const struct bim_type *q = NULL;
if (image_type == NULL) {
return NULL;
}
q = get_bim_by_type(image_type);
if (q == NULL) {
return NULL;
}
bim = util_common_calloc_s(sizeof(struct bim));
if (bim == NULL) {
return NULL;
}
bim->ops = q->ops;
bim->type = q->image_type;
if (image_name != NULL) {
bim->image_name = bim->ops->resolve_image_name(image_name);
if (bim->image_name == NULL) {
lcrd_append_error_message("Failed to resovle image name%s", bim->image_name);
bim_put(bim);
return NULL;
}
}
if (ext_config_image != NULL) {
bim->ext_config_image = util_strdup_s(ext_config_image);
if (bim->ext_config_image == NULL) {
lcrd_append_error_message("Failed to strdup external config image %s", bim->ext_config_image);
bim_put(bim);
return NULL;
}
}
if (container_id != NULL) {
bim->container_id = util_strdup_s(container_id);
}
return bim;
}
int im_get_container_filesystem_usage(const char *image_type, const char *id, imagetool_fs_info **fs_usage)
{
int ret = 0;
imagetool_fs_info *filesystemusage = NULL;
const struct bim_type *q = NULL;
struct bim *bim = NULL;
if (image_type == NULL || id == NULL) {
ERROR("Invalid input arguments");
ret = -1;
goto out;
}
q = get_bim_by_type(image_type);
if (q == NULL) {
ret = -1;
goto out;
}
bim = util_common_calloc_s(sizeof(struct bim));
if (bim == NULL) {
ret = -1;
goto out;
}
bim->ops = q->ops;
bim->type = q->image_type;
if (id != NULL) {
bim->container_id = util_strdup_s(id);
}
ret = bim->ops->filesystem_usage(bim, &filesystemusage);
if (ret != 0) {
ERROR("Failed to get filesystem usage for container %s", id);
ret = -1;
goto out;
}
*fs_usage = filesystemusage;
out:
bim_put(bim);
return ret;
}
int im_remove_container_rootfs(const char *image_type, const char *container_id)
{
int ret = 0;
struct bim *bim = NULL;
if (container_id == NULL || image_type == NULL) {
ERROR("Invalid input arguments");
ret = -1;
goto out;
}
bim = bim_get(image_type, NULL, NULL, container_id);
if (bim == NULL) {
ERROR("Failed to init bim for container %s", container_id);
ret = -1;
goto out;
}
ret = bim->ops->delete_rf(bim);
if (ret != 0) {
ERROR("Failed to delete rootfs for container %s", container_id);
ret = -1;
goto out;
}
out:
bim_put(bim);
return ret;
}
int im_umount_container_rootfs(const char *image_type, const char *image_name, const char *container_id)
{
int ret = 0;
struct bim *bim = NULL;
if (container_id == NULL || image_type == NULL || image_name == NULL) {
ERROR("Invalid input arguments");
ret = -1;
goto out;
}
bim = bim_get(image_type, image_name, NULL, container_id);
if (bim == NULL) {
ERROR("Failed to init bim for container %s", container_id);
ret = -1;
goto out;
}
ret = bim->ops->umount_rf(bim);
if (ret != 0) {
ERROR("Failed to umount rootfs for container %s", container_id);
ret = -1;
goto out;
}
out:
bim_put(bim);
return ret;
}
int im_mount_container_rootfs(const char *image_type, const char *image_name, const char *container_id)
{
int ret = 0;
struct bim *bim = NULL;
if (image_name == NULL || container_id == NULL || image_type == NULL) {
ERROR("Invalid input arguments");
ret = -1;
goto out;
}
bim = bim_get(image_type, image_name, NULL, container_id);
if (bim == NULL) {
ERROR("Failed to init bim for container %s", container_id);
ret = -1;
goto out;
}
ret = bim->ops->mount_rf(bim);
if (ret != 0) {
ERROR("Failed to mount rootfs for container %s", container_id);
ret = -1;
goto out;
}
out:
bim_put(bim);
return ret;
}
char *im_get_image_type(const char *image, const char *external_rootfs)
{
const char *image_name = NULL;
const struct bim_type *bim_type = NULL;
image_name = (external_rootfs != NULL) ? external_rootfs : image;
if (image_name == NULL) {
ERROR("Should specify the image name or external rootfs");
return NULL;
}
bim_type = bim_query(image_name);
if (bim_type == NULL) {
ERROR("Failed to query type of image %s", image_name);
lcrd_set_error_message("No such image:%s", image_name);
return NULL;
}
return util_strdup_s(bim_type->image_type);
}
bool im_config_image_exist(const char *image_name)
{
const struct bim_type *bim_type = NULL;
bim_type = bim_query(image_name);
if (bim_type == NULL) {
ERROR("Config image %s not exist", image_name);
lcrd_set_error_message("Image %s not exist", image_name);
return false;
}
return true;
}
int im_merge_image_config(const char *id, const char *image_type, const char *image_name,
const char *ext_config_image, oci_runtime_spec *oci_spec,
host_config *host_spec, container_custom_config *custom_spec,
char **real_rootfs)
{
int ret = 0;
struct bim *bim = NULL;
if (real_rootfs == NULL || oci_spec == NULL || image_type == NULL) {
ERROR("Invalid input arguments");
ret = -1;
goto out;
}
bim = bim_get(image_type, image_name, ext_config_image, id);
if (bim == NULL) {
ERROR("Failed to init bim of image %s", image_name);
ret = -1;
goto out;
}
ret = bim->ops->merge_conf(oci_spec, host_spec, custom_spec, bim, real_rootfs);
if (ret != 0) {
ERROR("Failed to merge image %s config, config image is %s", image_name, ext_config_image);
ret = -1;
goto out;
}
INFO("Use real rootfs: %s with type: %s", *real_rootfs, image_type);
out:
bim_put(bim);
return ret;
}
int im_get_user_conf(const char *image_type, const char *basefs, host_config *hc, const char *userstr,
oci_runtime_spec_process_user *puser)
{
int ret = 0;
struct bim *bim = NULL;
if (basefs == NULL || hc == NULL || image_type == NULL || puser == NULL) {
ERROR("Invalid input arguments");
ret = -1;
goto out;
}
bim = bim_get(image_type, NULL, NULL, NULL);
if (bim == NULL) {
ERROR("Failed to init bim for image type: %s", image_type);
ret = -1;
goto out;
}
ret = bim->ops->get_user_conf(basefs, hc, userstr, puser);
if (ret != 0) {
ERROR("Failed to get user config");
ret = -1;
goto out;
}
out:
bim_put(bim);
return ret;
}
static int append_images_to_response(im_list_response *response, imagetool_images_list *images_in)
{
int ret = 0;
size_t images_num = 0;
size_t old_num = 0;
imagetool_image **tmp = NULL;
size_t i = 0;
size_t new_size = 0;
size_t old_size = 0;
if (images_in == NULL || response == NULL) {
ERROR("Invalid input arguments");
ret = -1;
goto out;
}
if (response->images == NULL) {
response->images = util_common_calloc_s(sizeof(imagetool_images_list));
if (response->images == NULL) {
ERROR("Memeory out");
ret = -1;
goto out;
}
}
images_num = images_in->images_len;
// no images need to append
if (images_num == 0) {
goto out;
}
if (images_num > SIZE_MAX / sizeof(imagetool_image *) - response->images->images_len) {
ERROR("Too many images to append!");
ret = -1;
goto out;
}
old_num = response->images->images_len;
new_size = (old_num + images_num) * sizeof(imagetool_image *);
old_size = old_num * sizeof(imagetool_image *);
ret = mem_realloc((void **)(&tmp), new_size, response->images->images, old_size);
if (ret != 0) {
ERROR("Failed to realloc memory for append images");
ret = -1;
goto out;
}
response->images->images = tmp;
for (i = 0; i < images_num; i++) {
response->images->images[old_num + i] = images_in->images[i];
images_in->images[i] = NULL;
images_in->images_len--;
response->images->images_len++;
}
out:
return ret;
}
int im_list_images(im_list_request *request, im_list_response **response)
{
char *filter = NULL;
size_t i;
imagetool_images_list *images_tmp = NULL;
filter = request->filter.image.image;
*response = util_common_calloc_s(sizeof(im_list_response));
if (*response == NULL) {
ERROR("Out of memory");
return -1;
}
EVENT("Event: {Object: list images, Type: listing, Filter: %s}", filter ? filter : "");
for (i = 0; i < g_numbims; i++) {
int ret = g_bims[i].ops->list_ims(request, &images_tmp);
if (ret != 0) {
ERROR("Failed to list all images with type:%s", g_bims[i].image_type);
continue;
}
ret = append_images_to_response(*response, images_tmp);
if (ret != 0) {
ERROR("Failed to append images with type:%s", g_bims[i].image_type);
}
free_imagetool_images_list(images_tmp);
images_tmp = NULL;
}
EVENT("Event: {Object: list images, Type: listed, Filter: %s}", filter ? filter : "");
if (g_lcrd_errmsg != NULL) {
(*response)->errmsg = util_strdup_s(g_lcrd_errmsg);
}
return 0;
}
void free_im_list_request(im_list_request *ptr)
{
if (ptr == NULL) {
return;
}
free(ptr->filter.image.image);
ptr->filter.image.image = NULL;
free(ptr);
}
void free_im_list_response(im_list_response *ptr)
{
if (ptr == NULL) {
return;
}
free_imagetool_images_list(ptr->images);
ptr->images = NULL;
free(ptr->errmsg);
ptr->errmsg = NULL;
free(ptr);
}
static bool check_im_pull_args(const im_pull_request *req, im_pull_response * const *resp)
{
if (req == NULL || resp == NULL) {
ERROR("Request or response is NULL");
return false;
}
if (req->image == NULL) {
ERROR("Empty image required");
lcrd_set_error_message("Empty image required");
return false;
}
return true;
}
int im_pull_image(const im_pull_request *request, im_pull_response **response)
{
int ret = -1;
struct bim *bim = NULL;
if (!check_im_pull_args(request, response)) {
return ret;
}
bim = bim_get(request->type, NULL, NULL, NULL);
if (bim == NULL) {
ERROR("Failed to init bim, image type: %s", request->type);
goto out;
}
if (bim->ops->pull_image == NULL) {
WARN("Unimplements pull image in %s", bim->type);
ret = 0;
goto out;
}
ret = bim->ops->pull_image(request, response);
if (ret != 0) {
ERROR("Pull image %s failed", request->image);
ret = -1;
goto out;
}
out:
bim_put(bim);
return ret;
}
void free_im_pull_request(im_pull_request *req)
{
if (req == NULL) {
return;
}
free(req->type);
req->type = NULL;
free(req->image);
req->image = NULL;
free_sensitive_string(req->username);
req->username = NULL;
free_sensitive_string(req->password);
req->password = NULL;
free_sensitive_string(req->auth);
req->auth = NULL;
free_sensitive_string(req->server_address);
req->server_address = NULL;
free_sensitive_string(req->registry_token);
req->registry_token = NULL;
free_sensitive_string(req->identity_token);
req->identity_token = NULL;
free(req);
}
void free_im_pull_response(im_pull_response *resp)
{
if (resp == NULL) {
return;
}
free(resp->image_ref);
resp->image_ref = NULL;
free(resp->errmsg);
resp->errmsg = NULL;
free(resp);
}
int im_load_image(im_load_request *request, im_load_response **response)
{
int ret = -1;
struct bim *bim = NULL;
if (request == NULL || response == NULL) {
ERROR("Invalid input arguments");
return -1;
}
*response = util_common_calloc_s(sizeof(im_load_response));
if (*response == NULL) {
ERROR("Out of memory");
return -1;
}
if (request->file == NULL) {
ERROR("Load image requires image tarball file path");
lcrd_set_error_message("Load image requires image tarball file path");
goto pack_response;
}
if (request->type == NULL) {
ERROR("Missing image type");
lcrd_set_error_message("Missing image type");
goto pack_response;
}
bim = bim_get(request->type, NULL, NULL, NULL);
if (bim == NULL) {
ERROR("Failed to init bim, image type:%s", request->type);
goto pack_response;
}
EVENT("Event: {Object: %s, Type: loading}", request->file);
ret = bim->ops->load_image(request);
if (ret != 0) {
ERROR("Failed to load image from %s with tag %s and type %s", request->file, request->tag, request->type);
ret = -1;
goto pack_response;
}
EVENT("Event: {Object: %s, Type: loaded}", request->file);
pack_response:
if (g_lcrd_errmsg != NULL) {
(*response)->errmsg = util_strdup_s(g_lcrd_errmsg);
}
bim_put(bim);
return ret;
}
void free_im_load_request(im_load_request *ptr)
{
if (ptr == NULL) {
return;
}
free(ptr->file);
ptr->file = NULL;
free(ptr->tag);
ptr->file = NULL;
free(ptr->type);
ptr->type = NULL;
free(ptr);
}
void free_im_load_response(im_load_response *ptr)
{
if (ptr == NULL) {
return;
}
free(ptr->errmsg);
ptr->errmsg = NULL;
free(ptr);
}
int im_login(im_login_request *request, im_login_response **response)
{
int ret = -1;
struct bim *bim = NULL;
if (request == NULL || response == NULL) {
ERROR("Invalid input arguments");
return -1;
}
*response = util_common_calloc_s(sizeof(im_login_response));
if (*response == NULL) {
ERROR("Out of memory");
return -1;
}
if (request->server == NULL) {
ERROR("Login requires server address");
lcrd_set_error_message("Login requires server address");
goto pack_response;
}
if (request->type == NULL) {
ERROR("Login requires image type");
lcrd_set_error_message("Login requires image type");
goto pack_response;
}
if (request->username == NULL || request->password == NULL) {
ERROR("Missing username or password");
lcrd_set_error_message("Missing username or password");
goto pack_response;
}
bim = bim_get(request->type, NULL, NULL, NULL);
if (bim == NULL) {
ERROR("Failed to init bim, image type:%s", request->type);
goto pack_response;
}
EVENT("Event: {Object: %s, Type: logining}", request->server);
ret = bim->ops->login(request);
if (ret != 0) {
ERROR("Failed to login %s", request->server);
ret = -1;
goto pack_response;
}
EVENT("Event: {Object: %s, Type: logined}", request->server);
pack_response:
if (g_lcrd_errmsg != NULL) {
(*response)->errmsg = util_strdup_s(g_lcrd_errmsg);
}
bim_put(bim);
return ret;
}
void free_im_login_request(im_login_request *ptr)
{
if (ptr == NULL) {
return;
}
free_sensitive_string(ptr->username);
ptr->username = NULL;
free_sensitive_string(ptr->password);
ptr->password = NULL;
free(ptr->type);
ptr->type = NULL;
free_sensitive_string(ptr->server);
ptr->server = NULL;
free(ptr);
}
void free_im_login_response(im_login_response *ptr)
{
if (ptr == NULL) {
return;
}
free(ptr->errmsg);
ptr->errmsg = NULL;
free(ptr);
}
int im_logout(im_logout_request *request, im_logout_response **response)
{
int ret = -1;
struct bim *bim = NULL;
if (request == NULL || response == NULL) {
ERROR("Invalid input arguments");
return -1;
}
*response = util_common_calloc_s(sizeof(im_logout_response));
if (*response == NULL) {
ERROR("Out of memory");
return -1;
}
if (request->server == NULL) {
ERROR("Logout requires server address");
lcrd_set_error_message("Logout requires server address");
goto pack_response;
}
if (request->type == NULL) {
ERROR("Logout requires image type");
lcrd_set_error_message("Logout requires image type");
goto pack_response;
}
bim = bim_get(request->type, NULL, NULL, NULL);
if (bim == NULL) {
ERROR("Failed to init bim, image type:%s", request->type);
goto pack_response;
}
EVENT("Event: {Object: %s, Type: logouting}", request->server);
ret = bim->ops->logout(request);
if (ret != 0) {
ERROR("Failed to logout %s", request->server);
ret = -1;
goto pack_response;
}
EVENT("Event: {Object: %s, Type: logouted}", request->server);
pack_response:
if (g_lcrd_errmsg != NULL) {
(*response)->errmsg = util_strdup_s(g_lcrd_errmsg);
}
bim_put(bim);
return ret;
}
void free_im_logout_request(im_logout_request *ptr)
{
if (ptr == NULL) {
return;
}
free(ptr->type);
ptr->type = NULL;
free(ptr->server);
ptr->server = NULL;
free(ptr);
}
void free_im_logout_response(im_logout_response *ptr)
{
if (ptr == NULL) {
return;
}
free(ptr->errmsg);
ptr->errmsg = NULL;
free(ptr);
}
int im_rm_image(im_remove_request *request, im_remove_response **response)
{
int ret = -1;
char *image_ref = NULL;
const struct bim_type *bim_type = NULL;
struct bim *bim = NULL;
if (request == NULL || response == NULL) {
ERROR("Invalid input arguments");
return -1;
}
*response = util_common_calloc_s(sizeof(im_remove_response));
if (*response == NULL) {
ERROR("Out of memory");
return -1;
}
if (request->image.image == NULL) {
ERROR("remove image requires image ref");
lcrd_set_error_message("remove image requires image ref");
goto pack_response;
}
image_ref = util_strdup_s(request->image.image);
EVENT("Event: {Object: %s, Type: removing}", image_ref);
bim_type = bim_query(image_ref);
if (bim_type == NULL) {
ERROR("No such image:%s", image_ref);
lcrd_set_error_message("No such image:%s", image_ref);
goto pack_response;
}
bim = bim_get(bim_type->image_type, image_ref, NULL, NULL);
if (bim == NULL) {
ERROR("Failed to init bim for image %s", image_ref);
goto pack_response;
}
ret = bim->ops->rm_image(request);
if (ret != 0) {
ERROR("Failed to remove image %s", image_ref);
ret = -1;
goto pack_response;
}
EVENT("Event: {Object: %s, Type: removed}", image_ref);
pack_response:
if (g_lcrd_errmsg != NULL) {
(*response)->errmsg = util_strdup_s(g_lcrd_errmsg);
}
free(image_ref);
bim_put(bim);
return ret;
}
void free_im_remove_request(im_remove_request *ptr)
{
if (ptr == NULL) {
return;
}
free(ptr->image.image);
ptr->image.image = NULL;
free(ptr);
}
void free_im_remove_response(im_remove_response *ptr)
{
if (ptr == NULL) {
return;
}
free(ptr->errmsg);
ptr->errmsg = NULL;
free(ptr);
}
int im_inspect_image(const im_inspect_request *request, im_inspect_response **response)
{
int ret = 0;
char *image_ref = NULL;
char *inspected_json = NULL;
const struct bim_type *bim_type = NULL;
struct bim *bim = NULL;
if (request == NULL || response == NULL) {
ERROR("Invalid input arguments");
return -1;
}
*response = util_common_calloc_s(sizeof(im_inspect_response));
if (*response == NULL) {
ERROR("Out of memory");
return -1;
}
if (request->image.image == NULL) {
ERROR("inspect image requires image ref");
lcrd_set_error_message("inspect image requires image ref");
ret = -1;
goto pack_response;
}
image_ref = util_strdup_s(request->image.image);
EVENT("Event: {Object: %s, Type: inspecting}", image_ref);
bim_type = bim_query(image_ref);
if (bim_type == NULL) {
ERROR("No such image:%s", image_ref);
lcrd_set_error_message("No such image:%s", image_ref);
ret = -1;
goto pack_response;
}
bim = bim_get(bim_type->image_type, image_ref, NULL, NULL);
if (bim == NULL) {
ERROR("Failed to init bim for image %s", image_ref);
ret = -1;
goto pack_response;
}
ret = bim->ops->inspect_image(bim, &inspected_json);
if (ret != 0) {
ERROR("Failed to inspect image %s", image_ref);
ret = -1;
goto pack_response;
}
EVENT("Event: {Object: %s, Type: inspected}", image_ref);
pack_response:
if (g_lcrd_errmsg != NULL) {
(*response)->errmsg = util_strdup_s(g_lcrd_errmsg);
}
if (inspected_json != NULL) {
(*response)->im_inspect_json = util_strdup_s(inspected_json);
}
free(image_ref);
free(inspected_json);
bim_put(bim);
return ret;
}
void free_im_inspect_request(im_inspect_request *ptr)
{
if (ptr == NULL) {
return;
}
free(ptr->image.image);
ptr->image.image = NULL;
free(ptr);
}
void free_im_inspect_response(im_inspect_response *ptr)
{
if (ptr == NULL) {
return;
}
free(ptr->im_inspect_json);
ptr->im_inspect_json = NULL;
free(ptr->errmsg);
ptr->errmsg = NULL;
free(ptr);
}
static int bims_init(const char *rootpath)
{
int ret = 0;
size_t i;
for (i = 0; i < g_numbims; i++) {
ret = g_bims[i].ops->init(rootpath);
if (ret != 0) {
ERROR("Failed to init bim %s", g_bims[i].image_type);
break;
}
}
return ret;
}
int image_module_init(const char *rootpath)
{
return bims_init(rootpath);
}
int map_to_key_value_string(const json_map_string_string *map, char ***array, size_t *array_len)
{
char **strings = NULL;
size_t strings_len = 0;
size_t i;
int ret;
if (map == NULL) {
return 0;
}
for (i = 0; i < map->len; i++) {
char *str = NULL;
size_t len;
if (strlen(map->keys[i]) > (SIZE_MAX - strlen(map->values[i])) - 2) {
ERROR("Invalid keys/values");
goto cleanup;
}
len = strlen(map->keys[i]) + strlen(map->values[i]) + 2;
str = util_common_calloc_s(len);
if (str == NULL) {
ERROR("Out of memory");
goto cleanup;
}
ret = sprintf_s(str, len, "%s=%s", map->keys[i], map->values[i]);
if (ret < 0) {
ERROR("Failed to print string");
free(str);
goto cleanup;
}
ret = util_array_append(&strings, str);
free(str);
if (ret != 0) {
ERROR("Failed to append array");
goto cleanup;
}
strings_len++;
}
*array = strings;
*array_len = strings_len;
return 0;
cleanup:
util_free_array(strings);
return -1;
}