From cd503ba4e456c3eaf5fa4cefb0ce2ba6059dff66 Mon Sep 17 00:00:00 2001 From: wujing Date: Sat, 16 May 2020 00:43:12 -0400 Subject: [PATCH] rootfs store interface implement Signed-off-by: wujing --- src/cutils/utils_images.c | 69 ++ src/cutils/utils_images.h | 1 + src/image/oci/registry/registry.h | 2 + .../oci/storage/image_store/image_store.c | 84 +- src/image/oci/storage/rootfs_store/rootfs.c | 6 +- src/image/oci/storage/rootfs_store/rootfs.h | 2 +- .../oci/storage/rootfs_store/rootfs_store.c | 858 ++++++++++++++++-- src/image/oci/storage/storage.h | 3 +- 8 files changed, 854 insertions(+), 171 deletions(-) diff --git a/src/cutils/utils_images.c b/src/cutils/utils_images.c index c19f604..9251620 100644 --- a/src/cutils/utils_images.c +++ b/src/cutils/utils_images.c @@ -290,3 +290,72 @@ char *oci_strip_dockerio_prefix(const char *name) return util_strdup_s(name); } +static bool should_use_origin_name(const char *name) +{ + size_t i; + + for (i = 0; i < strlen(name); i++) { + char ch = name[i]; + if (ch != '.' && !(ch >= '0' && ch <= '9') && !(ch >= 'a' && ch <= 'z')) { + return false; + } + } + + return true; +} + +// Convert a BigData key name into an acceptable file name. +char *make_big_data_base_name(const char *key) +{ + int ret = 0; + int nret = 0; + char *b64_encode_name = NULL; + size_t b64_encode_name_len = 0; + char *base_name = NULL; + size_t name_size; + + if (should_use_origin_name(key)) { + return util_strdup_s(key); + } + + b64_encode_name_len = util_base64_encode_len(strlen(key)); + b64_encode_name = util_common_calloc_s(b64_encode_name_len + 1); + if (b64_encode_name == NULL) { + ERROR("Out of memory"); + ret = -1; + goto out; + } + + nret = util_base64_encode((unsigned char *)key, strlen(key), b64_encode_name, b64_encode_name_len); + if (nret < 0) { + ret = -1; + ERROR("Encode auth to base64 failed"); + goto out; + } + name_size = 1 + strlen(b64_encode_name) + 1; // '=' + encode string + '\0' + + base_name = (char *)util_common_calloc_s(name_size * sizeof(char)); + if (base_name == NULL) { + ERROR("Out of memory"); + ret = -1; + goto out; + } + + nret = snprintf(base_name, name_size, "=%s", b64_encode_name); + if (nret < 0 || (size_t)nret >= name_size) { + ERROR("Out of memory"); + ret = -1; + goto out; + } + DEBUG("big data file name : %s", base_name); + +out: + if (ret != 0) { + free(base_name); + base_name = NULL; + } + free(b64_encode_name); + + return base_name; +} + diff --git a/src/cutils/utils_images.h b/src/cutils/utils_images.h index 64c0e9e..95dffe4 100644 --- a/src/cutils/utils_images.h +++ b/src/cutils/utils_images.h @@ -39,6 +39,7 @@ char *oci_normalize_image_name(const char *name); int oci_split_image_name(const char *image_name, char **host, char **name, char **tag); char *oci_full_image_name(const char *host, const char *name, const char *tag); char *oci_strip_dockerio_prefix(const char *name); +char *make_big_data_base_name(const char *key); #ifdef __cplusplus } diff --git a/src/image/oci/registry/registry.h b/src/image/oci/registry/registry.h index 138e28d..e00b439 100644 --- a/src/image/oci/registry/registry.h +++ b/src/image/oci/registry/registry.h @@ -15,6 +15,8 @@ #ifndef __IMAGE_REGISTRY_H #define __IMAGE_REGISTRY_H +#include + #ifdef __cplusplus extern "C" { #endif diff --git a/src/image/oci/storage/image_store/image_store.c b/src/image/oci/storage/image_store/image_store.c index 54186e4..1aee5c4 100644 --- a/src/image/oci/storage/image_store/image_store.c +++ b/src/image/oci/storage/image_store/image_store.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include "utils.h" #include "log.h" @@ -1296,75 +1295,6 @@ out: return ret; } -static bool should_use_origin_name(const char *name) -{ - size_t i; - - for (i = 0; i < strlen(name); i++) { - char ch = name[i]; - if (ch != '.' && !(ch >= '0' && ch <= '9') && !(ch >= 'a' && ch <= 'z')) { - return false; - } - } - - return true; -} - -// Convert a BigData key name into an acceptable file name. -static char *make_big_data_base_name(const char *key) -{ - int ret = 0; - int nret = 0; - char *b64_encode_name = NULL; - size_t b64_encode_name_len = 0; - char *base_name = NULL; - size_t name_size; - - if (should_use_origin_name(key)) { - return util_strdup_s(key); - } - - b64_encode_name_len = util_base64_encode_len(strlen(key)); - b64_encode_name = util_common_calloc_s(b64_encode_name_len + 1); - if (b64_encode_name == NULL) { - ERROR("Out of memory"); - ret = -1; - goto out; - } - - nret = util_base64_encode((unsigned char *)key, strlen(key), b64_encode_name, b64_encode_name_len); - if (nret < 0) { - ret = -1; - ERROR("Encode auth to base64 failed"); - goto out; - } - name_size = 1 + strlen(b64_encode_name) + 1; // '=' + encode string + '\0' - - base_name = (char *)util_common_calloc_s(name_size * sizeof(char)); - if (base_name == NULL) { - ERROR("Out of memory"); - ret = -1; - goto out; - } - - nret = snprintf(base_name, name_size, "=%s", b64_encode_name); - if (nret < 0 || (size_t)nret >= name_size) { - ERROR("Out of memory"); - ret = -1; - goto out; - } - DEBUG("big data file name : %s", base_name); - -out: - if (ret != 0) { - free(base_name); - base_name = NULL; - } - free(b64_encode_name); - - return base_name; -} - static int get_data_path(const char *id, const char *key, char *path, size_t len) { int ret = 0; @@ -1779,7 +1709,7 @@ int image_store_set_names(const char *id, const char **names, size_t names_len) } if (!image_store_lock(EXCLUSIVE)) { - ERROR("Failed to lock image store with exclusive lock, not allowed to change image name assignments"); + ERROR("Failed to lock image store with exclusive lock, not allowed to change image names assignments"); return -1; } @@ -1914,7 +1844,11 @@ int image_store_set_metadata(const char *id, const char *metadata) free(img->simage->metadata); img->simage->metadata = util_strdup_s(metadata); - save_image(img); + if (save_image(img) != 0) { + ERROR("Failed to save image"); + ret = -1; + goto out; + } out: image_ref_dec(img); @@ -2357,7 +2291,11 @@ int image_store_set_image_size(const char *id, uint64_t size) } img->simage->size = size; - save_image(img); + if (save_image(img) != 0) { + ERROR("Failed to save image"); + ret = -1; + goto out; + } out: image_ref_dec(img); diff --git a/src/image/oci/storage/rootfs_store/rootfs.c b/src/image/oci/storage/rootfs_store/rootfs.c index 134544c..f3b5984 100644 --- a/src/image/oci/storage/rootfs_store/rootfs.c +++ b/src/image/oci/storage/rootfs_store/rootfs.c @@ -51,7 +51,7 @@ cntrootfs_t *new_rootfs(storage_rootfs *scntr) return NULL; } - c->scontainer = scntr; + c->srootfs = scntr; return c; @@ -86,8 +86,8 @@ void free_rootfs_t(cntrootfs_t *ptr) if (ptr == NULL) { return; } - free_storage_rootfs(ptr->scontainer); - ptr->scontainer = NULL; + free_storage_rootfs(ptr->srootfs); + ptr->srootfs = NULL; free(ptr); } diff --git a/src/image/oci/storage/rootfs_store/rootfs.h b/src/image/oci/storage/rootfs_store/rootfs.h index daf8c82..41aaa63 100644 --- a/src/image/oci/storage/rootfs_store/rootfs.h +++ b/src/image/oci/storage/rootfs_store/rootfs.h @@ -26,7 +26,7 @@ extern "C" { #endif typedef struct _cntrootfs_t { - storage_rootfs *scontainer; + storage_rootfs *srootfs; uint64_t refcnt; } cntrootfs_t; diff --git a/src/image/oci/storage/rootfs_store/rootfs_store.c b/src/image/oci/storage/rootfs_store/rootfs_store.c index 2083456..c605abb 100644 --- a/src/image/oci/storage/rootfs_store/rootfs_store.c +++ b/src/image/oci/storage/rootfs_store/rootfs_store.c @@ -10,7 +10,7 @@ * See the Mulan PSL v2 for more details. * Author: wujing * Create: 2020-05-12 - * Description: provide image store functions + * Description: provide container rootfs store functions ******************************************************************************/ #define _GNU_SOURCE #include "rootfs_store.h" @@ -47,17 +47,23 @@ typedef struct rootfs_store { bool loaded; } rootfs_store_t; +enum lock_type { + SHARED = 0, + EXCLUSIVE +}; + rootfs_store_t *g_rootfs_store = NULL; -static inline bool rootfs_store_lock(bool writable) +static inline bool rootfs_store_lock(enum lock_type type) { int nret = 0; - if (writable) { - nret = pthread_rwlock_wrlock(&g_rootfs_store->rwlock); - } else { + if (type == SHARED) { nret = pthread_rwlock_rdlock(&g_rootfs_store->rwlock); + } else { + nret = pthread_rwlock_wrlock(&g_rootfs_store->rwlock); } + if (nret != 0) { ERROR("Lock memory store failed: %s", strerror(nret)); return false; @@ -121,6 +127,44 @@ static void rootfs_store_field_kvfree(void *key, void *value) free(key); } +static inline int get_data_dir(const char *id, char *path, size_t len) +{ + int nret = snprintf(path, len, "%s/%s", g_rootfs_store->dir, id); + return (nret < 0 || (size_t)nret >= len) ? -1 : 0; +} + + +static int get_data_path(const char *id, const char *key, char *path, size_t len) +{ + int ret = 0; + int nret = 0; + char *data_base_name = NULL; + char data_dir[PATH_MAX] = { 0x00 }; + + data_base_name = make_big_data_base_name(key); + if (data_base_name == NULL) { + ERROR("Failed to make big data base name"); + return -1; + } + + if (get_data_dir(id, data_dir, sizeof(data_dir)) != 0) { + ERROR("Failed to get rootfs data dir: %s", id); + ret = -1; + goto out; + } + + nret = snprintf(path, len, "%s/%s", data_dir, data_base_name); + if (nret < 0 || (size_t)nret >= len) { + ERROR("Failed to get big data base path"); + ret = -1; + goto out; + } + +out: + free(data_base_name); + return ret; +} + static int do_append_container(storage_rootfs *c) { cntrootfs_t *cntr = NULL; @@ -190,7 +234,7 @@ static int get_containers_from_json() char *id_patten = "^[a-f0-9]{64}$"; char container_path[PATH_MAX] = { 0x00 }; - if (!rootfs_store_lock(true)) { + if (!rootfs_store_lock(EXCLUSIVE)) { ERROR("Failed to lock container store"); return -1; } @@ -242,30 +286,30 @@ static int remove_name(cntrootfs_t *cntr, const char *name) return 0; } - for (i = 0; i < cntr->scontainer->names_len; i++) { - if (strcmp(cntr->scontainer->names[i], name) == 0) { + for (i = 0; i < cntr->srootfs->names_len; i++) { + if (strcmp(cntr->srootfs->names[i], name) == 0) { count++; } } - new_size = (cntr->scontainer->names_len - count) * sizeof(char *); + new_size = (cntr->srootfs->names_len - count) * sizeof(char *); tmp_names = (char **)util_common_calloc_s(new_size); if (tmp_names == NULL) { ERROR("Out of memory"); return -1; } - for (i = 0; i < cntr->scontainer->names_len; i++) { - if (strcmp(cntr->scontainer->names[i], name) != 0) { - tmp_names[index++] = util_strdup_s(cntr->scontainer->names[i]); + for (i = 0; i < cntr->srootfs->names_len; i++) { + if (strcmp(cntr->srootfs->names[i], name) != 0) { + tmp_names[index++] = util_strdup_s(cntr->srootfs->names[i]); } - free(cntr->scontainer->names[i]); - cntr->scontainer->names[i] = NULL; + free(cntr->srootfs->names[i]); + cntr->srootfs->names[i] = NULL; } - free(cntr->scontainer->names); - cntr->scontainer->names = tmp_names; - cntr->scontainer->names_len = index; + free(cntr->srootfs->names); + cntr->srootfs->names = tmp_names; + cntr->srootfs->names_len = index; tmp_names = NULL; return 0; @@ -286,8 +330,8 @@ static int save_rootfs(cntrootfs_t *cntr) parser_error err = NULL; char *json_data = NULL; - if (get_container_path(cntr->scontainer->id, container_path, sizeof(container_path)) != 0) { - ERROR("Failed to get container path by id: %s", cntr->scontainer->id); + if (get_container_path(cntr->srootfs->id, container_path, sizeof(container_path)) != 0) { + ERROR("Failed to get container path by id: %s", cntr->srootfs->id); return -1; } @@ -298,7 +342,7 @@ static int save_rootfs(cntrootfs_t *cntr) return -1; } - json_data = storage_rootfs_generate_json(cntr->scontainer, NULL, &err); + json_data = storage_rootfs_generate_json(cntr->srootfs, NULL, &err); if (json_data == NULL) { ERROR("Failed to generate container json path string:%s", err ? err : " "); ret = -1; @@ -324,27 +368,27 @@ static int load_container_to_store_field(cntrootfs_t *cntr) bool should_save = false; size_t i; - if (!map_replace(g_rootfs_store->byid, (void *)cntr->scontainer->id, (void *)cntr)) { + if (!map_replace(g_rootfs_store->byid, (void *)cntr->srootfs->id, (void *)cntr)) { ERROR("Failed to insert container to id index"); return -1; } - if (!map_replace(g_rootfs_store->bylayer, (void *)cntr->scontainer->layer, (void *)cntr)) { + if (!map_replace(g_rootfs_store->bylayer, (void *)cntr->srootfs->layer, (void *)cntr)) { ERROR("Failed to insert container to layer index"); return -1; } - for (i = 0; i < cntr->scontainer->names_len; i++) { - cntrootfs_t *conflict_container = (cntrootfs_t *)map_search(g_rootfs_store->byname, (void *)cntr->scontainer->names[i]); + for (i = 0; i < cntr->srootfs->names_len; i++) { + cntrootfs_t *conflict_container = (cntrootfs_t *)map_search(g_rootfs_store->byname, (void *)cntr->srootfs->names[i]); if (conflict_container != NULL) { - if (remove_name(conflict_container, cntr->scontainer->names[i]) != 0) { + if (remove_name(conflict_container, cntr->srootfs->names[i]) != 0) { ERROR("Failed to remove name from conflict container"); ret = -1; goto out; } should_save = true; } - if (!map_replace(g_rootfs_store->byname, (void *)cntr->scontainer->names[i], (void *)cntr)) { + if (!map_replace(g_rootfs_store->byname, (void *)cntr->srootfs->names[i], (void *)cntr)) { ERROR("Failed to insert containes to name index"); ret = -1; goto out; @@ -723,7 +767,7 @@ char *rootfs_store_create(const char *id, const char **names, size_t names_len, return NULL; } - if (!rootfs_store_lock(true)) { + if (!rootfs_store_lock(EXCLUSIVE)) { ERROR("Failed to lock container store, not allowed to create new containers"); return NULL; } @@ -856,19 +900,6 @@ found: return value; } -static inline cntrootfs_t *lookup_with_lock(const char *id) -{ - cntrootfs_t *cntr = NULL; - - if (!rootfs_store_lock(false)) { - return NULL; - } - - cntr = lookup(id); - rootfs_store_unlock(); - return cntr; -} - char *rootfs_store_lookup(const char *id) { char *container_id = NULL; @@ -884,24 +915,24 @@ char *rootfs_store_lookup(const char *id) return NULL; } - cntr = lookup_with_lock(id); + if (!rootfs_store_lock(SHARED)) { + ERROR("Failed to lock rootfs store, not allowed to lookup rootfs id assginments"); + return NULL; + } + + cntr = lookup(id); if (cntr == NULL) { ERROR("Container not known"); return NULL; } - container_id = util_strdup_s(cntr->scontainer->id); + container_id = util_strdup_s(cntr->srootfs->id); rootfs_ref_dec(cntr); + rootfs_store_unlock(); return container_id; } -static inline int get_data_dir(const char *id, char *path, size_t len) -{ - int nret = snprintf(path, len, "%s/%s", g_rootfs_store->dir, id); - return (nret < 0 || (size_t)nret >= len) ? -1 : 0; -} - static int remove_rootfs_from_memory(const char *id) { struct linked_list *item = NULL; @@ -922,14 +953,14 @@ static int remove_rootfs_from_memory(const char *id) goto out; } - if (!map_remove(g_rootfs_store->bylayer, cntr->scontainer->layer)) { + if (!map_remove(g_rootfs_store->bylayer, cntr->srootfs->layer)) { ERROR("Failed to remove rootfs from layers map in rootfs store"); ret = -1; goto out; } - for (; i < cntr->scontainer->names_len; i++) { - if (!map_remove(g_rootfs_store->byname, (void *)cntr->scontainer->names[i])) { + for (; i < cntr->srootfs->names_len; i++) { + if (!map_remove(g_rootfs_store->byname, (void *)cntr->srootfs->names[i])) { ERROR("Failed to remove rootfs from names index in rootfs store"); ret = -1; goto out; @@ -938,7 +969,7 @@ static int remove_rootfs_from_memory(const char *id) linked_list_for_each_safe(item, &(g_rootfs_store->rootfs_list), next) { cntrootfs_t *tmp = (cntrootfs_t *)item->elem; - if (strcmp(tmp->scontainer->id, id) != 0) { + if (strcmp(tmp->srootfs->id, id) != 0) { continue; } linked_list_del(item); @@ -986,7 +1017,7 @@ int rootfs_store_delete(const char *id) return -1; } - if (!rootfs_store_lock(true)) { + if (!rootfs_store_lock(EXCLUSIVE)) { ERROR("Failed to lock rootfs store"); ret = -1; goto out; @@ -999,13 +1030,13 @@ int rootfs_store_delete(const char *id) goto out; } - if (remove_rootfs_from_memory(cntr->scontainer->id) != 0) { + if (remove_rootfs_from_memory(cntr->srootfs->id) != 0) { ERROR("Failed to remove rootfs from memory"); ret = -1; goto out; } - if (remove_rootfs_dir(cntr->scontainer->id) != 0) { + if (remove_rootfs_dir(cntr->srootfs->id) != 0) { ERROR("Failed to delete rootfs directory"); ret = -1; goto out; @@ -1038,13 +1069,13 @@ static int delete_rootfs_from_store_without_lock(const char *id) return -1; } - if (remove_rootfs_from_memory(cntr->scontainer->id) != 0) { + if (remove_rootfs_from_memory(cntr->srootfs->id) != 0) { ERROR("Failed to remove rootfs from memory"); ret = -1; goto out; } - if (remove_rootfs_dir(cntr->scontainer->id) != 0) { + if (remove_rootfs_dir(cntr->srootfs->id) != 0) { ERROR("Failed to delete rootfs directory"); ret = -1; goto out; @@ -1068,13 +1099,13 @@ int rootfs_store_wipe() return -1; } - if (!rootfs_store_lock(true)) { + if (!rootfs_store_lock(EXCLUSIVE)) { ERROR("Failed to lock rootfs store, not allowed to delete rootfs"); ret = -1; } linked_list_for_each_safe(item, &(g_rootfs_store->rootfs_list), next) { - id = util_strdup_s(((cntrootfs_t *)item->elem)->scontainer->id); + id = util_strdup_s(((cntrootfs_t *)item->elem)->srootfs->id); if (delete_rootfs_from_store_without_lock(id) != 0) { ERROR("Failed to delete rootfs: %s", id); ret = -1; @@ -1090,63 +1121,704 @@ out: return ret; } -int rootfs_store_set_big_data(const char *id, const char *key, const char *data) +static bool get_value_from_json_map_string_int64(json_map_string_int64 *map, const char *key, int64_t *value) { - return 0; -} + size_t i; -int rootfs_store_set_names(const char *id, const char **names, size_t names_len) -{ - return 0; -} + for (i = 0; i < map->len; i++) { + if (strcmp(key, map->keys[i]) == 0) { + *value = map->values[i]; + return true; + } + } -int rootfs_store_set_metadata(const char *id, const char *metadata) -{ - return 0; + return false; } -int rootfs_store_save(cntrootfs_t *c) +static char *get_value_from_json_map_string_string(json_map_string_string *map, const char *key) { - return 0; -} + size_t i; -bool rootfs_store_exists(const char *id) -{ - return false; -} + if (map == NULL) { + return NULL; + } -storage_rootfs *rootfs_store_get_rootfs(const char *id) -{ - return NULL; -} + for (i = 0; i < map->len; i++) { + if (strcmp(key, map->keys[i]) == 0) { + return util_strdup_s(map->values[i]); + } + } -char *rootfs_store_big_data(const char *id, const char *key) -{ return NULL; } -int64_t rootfs_store_big_data_size(const char *id, const char *key) +static int append_big_data_name(storage_rootfs *rootfs, const char *name) { - return -1; + size_t new_size, old_size; + char **tmp_names = NULL; + + if (name == NULL) { + return 0; + } + + old_size = rootfs->big_data_names_len * sizeof(char *); + new_size = old_size + sizeof(char *); + + if (mem_realloc((void **)&tmp_names, new_size, (void *)rootfs->big_data_names, old_size) != 0) { + ERROR("Failed to realloc memory"); + return -1; + } + + rootfs->big_data_names = tmp_names; + rootfs->big_data_names[rootfs->big_data_names_len++] = util_strdup_s(name); + + return 0; } -char *rootfs_store_big_data_digest(const char *id, const char *key) +static int update_rootfs_with_big_data(cntrootfs_t *img, const char *key, const char *data, bool *should_save) { - return NULL; -} + int ret = 0; + size_t i; + bool size_found = false; + bool add_name = true; + int64_t old_size; + char *old_digest = NULL; + char *new_digest = NULL; + char *full_digest = NULL; + + if (img->srootfs->big_data_sizes == NULL) { + img->srootfs->big_data_sizes = (json_map_string_int64 *)util_common_calloc_s(sizeof(json_map_string_int64)); + if (img->srootfs->big_data_sizes == NULL) { + ERROR("Out of memory"); + return -1; + } + } -int rootfs_store_big_data_names(const char *id, char ***names, size_t *names_len) + size_found = get_value_from_json_map_string_int64(img->srootfs->big_data_sizes, key, &old_size); + append_json_map_string_int64(img->srootfs->big_data_sizes, key, (int64_t)strlen(data)); + + if (img->srootfs->big_data_digests == NULL) { + img->srootfs->big_data_digests = (json_map_string_string *)util_common_calloc_s(sizeof(json_map_string_string)); + if (img->srootfs->big_data_digests == NULL) { + ERROR("Out of memory"); + return -1; + } + } + + old_digest = get_value_from_json_map_string_string(img->srootfs->big_data_digests, key); + new_digest = sha256_digest_str(data); + full_digest = util_full_digest(new_digest); + append_json_map_string_string(img->srootfs->big_data_digests, key, full_digest); + + if (!size_found || old_size != (int64_t)strlen(data) || + old_digest == NULL || strcmp(old_digest, full_digest) != 0) { + *should_save = true; + } + + for (i = 0; i < img->srootfs->big_data_names_len; i++) { + if (strcmp(img->srootfs->big_data_names[i], key) == 0) { + add_name = false; + break; + } + } + + if (add_name) { + if (append_big_data_name(img->srootfs, key) != 0) { + ERROR("Failed to append big data name"); + ret = -1; + goto out; + } + *should_save = true; + } + +out: + free(old_digest); + free(new_digest); + free(full_digest); + return ret; +} +int rootfs_store_set_big_data(const char *id, const char *key, const char *data) { - return 0; + int ret = 0; + cntrootfs_t *cntr = NULL; + const char *rootfs_id = NULL; + char rootfs_dir[PATH_MAX] = { 0x00 }; + char big_data_file[PATH_MAX] = { 0x00 }; + bool save = false; + + if (key == NULL || strlen(key) == 0) { + ERROR("Not a valid name for a big data item, can't set empty name for rootfs big data item"); + return -1; + } + + if (g_rootfs_store == NULL) { + ERROR("Rootfs store is not ready"); + return -1; + } + + if (!rootfs_store_lock(EXCLUSIVE)) { + ERROR("Failed to lock rootfs store with exclusive lock, not allowed to change rootfs big data assignments"); + ret = -1; + goto out; + } + + cntr = lookup(id); + if (cntr == NULL) { + ERROR("Failed to lookup rootfs from store"); + ret = -1; + goto out; + } + rootfs_id = cntr->srootfs->id; + + if (get_data_dir(rootfs_id, rootfs_dir, sizeof(rootfs_dir)) != 0) { + ERROR("Failed to get rootfs data dir: %s", id); + ret = -1; + goto out; + } + + ret = util_mkdir_p(rootfs_dir, IMAGE_STORE_PATH_MODE); + if (ret < 0) { + ERROR("Unable to create directory %s.", rootfs_dir); + ret = -1; + goto out; + } + + if (get_data_path(rootfs_id, key, big_data_file, sizeof(big_data_file)) != 0) { + ERROR("Failed to get big data file path: %s.", key); + ret = -1; + goto out; + } + + if (util_atomic_write_file(big_data_file, data, strlen(data), SECURE_CONFIG_FILE_MODE) != 0) { + ERROR("Failed to save big data file: %s", big_data_file); + ret = -1; + goto out; + } + + if (update_rootfs_with_big_data(cntr, key, data, &save) != 0) { + ERROR("Failed to update rootfs big data"); + ret = -1; + goto out; + } + + if (save && save_rootfs(cntr) != 0) { + ERROR("Failed to complete persistence to disk"); + ret = -1; + goto out; + } + +out: + rootfs_ref_dec(cntr); + rootfs_store_unlock(); + return ret; + } -char *rootfs_store_metadata(const char *id) +int rootfs_store_set_names(const char *id, const char **names, size_t names_len) { - return NULL; + int ret = 0; + cntrootfs_t *cntr = NULL; + cntrootfs_t *other_cntr = NULL; + char **unique_names = NULL; + size_t unique_names_len = 0; + size_t i; + + if (id == NULL) { + ERROR("Invalid paratemer, id is NULL"); + return -1; + } + + if (names == NULL || names_len == 0) { + ERROR("Cannot leave the rootfs name empty"); + return -1; + } + + if (g_rootfs_store == NULL) { + ERROR("Container store is not ready"); + return -1; + } + + if (!rootfs_store_lock(EXCLUSIVE)) { + ERROR("Failed to lock rootfs store with exclusive lock, not allowed to change rootfs names assignments"); + return -1; + } + + cntr = lookup(id); + if (cntr == NULL) { + ERROR("Rootfs not known"); + ret = -1; + goto out; + } + + if (util_string_array_unique((const char **)names, names_len, &unique_names, &unique_names_len) != 0) { + ERROR("Failed to unique names"); + ret = -1; + goto out; + } + + for (i = 0; i < cntr->srootfs->names_len; i++) { + if (!map_remove(g_rootfs_store->byname, (void *)cntr->srootfs->names[i])) { + ERROR("Failed to remove rootfs from ids map in rootfs store : %s", cntr->srootfs->names[i]); + ret = -1; + goto out; + } + } + + for (i = 0; i < unique_names_len; i++) { + other_cntr = (cntrootfs_t *)map_search(g_rootfs_store->byname, (void *)unique_names[i]); + if (other_cntr != NULL && remove_name(other_cntr, unique_names[i]) != 0) { + ERROR("Failed to remove name from other container rootfs"); + ret = -1; + goto out; + } + if (!map_replace(g_rootfs_store->byname, unique_names[i], (void *)cntr)) { + ERROR("Failed to update byname map in rootfs store"); + ret = -1; + goto out; + } + } + + util_free_array_by_len(cntr->srootfs->names, cntr->srootfs->names_len); + cntr->srootfs->names = unique_names; + cntr->srootfs->names_len = unique_names_len; + unique_names = NULL; + unique_names_len = 0; + + if (save_rootfs(cntr) != 0) { + ERROR("Failed to update container"); + ret = -1; + goto out; + } + +out: + util_free_array_by_len(unique_names, unique_names_len); + rootfs_ref_dec(cntr); + rootfs_store_unlock(); + return ret; } -int rootfs_store_get_all_rootfs(struct rootfs_list *all_rootfs) +int rootfs_store_set_metadata(const char *id, const char *metadata) { - return 0; + int ret = 0; + cntrootfs_t *cntr = NULL; + + if (id == NULL || metadata == NULL) { + ERROR("Invalid paratemer: id(%s), metadata(%s)", id, metadata); + return -1; + } + + if (g_rootfs_store == NULL) { + ERROR("Container store is not ready"); + return -1; + } + + if (!rootfs_store_lock(EXCLUSIVE)) { + ERROR("Failed to lock rootfs store with exclusive lock, not allowed to modify rootfs metadata"); + return -1; + } + + cntr = lookup(id); + if (cntr == NULL) { + ERROR("Rootfs not known"); + ret = -1; + goto out; + } + + free(cntr->srootfs->metadata); + cntr->srootfs->metadata = util_strdup_s(metadata); + if (save_rootfs(cntr) != 0) { + ERROR("Failed to save container rootfs"); + ret = -1; + goto out; + } + +out: + rootfs_ref_dec(cntr); + rootfs_store_unlock(); + return ret; +} + +int rootfs_store_save(cntrootfs_t *c) +{ + int ret = 0; + + if (c == NULL) { + ERROR("Invalid parameter, container rootfs is NULL"); + return -1; + } + + if (g_rootfs_store == NULL) { + ERROR("Rootfs store is not ready"); + return -1; + } + + if (!rootfs_store_lock(SHARED)) { + ERROR("Failed to lock rootfs store with shared lock, not allowed to save rootfs"); + return -1; + } + + ret = save_rootfs(c); + + rootfs_store_unlock(); + + return ret; +} + +bool rootfs_store_exists(const char *id) +{ + bool ret = true; + cntrootfs_t *cntr = NULL; + + if (id == NULL) { + ERROR("Invalid paratemer, id is NULL"); + return false; + } + + if (g_rootfs_store == NULL) { + ERROR("Rootfs store is not ready"); + return false; + } + + if (!rootfs_store_lock(SHARED)) { + ERROR("Failed to lock rootfs store with shared lock, not allowed to get rootfs exist info"); + return false; + } + + cntr = lookup(id); + if (cntr == NULL) { + ERROR("Rootfs not known"); + ret = false; + goto out; + } + +out: + rootfs_ref_dec(cntr); + rootfs_store_unlock(); + return ret; +} + +static storage_rootfs *copy_rootfs(const storage_rootfs *rootfs) +{ + char *json = NULL; + parser_error err = NULL; + storage_rootfs *ans = NULL; + + if (rootfs == NULL) { + return NULL; + } + + json = storage_rootfs_generate_json(rootfs, NULL, &err); + if (json == NULL) { + ERROR("Failed to generate json: %s", err); + goto out; + } + ans = storage_rootfs_parse_data(json, NULL, &err); + if (ans == NULL) { + ERROR("Failed to parse json: %s", err); + goto out; + } + +out: + free(err); + free(json); + return ans; +} + +storage_rootfs *rootfs_store_get_rootfs(const char *id) +{ + cntrootfs_t *cntr = NULL; + storage_rootfs *dup_rootfs = NULL; + + if (id == NULL) { + ERROR("Invalid parameter, id is NULL"); + return NULL; + } + + if (g_rootfs_store == NULL) { + ERROR("Rootfs store is not ready"); + return NULL; + } + + if (!rootfs_store_lock(SHARED)) { + ERROR("Failed to rootfs store with shared lock, not allowed to get rootfs from store"); + return NULL; + } + + cntr = lookup(id); + if (cntr == NULL) { + ERROR("Rootfs not known"); + goto out; + } + + dup_rootfs = copy_rootfs(cntr->srootfs); + +out: + rootfs_ref_dec(cntr); + rootfs_store_unlock(); + return dup_rootfs; +} + +char *rootfs_store_big_data(const char *id, const char *key) +{ + int ret = 0; + cntrootfs_t *cntr = NULL; + size_t filesize; + char filename[PATH_MAX] = { 0x00 }; + char *content = NULL; + + if (id == NULL) { + ERROR("Invalid parameter, id is NULL"); + return NULL; + } + + if (key == NULL || strlen(key) == 0) { + ERROR("Not a valid name for a big data item, can't retrieve rootfs big data value for empty name"); + return NULL; + } + + if (g_rootfs_store == NULL) { + ERROR("Rootfs store is not read"); + return NULL; + } + + if (!rootfs_store_lock(SHARED)) { + ERROR("Failed to lock rootfs store with shared lock, not allowed to get rootfs big data"); + return NULL; + } + + cntr = lookup(id); + if (cntr == NULL) { + ERROR("Rootfs not known"); + goto out; + } + + ret = get_data_path(cntr->srootfs->id, key, filename, sizeof(filename)); + + if (ret != 0) { + ERROR("Failed to get big data file path: %s.", key); + goto out; + } + + content = read_file(filename, &filesize); + +out: + rootfs_ref_dec(cntr); + rootfs_store_unlock(); + return content; +} + +static int get_size_with_update_big_data(const char *id, const char *key, int64_t *size) +{ + int ret = 0; + cntrootfs_t *cntr = NULL; + char *data = NULL; + + data = rootfs_store_big_data(id, key); + if (data == NULL) { + return -1; + } + + if (rootfs_store_set_big_data(id, key, data) != 0) { + free(data); + return -1; + } + + free(data); + + if (!rootfs_store_lock(SHARED)) { + ERROR("Failed to lock rootfs store with shared lock, not allowed to get rootfs big data size assignments"); + return -1; + } + + cntr = lookup(id); + if (cntr == NULL) { + ERROR("Rootfs not known"); + ret = -1; + goto out; + } + + (void)get_value_from_json_map_string_int64(cntr->srootfs->big_data_sizes, key, size); + +out: + rootfs_ref_dec(cntr); + rootfs_store_unlock(); + return ret; +} + +int64_t rootfs_store_big_data_size(const char *id, const char *key) +{ + bool bret = false; + cntrootfs_t *cntr = NULL; + int64_t size = -1; + + if (id == NULL) { + ERROR("Invalid parameter, id is NULL"); + return -1; + } + + if (key == NULL || strlen(key) == 0) { + ERROR("Not a valid name for a big data item, can't retrieve rootfs big data value for empty name"); + return -1; + } + + if (g_rootfs_store == NULL) { + ERROR("Rootfs store is not ready"); + return -1; + } + + if (!rootfs_store_lock(SHARED)) { + ERROR("Failed to lock rootfs store with shared lock, not allowed to get rootfs big data size assignments"); + return -1; + } + + cntr = lookup(id); + if (cntr == NULL) { + ERROR("Rootfs not known"); + goto out; + } + + bret = get_value_from_json_map_string_int64(cntr->srootfs->big_data_sizes, key, &size); + + rootfs_ref_dec(cntr); + + if (bret || get_size_with_update_big_data(id, key, &size) == 0) { + goto out; + } + + ERROR("Size is not known"); + +out: + rootfs_store_unlock(); + return size; +} + +char *rootfs_store_big_data_digest(const char *id, const char *key) +{ + return NULL; +} + +int rootfs_store_big_data_names(const char *id, char ***names, size_t *names_len) +{ + int ret = 0; + cntrootfs_t *cntr = NULL; + + if (id == NULL) { + ERROR("Invalid parameter, id is NULL"); + return -1; + } + + if (g_rootfs_store == NULL) { + ERROR("Rootfs store is not ready"); + return -1; + } + + if (!rootfs_store_lock(SHARED)) { + ERROR("Failed to lock rootfs store with shared lock, not allowed to get rootfs big data names assignments"); + return -1; + } + + cntr = lookup(id); + if (cntr == NULL) { + ERROR("Rootfs not known"); + ret = -1; + goto out; + } + + if (dup_array_of_strings((const char **)cntr->srootfs->big_data_names, cntr->srootfs->big_data_names_len, names, + names_len) != 0) { + ERROR("Failed to dup rootfs's names"); + ret = -1; + goto out; + } + +out: + rootfs_ref_dec(cntr); + rootfs_store_unlock(); + return ret; +} + +char *rootfs_store_metadata(const char *id) +{ + cntrootfs_t *img = NULL; + char *metadata = NULL; + + if (id == NULL) { + ERROR("Invalid parameter, id is NULL"); + return NULL; + } + + if (g_rootfs_store == NULL) { + ERROR("Rootfs store is not ready"); + return NULL; + } + + if (!rootfs_store_lock(SHARED)) { + ERROR("Failed to lock rootfs store with shared lock, not allowed to get rootfs metadata assignments"); + return NULL; + } + + img = lookup(id); + if (img == NULL) { + ERROR("Rootfs not known"); + goto out; + } + + metadata = util_strdup_s(img->srootfs->metadata); + +out: + rootfs_ref_dec(img); + rootfs_store_unlock(); + return metadata; +} + +int rootfs_store_get_all_rootfs(struct rootfs_list *all_rootfs) +{ + int ret = 0; + struct linked_list *item = NULL; + struct linked_list *next = NULL; + + if (all_rootfs == NULL) { + ERROR("Invalid input paratemer, memory should be allocated first"); + return -1; + } + + if (g_rootfs_store == NULL) { + ERROR("Rootfs store is not already!"); + return -1; + } + + if (!rootfs_store_lock(SHARED)) { + ERROR("Failed to lock rootfs store with shared lock, not allowed to get all the known rootfss"); + return -1; + } + + if (g_rootfs_store->rootfs_list_len == 0) { + goto out; + } + + all_rootfs->rootfs = util_common_calloc_s(g_rootfs_store->rootfs_list_len * sizeof(storage_rootfs *)); + if (all_rootfs->rootfs == NULL) { + ERROR("Out of memory"); + ret = -1; + goto out; + } + + linked_list_for_each_safe(item, &(g_rootfs_store->rootfs_list), next) { + storage_rootfs *tmp_rootfs = NULL; + cntrootfs_t *img = (cntrootfs_t *)item->elem; + tmp_rootfs = copy_rootfs(img->srootfs); + if (tmp_rootfs == NULL) { + ERROR("Failed to copy container rootfs"); + ret = -1; + goto out; + } + + all_rootfs->rootfs[all_rootfs->rootfs_len++] = tmp_rootfs; + tmp_rootfs = NULL; + } + +out: + rootfs_store_unlock(); + return ret; } diff --git a/src/image/oci/storage/storage.h b/src/image/oci/storage/storage.h index f29719b..d59b2cf 100644 --- a/src/image/oci/storage/storage.h +++ b/src/image/oci/storage/storage.h @@ -20,6 +20,7 @@ #include #include "types_def.h" #include "storage_image.h" +#include "storage_rootfs.h" #include "imagetool_images_list.h" #include "imagetool_fs_info.h" @@ -46,7 +47,7 @@ struct layer_list { }; struct rootfs_list { - struct storage_rootfs **rootfs; + storage_rootfs **rootfs; size_t rootfs_len; }; -- GitLab