diff --git a/0001-cleancode-http-request.patch b/0001-cleancode-http-request.patch index ee8cb2a..9ccffc8 100644 --- a/0001-cleancode-http-request.patch +++ b/0001-cleancode-http-request.patch @@ -1,7 +1,7 @@ From c0900d0bb68cb29484f670a67412447df316ff6e Mon Sep 17 00:00:00 2001 From: zhangxiaoyu Date: Tue, 19 Apr 2022 18:33:16 +0800 -Subject: [PATCH 1/3] cleancode: http request +Subject: [PATCH 1/5] cleancode: http request Signed-off-by: zhangxiaoyu --- @@ -207,5 +207,5 @@ index 2ed7fbe8..0b53cf1e 100644 static void close_file(FILE *pagefile) -- -2.25.1 +2.32.0 (Apple Git-132) diff --git a/0002-refactor-mount-parse-in-spec-module.patch b/0002-refactor-mount-parse-in-spec-module.patch index 98de307..28c0225 100644 --- a/0002-refactor-mount-parse-in-spec-module.patch +++ b/0002-refactor-mount-parse-in-spec-module.patch @@ -1,7 +1,7 @@ From b58453982016f9a2f707b51ad54f12583aa21929 Mon Sep 17 00:00:00 2001 From: wujing Date: Wed, 20 Apr 2022 10:52:30 +0800 -Subject: [PATCH 2/3] refactor mount parse in spec module +Subject: [PATCH 2/5] refactor mount parse in spec module Signed-off-by: wujing --- @@ -231,5 +231,5 @@ index 5644b21e..c89f077f 100644 if (tmpfs == NULL) { return NULL; -- -2.25.1 +2.32.0 (Apple Git-132) diff --git a/0003-support-isula-wait-even-if-it-s-not-oci-image.patch b/0003-support-isula-wait-even-if-it-s-not-oci-image.patch index 0117906..7c3a530 100644 --- a/0003-support-isula-wait-even-if-it-s-not-oci-image.patch +++ b/0003-support-isula-wait-even-if-it-s-not-oci-image.patch @@ -1,7 +1,7 @@ From e0c13b23ddee161a6196ca2e0c970704e4bbef0e Mon Sep 17 00:00:00 2001 From: WangFengTu Date: Sun, 24 Apr 2022 14:18:26 +0800 -Subject: [PATCH 3/3] support isula wait even if it's not oci image +Subject: [PATCH 3/5] support isula wait even if it's not oci image Signed-off-by: WangFengTu --- @@ -26,5 +26,5 @@ index 0e5b845c..2deb862c 100644 // `logs` sub-command "logs", false, cmd_logs_main, g_cmd_logs_desc, NULL, &g_cmd_logs_args -- -2.25.1 +2.32.0 (Apple Git-132) diff --git a/0004-add-isula-import-restful-mode.patch b/0004-add-isula-import-restful-mode.patch new file mode 100644 index 0000000..eeb6166 --- /dev/null +++ b/0004-add-isula-import-restful-mode.patch @@ -0,0 +1,267 @@ +From 0f05484cceb58117f165bcc402156194289ea9c3 Mon Sep 17 00:00:00 2001 +From: chengzrz +Date: Thu, 28 Apr 2022 19:11:46 +0800 +Subject: [PATCH 4/5] add isula import restful mode + +Signed-off-by: chengzrz +--- + src/api/services/images/rest/image.rest.h | 3 + + src/client/connect/rest/rest_images_client.c | 107 ++++++++++++++++++ + .../entry/connect/rest/rest_images_service.c | 89 +++++++++++++++ + 3 files changed, 199 insertions(+) + +diff --git a/src/api/services/images/rest/image.rest.h b/src/api/services/images/rest/image.rest.h +index 6ebdc109..a61a285f 100644 +--- a/src/api/services/images/rest/image.rest.h ++++ b/src/api/services/images/rest/image.rest.h +@@ -31,6 +31,8 @@ + #include "isula_libutils/image_logout_response.h" + #include "isula_libutils/image_tag_image_request.h" + #include "isula_libutils/image_tag_image_response.h" ++#include "isula_libutils/image_import_request.h" ++#include "isula_libutils/image_import_response.h" + + #ifndef RestHttpHead + #define RestHttpHead "http://localhost" +@@ -44,6 +46,7 @@ + #define ImagesServiceLogin "/ImagesService/Login" + #define ImagesServiceLogout "/ImagesService/Logout" + #define ImagesServiceTag "/ImagesService/Tag" ++#define ImagesServiceImport "/ImagesService/Import" + + #endif + +diff --git a/src/client/connect/rest/rest_images_client.c b/src/client/connect/rest/rest_images_client.c +index ae754f76..3deeeead 100644 +--- a/src/client/connect/rest/rest_images_client.c ++++ b/src/client/connect/rest/rest_images_client.c +@@ -858,6 +858,112 @@ out: + return ret; + } + ++/* image import request to rest */ ++static int image_import_request_to_rest(const struct isula_import_request *request, char **body, size_t *body_len) ++{ ++ image_import_request *crequest = NULL; ++ parser_error err = NULL; ++ int ret = 0; ++ ++ crequest = util_common_calloc_s(sizeof(image_import_request)); ++ if (crequest == NULL) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ crequest->file = util_strdup_s(request->file); ++ crequest->tag = util_strdup_s(request->tag); ++ ++ *body = image_import_request_generate_json(crequest, NULL, &err); ++ if (*body == NULL) { ++ ERROR("Failed to generate image import request json:%s", err); ++ ret = -1; ++ goto out; ++ } ++ *body_len = strlen(*body) + 1; ++ ++out: ++ free(err); ++ free_image_import_request(crequest); ++ ++ return ret; ++} ++ ++/* unpack image import response */ ++static int unpack_image_import_response(const struct parsed_http_message *message, void *arg) ++{ ++ struct isula_import_response *c_import_response = (struct isula_import_response *)arg; ++ image_import_response *import_response = NULL; ++ parser_error err = NULL; ++ int ret = 0; ++ ++ ret = check_status_code(message->status_code); ++ if (ret != 0) { ++ ERROR("Tag image check status code failed.\n"); ++ goto out; ++ } ++ ++ import_response = image_import_response_parse_data(message->body, NULL, &err); ++ if (import_response == NULL) { ++ ERROR("Invalid import image response:%s", err); ++ ret = -1; ++ goto out; ++ } ++ ++ c_import_response->server_errono = import_response->cc; ++ c_import_response->errmsg = util_strdup_s(import_response->errmsg); ++ c_import_response->id = util_strdup_s(import_response->id); ++ ++ ret = (import_response->cc == ISULAD_SUCCESS) ? 0 : -1; ++ if (message->status_code == RESTFUL_RES_SERVERR) { ++ ret = -1; ++ } ++ ++out: ++ free(err); ++ free_image_import_response(import_response); ++ ++ return ret; ++} ++ ++/* rest image import */ ++static int rest_image_import(const struct isula_import_request *request, struct isula_import_response *response, ++ void *arg) ++{ ++ ++ client_connect_config_t *connect_config = (client_connect_config_t *)arg; ++ const char *socketname = (const char *)(connect_config->socket); ++ char *body = NULL; ++ Buffer *output = NULL; ++ int ret = 0; ++ size_t len = 0; ++ ++ ret = image_import_request_to_rest(request, &body, &len); ++ if (ret != 0) { ++ goto out; ++ } ++ ++ ret = rest_send_requst(socketname, RestHttpHead ImagesServiceImport, body, len, &output); ++ if (ret != 0) { ++ ERROR("Send import request failed."); ++ response->errmsg = util_strdup_s(errno_to_error_message(ISULAD_ERR_CONNECT)); ++ response->cc = ISULAD_ERR_EXEC; ++ goto out; ++ } ++ ++ ret = get_response(output, unpack_image_import_response, (void *)response); ++ if (ret != 0) { ++ ERROR("Get import response failed."); ++ goto out; ++ } ++ ++out: ++ buffer_free(output); ++ put_body(body); ++ ++ return ret; ++} ++ ++ + /* rest images client ops init */ + int rest_images_client_ops_init(isula_connect_ops *ops) + { +@@ -873,6 +979,7 @@ int rest_images_client_ops_init(isula_connect_ops *ops) + ops->image.login = &rest_image_login; + ops->image.logout = &rest_image_logout; + ops->image.tag = &rest_image_tag; ++ ops->image.import = &rest_image_import; + + return 0; + } +diff --git a/src/daemon/entry/connect/rest/rest_images_service.c b/src/daemon/entry/connect/rest/rest_images_service.c +index 39a3bd6c..7107d255 100644 +--- a/src/daemon/entry/connect/rest/rest_images_service.c ++++ b/src/daemon/entry/connect/rest/rest_images_service.c +@@ -797,6 +797,90 @@ out: + free_image_tag_image_response(cresponse); + } + ++/* image import request from rest */ ++static int image_import_request_from_rest(evhtp_request_t *req, image_import_request **crequest) ++{ ++ int ret = 0; ++ size_t body_len; ++ char *body = NULL; ++ parser_error err = NULL; ++ ++ if (get_body(req, &body_len, &body) != 0) { ++ ERROR("Failed to get body"); ++ return -1; ++ } ++ ++ *crequest = image_import_request_parse_data(body, NULL, &err); ++ if (*crequest == NULL) { ++ ERROR("Invalid import request body:%s", err); ++ ret = -1; ++ goto out; ++ } ++ ++out: ++ put_body(body); ++ free(err); ++ ++ return ret; ++} ++ ++/* evhtp send image import repsponse */ ++static void evhtp_send_image_import_repsponse(evhtp_request_t *req, image_import_response *response, int rescode) ++{ ++ parser_error err = NULL; ++ char *response_data = NULL; ++ ++ response_data = image_import_response_generate_json(response, NULL, &err); ++ if (response_data != NULL) { ++ evhtp_send_response(req, response_data, rescode); ++ goto out; ++ } ++ ++ ERROR("Import: failed to generate request json:%s", err); ++ evhtp_send_reply(req, RESTFUL_RES_ERROR); ++ ++out: ++ free(response_data); ++ free(err); ++} ++ ++/* rest image import cb */ ++static void rest_image_import_cb(evhtp_request_t *req, void *arg) ++{ ++ int tret; ++ service_executor_t *cb = NULL; ++ image_import_request *crequest = NULL; ++ image_import_response *cresponse = NULL; ++ ++ // only deal with POST request ++ if (evhtp_request_get_method(req) != htp_method_POST) { ++ evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); ++ return; ++ } ++ ++ cb = get_service_executor(); ++ if (cb == NULL || cb->image.import == NULL) { ++ ERROR("Unimplemented import callback"); ++ evhtp_send_reply(req, RESTFUL_RES_NOTIMPL); ++ return; ++ } ++ ++ tret = image_import_request_from_rest(req, &crequest); ++ if (tret < 0) { ++ ERROR("Bad request"); ++ evhtp_send_reply(req, RESTFUL_RES_SERVERR); ++ goto out; ++ } ++ ++ (void)cb->image.import(crequest, &cresponse); ++ evhtp_send_image_import_repsponse(req, cresponse, RESTFUL_RES_OK); ++ ++out: ++ free_image_import_request(crequest); ++ free_image_import_response(cresponse); ++} ++ ++ + /* rest register images handler */ + int rest_register_images_handler(evhtp_t *htp) + { +@@ -840,5 +924,10 @@ int rest_register_images_handler(evhtp_t *htp) + return -1; + } + ++ if (evhtp_set_cb(htp, ImagesServiceImport, rest_image_import_cb, NULL) == NULL) { ++ ERROR("Failed to register image logout callback"); ++ return -1; ++ } ++ + return 0; + } +-- +2.32.0 (Apple Git-132) + diff --git a/0005-Adapt-to-bionic-libc-parser-for-passwd-and-group-obj.patch b/0005-Adapt-to-bionic-libc-parser-for-passwd-and-group-obj.patch new file mode 100644 index 0000000..ad6d308 --- /dev/null +++ b/0005-Adapt-to-bionic-libc-parser-for-passwd-and-group-obj.patch @@ -0,0 +1,657 @@ +From 1d768559f42375eb3bbb3ad0de52a6b49535e40c Mon Sep 17 00:00:00 2001 +From: chegJH +Date: Thu, 7 Apr 2022 17:33:06 +0800 +Subject: [PATCH 5/5] Adapt to bionic libc, parser for passwd and group object + +Signed-off-by: chegJH +--- + .../modules/image/image_rootfs_handler.c | 25 ++ + src/utils/cutils/utils_pwgr.c | 317 ++++++++++++++++++ + src/utils/cutils/utils_pwgr.h | 33 ++ + test/cutils/CMakeLists.txt | 1 + + test/cutils/utils_pwgr/CMakeLists.txt | 29 ++ + test/cutils/utils_pwgr/group_sample | 8 + + test/cutils/utils_pwgr/passwd_sample | 11 + + test/cutils/utils_pwgr/utils_pwgr_ut.cc | 101 ++++++ + 8 files changed, 525 insertions(+) + create mode 100644 src/utils/cutils/utils_pwgr.c + create mode 100644 src/utils/cutils/utils_pwgr.h + create mode 100644 test/cutils/utils_pwgr/CMakeLists.txt + create mode 100644 test/cutils/utils_pwgr/group_sample + create mode 100644 test/cutils/utils_pwgr/passwd_sample + create mode 100644 test/cutils/utils_pwgr/utils_pwgr_ut.cc + +diff --git a/src/daemon/modules/image/image_rootfs_handler.c b/src/daemon/modules/image/image_rootfs_handler.c +index f7bc9bc9..960d52c7 100644 +--- a/src/daemon/modules/image/image_rootfs_handler.c ++++ b/src/daemon/modules/image/image_rootfs_handler.c +@@ -33,6 +33,7 @@ + #include "path.h" + #include "utils_convert.h" + #include "utils_file.h" ++#include "utils_pwgr.h" + + #define MINUID 0 + #define MAXUID (((1LL << 31) - 1)) +@@ -88,7 +89,11 @@ static int proc_by_fpasswd(FILE *f_passwd, const char *user, defs_process_user * + struct passwd *pwbufp = NULL; + + if (f_passwd != NULL) { ++#ifdef __ANDROID__ ++ errval = util_getpwent_r(f_passwd, &pw, buf, sizeof(buf), &pwbufp); ++#else + errval = fgetpwent_r(f_passwd, &pw, buf, sizeof(buf), &pwbufp); ++#endif + + while (errval == 0 && pwbufp != NULL) { + userfound = b_user_found(user, pwbufp); +@@ -102,7 +107,11 @@ static int proc_by_fpasswd(FILE *f_passwd, const char *user, defs_process_user * + *matched_username = util_strdup_s(pwbufp->pw_name); + break; + } ++#ifdef __ANDROID__ ++ errval = util_getpwent_r(f_passwd, &pw, buf, sizeof(buf), &pwbufp); ++#else + errval = fgetpwent_r(f_passwd, &pw, buf, sizeof(buf), &pwbufp); ++#endif + } + } + +@@ -212,14 +221,22 @@ static int do_proc_by_froup(FILE *f_group, const char *group, defs_process_user + return 0; + } + ++#ifdef __ANDROID__ ++ errval = util_getgrent_r(f_group, &grp, buf, sizeof(buf), &gbufp); ++#else + errval = fgetgrent_r(f_group, &grp, buf, sizeof(buf), &gbufp); ++#endif + while (errval == 0 && gbufp != NULL) { + // Treat numeric group as valid GID + if (group == NULL) { + if (search_group_list(gbufp, matched_username, puser) != 0) { + return -1; + } ++#ifdef __ANDROID__ ++ errval = util_getgrent_r(f_group, &grp, buf, sizeof(buf), &gbufp); ++#else + errval = fgetgrent_r(f_group, &grp, buf, sizeof(buf), &gbufp); ++#endif + continue; + } + +@@ -229,7 +246,11 @@ static int do_proc_by_froup(FILE *f_group, const char *group, defs_process_user + puser->gid = gbufp->gr_gid; + *groupcnt = 1; + } ++#ifdef __ANDROID__ ++ errval = util_getgrent_r(f_group, &grp, buf, sizeof(buf), &gbufp); ++#else + errval = fgetgrent_r(f_group, &grp, buf, sizeof(buf), &gbufp); ++#endif + } + + return 0; +@@ -363,7 +384,11 @@ static int get_additional_groups(char **additional_groups, size_t additional_gro + struct group *gbufp = NULL; + struct group *groups = NULL; + ++#ifdef __ANDROID__ ++ while (f_group != NULL && util_getgrent_r(f_group, &grp, buf, sizeof(buf), &gbufp) == 0) { ++#else + while (f_group != NULL && fgetgrent_r(f_group, &grp, buf, sizeof(buf), &gbufp) == 0) { ++#endif + for (i = 0; i < additional_groups_len; i++) { + if (!group_matched(additional_groups[i], gbufp)) { + continue; +diff --git a/src/utils/cutils/utils_pwgr.c b/src/utils/cutils/utils_pwgr.c +new file mode 100644 +index 00000000..f4588268 +--- /dev/null ++++ b/src/utils/cutils/utils_pwgr.c +@@ -0,0 +1,317 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: hejunjie ++ * Create: 2022-04-08 ++ * Description: Provide line parser for android ++ *******************************************************************************/ ++ ++#define _GNU_SOURCE ++#include "utils_pwgr.h" ++ ++#include ++#include ++#include ++#include ++ ++#include "isula_libutils/log.h" ++#include "utils_string.h" ++#include "utils_convert.h" ++#include "utils_file.h" ++#include "utils.h" ++ ++static int hold_int(const char delim, bool required, char **src, unsigned int *dst) ++{ ++ long long res = 0; ++ char *walker = *src; ++ char *err_str = NULL; ++ ++ if (**src == '\0') { ++ ERROR("Empty subject on given entrie is not allowed."); ++ return -1; ++ } ++ ++ while (*walker != delim) { ++ if (*walker == '\0') { ++ break; ++ } ++ ++walker; ++ } ++ ++ if (*walker == **src) { ++ if (required) { // deafult 0 while required full content but integer part is missing ++ *dst = 0; ++ *src = walker + 1; ++ return 0; ++ } ++ ERROR("Integer part is missing."); ++ ++(*src); ++ return -1; ++ } ++ ++ res = strtoll(*src, &err_str, 0); ++ if (errno == ERANGE) { ++ ERROR("Parse int from string failed."); ++ return -1; ++ } ++ if (res < 0) { ++ ERROR("Gid uid shall not be negative."); ++ return -1; ++ } ++ ++ if (sizeof(void *) > 4 && res > UINT_MAX) { // make sure 64-bit platform behave same as 32-bit ++ res = UINT_MAX; ++ } ++ res = res & UINT_MAX; ++ *dst = (uint32_t)res; ++ *src = err_str + 1; // update src to next valid context in line. ++ ++ return 0; ++} ++ ++static int hold_string(const char delim, char **src, char **dst) ++{ ++ if (**src == delim) { // if src point to deliminator, content parsing is skiped. ++ *dst = ""; ++ *src = *src + 1; ++ return 0; ++ } ++ ++ if (**src == '\0') { ++ return 0; ++ } ++ ++ for (*dst = *src; **src != delim; ++(*src)) { ++ if (**src == '\0') { ++ break; ++ } ++ } ++ if (**src == delim) { ++ **src = '\0'; ++ ++(*src); ++ } ++ ++ return 0; ++} ++ ++static int parse_line_pw(const char delim, char *line, struct passwd *result) ++{ ++ int ret = 0; ++ bool required = false; ++ ++ ret = hold_string(delim, &line, &result->pw_name); ++ if (ret != 0) { ++ ERROR("Parse name error."); ++ return ret; ++ } ++ ++ required = (result->pw_name[0] == '+' || result->pw_name[0] == '-') ? true : false; ++ ++ ret = hold_string(delim, &line, &result->pw_passwd); ++ if (ret != 0) { ++ ERROR("Parse passwd error."); ++ return ret; ++ } ++ ++ ret = hold_int(delim, required, &line, &result->pw_uid); ++ if (ret != 0) { ++ // a legitimate line must have uid ++ ERROR("Parse uid error."); ++ return ret; ++ } ++ ret = hold_int(delim, required, &line, &result->pw_gid); ++ if (ret != 0) { ++ // it's ok to not provide gid ++ ERROR("Parse gid error."); ++ } ++ ++ ret = hold_string(delim, &line, &result->pw_gecos); ++ if (ret != 0) { ++ ERROR("Parse gecos error."); ++ return ret; ++ } ++ ++ ret = hold_string(delim, &line, &result->pw_dir); ++ if (ret != 0) { ++ ERROR("Parse dir error."); ++ return ret; ++ } ++ ++ ret = hold_string(delim, &line, &result->pw_shell); ++ if (ret != 0) { ++ ERROR("Parse shell error."); ++ return ret; ++ } ++ ++ return ret; ++} ++ ++static char **hold_string_list(char **line, char *buf_start, char *buf_end, const char terminator) ++{ ++ char **result = NULL; ++ char **walker = NULL; ++ ++ if (**line == '\0') { ++ return 0; ++ } ++ // For ultimate space usage, the blank area from buffer which was allocated from stack is used ++ buf_start += __alignof__(char *) - 1; ++ // align the starting position of the buffer to use it as a 2d array ++ buf_start -= (buf_start - (char *)0) % __alignof__(char *); ++ // record the starting position for latter return ++ result = (char **)buf_start; ++ // set stop edge for the buffer ++ walker = result; ++ ++ for (; walker < (char **)buf_end; ++walker) { ++ (void)util_trim_space(*line); ++ if (hold_string(',', line, walker) != 0) { ++ ERROR("Parse string list error."); ++ return NULL; ++ } ++ ++ if ((char *)(walker + 2) > buf_end) { ++ return NULL; ++ } ++ ++ if (**line == '\0') { ++ return result; ++ } ++ } ++ ++ return result; ++} ++ ++static int parse_line_gr(const char delim, char *line, size_t buflen, struct group *result) ++{ ++ int ret = 0; ++ bool rf = false; ++ char *freebuff = line + 1 + strlen(line); ++ char *buffend = line + buflen; ++ ++ ret = hold_string(delim, &line, &result->gr_name); ++ if (ret != 0) { ++ ERROR("Parse name error."); ++ return ret; ++ } ++ ++ ret = hold_string(delim, &line, &result->gr_passwd); ++ if (ret != 0) { ++ ERROR("Parse gecos error."); ++ return ret; ++ } ++ if (result->gr_name[0] == '+' || result->gr_name[0] == '-') { ++ rf = true; ++ } ++ ++ ret = hold_int(delim, rf, &line, &result->gr_gid); ++ if (ret != 0) { ++ ERROR("Parse gid error."); ++ return ret; ++ } ++ ++ result->gr_mem = hold_string_list(&line, freebuff, buffend, ','); ++ ++ return 0; ++} ++ ++int util_getpwent_r(FILE *stream, struct passwd *resbuf, char *buffer, size_t buflen, struct passwd **result) ++{ ++ const char delim = ':'; ++ ++ if (stream == NULL || resbuf == NULL || buffer == NULL) { ++ ERROR("Password obj, params is NULL."); ++ return -1; ++ } ++ ++ if (buflen <= 1) { ++ ERROR("Inadiquate buffer length was given."); ++ return -1; ++ } ++ ++ if (*result != NULL) { ++ ERROR("Result shall point to null to start."); ++ return -1; ++ } ++ ++ __fsetlocking(stream, FSETLOCKING_BYCALLER); ++ buffer[buflen - 1] = '\0'; ++ ++ if (feof(stream)) { ++ *result = NULL; ++ return ENOENT; ++ } ++ ++ while (fgets(buffer, buflen, stream) != NULL) { ++ (void)util_trim_space(buffer); ++ if (buffer[0] == '\0' || buffer[0] == '#' || strlen(buffer) < 1) { ++ continue; ++ } ++ ++ if (parse_line_pw(delim, buffer, resbuf) == 0) { ++ break; ++ } ++ ++ if (buffer[buflen - 1] != '\0') { ++ *result = NULL; ++ return ERANGE; ++ } ++ } ++ *result = resbuf; ++ ++ return 0; ++} ++ ++int util_getgrent_r(FILE *stream, struct group *resbuf, char *buffer, size_t buflen, struct group **result) ++{ ++ const char delim = ':'; ++ ++ if (stream == NULL || resbuf == NULL || buffer == NULL) { ++ ERROR("Group obj, params is NULL."); ++ return -1; ++ } ++ ++ if (buflen <= 1) { ++ ERROR("Inadiquate buffer length was given."); ++ return -1; ++ } ++ ++ if (*result != NULL) { ++ ERROR("Result shall point to null to start."); ++ return -1; ++ } ++ ++ __fsetlocking(stream, FSETLOCKING_BYCALLER); ++ buffer[buflen - 1] = '\0'; ++ ++ if (feof(stream)) { ++ *result = NULL; ++ return ENOENT; ++ } ++ ++ while (fgets(buffer, buflen, stream) != NULL) { ++ (void)util_trim_space(buffer); ++ if (buffer[0] == '\0' || buffer[0] == '#' || strlen(buffer) < 1) { ++ continue; ++ } ++ ++ if (parse_line_gr(delim, buffer, buflen, resbuf) == 0) { ++ break; ++ } ++ ++ if (buffer[buflen - 1] != '\0') { ++ *result = NULL; ++ return ERANGE; ++ } ++ } ++ *result = resbuf; ++ ++ return 0; ++} +\ No newline at end of file +diff --git a/src/utils/cutils/utils_pwgr.h b/src/utils/cutils/utils_pwgr.h +new file mode 100644 +index 00000000..45e38059 +--- /dev/null ++++ b/src/utils/cutils/utils_pwgr.h +@@ -0,0 +1,33 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: hejunjie ++ * Create: 2022-04-08 ++ * Description: Provide line parser for android ++ *******************************************************************************/ ++#ifndef UTILS_CUTILS_UTILS_PWGR_H ++#define UTILS_CUTILS_UTILS_PWGR_H ++ ++#include ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++int util_getpwent_r(FILE *stream, struct passwd *resbuf, char *buffer, size_t buflen, struct passwd **result); ++ ++int util_getgrent_r(FILE *stream, struct group *resbuf, char *buffer, size_t buflen, struct group **result); ++ ++#ifdef __cplusplus ++} ++#endif ++#endif // UTILS_CUTILS_UTILS_PWGR_H +diff --git a/test/cutils/CMakeLists.txt b/test/cutils/CMakeLists.txt +index 826255cd..b549f844 100644 +--- a/test/cutils/CMakeLists.txt ++++ b/test/cutils/CMakeLists.txt +@@ -4,3 +4,4 @@ add_subdirectory(utils_string) + add_subdirectory(utils_convert) + add_subdirectory(utils_array) + add_subdirectory(utils_base64) ++add_subdirectory(utils_pwgr) +diff --git a/test/cutils/utils_pwgr/CMakeLists.txt b/test/cutils/utils_pwgr/CMakeLists.txt +new file mode 100644 +index 00000000..548718da +--- /dev/null ++++ b/test/cutils/utils_pwgr/CMakeLists.txt +@@ -0,0 +1,29 @@ ++project(iSulad_UT) ++ ++SET(EXE utils_pwgr_ut) ++ ++add_executable(${EXE} ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_string.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_array.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_file.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_convert.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_verify.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_regex.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_pwgr.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/sha256/sha256.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/map/map.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/map/rb_tree.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/path.c ++ utils_pwgr_ut.cc) ++ ++target_include_directories(${EXE} PUBLIC ++ ${GTEST_INCLUDE_DIR} ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../include ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/common ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/map ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/sha256 ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils ++ ) ++target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${ISULA_LIBUTILS_LIBRARY} -lcrypto -lyajl -lz) ++add_test(NAME ${EXE} COMMAND ${EXE} --gtest_output=xml:${EXE}-Results.xml) +diff --git a/test/cutils/utils_pwgr/group_sample b/test/cutils/utils_pwgr/group_sample +new file mode 100644 +index 00000000..c73883cc +--- /dev/null ++++ b/test/cutils/utils_pwgr/group_sample +@@ -0,0 +1,8 @@ ++root:x:0: ++#bin:x:1: ++ ++-adm:x:4: +++adm:x:4: ++adm:x:4:a,list,of,users ++adm:x:4:are,split,by,comma ++adm:x:4:root,john, boob,jason +\ No newline at end of file +diff --git a/test/cutils/utils_pwgr/passwd_sample b/test/cutils/utils_pwgr/passwd_sample +new file mode 100644 +index 00000000..d4f3250d +--- /dev/null ++++ b/test/cutils/utils_pwgr/passwd_sample +@@ -0,0 +1,11 @@ ++root:x:0:0:root:/root:/bin/bash ++bin:x:1:1:bin:/bin:/sbin/nologin ++bin:x:-1:1:bin:/bin:/sbin/nologin ++uidonly:x:1::bin:/bin:/sbin/nologin ++::::1:1:bin:/bin:/sbin/nologin ++ ++#npt:*:66:77::/etc/ntp:/sbin/nologin ++npt:*:66:77::/etc/ntp:/sbin/nologin ++npt:*:66:77::/etc/ntp:/sbin/nologin:some:extra:context:added +++npt:*::::/etc/ntp:/sbin/nologin ++-npt:*::::/etc/ntp:/sbin/nologin +\ No newline at end of file +diff --git a/test/cutils/utils_pwgr/utils_pwgr_ut.cc b/test/cutils/utils_pwgr/utils_pwgr_ut.cc +new file mode 100644 +index 00000000..1a121f88 +--- /dev/null ++++ b/test/cutils/utils_pwgr/utils_pwgr_ut.cc +@@ -0,0 +1,101 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: hejunjie ++ * Create: 2022-04-08 ++ * Description: utils_pwgr unit test ++ *******************************************************************************/ ++ ++#include ++#include "utils_pwgr.h" ++ ++TEST(utils_pwgr, test_getpwent_r) ++{ ++ std::string path = "../../../../test/cutils/utils_pwgr/passwd_sample"; ++ FILE *f_pw = fopen(path.c_str(), "r"); ++ ASSERT_NE(f_pw, nullptr); ++ ++ struct passwd pw; ++ struct passwd *ppw = nullptr; ++ char buf[BUFSIZ]; ++ ++ std::vector> testcase = { ++ std::make_tuple("root", "x", 0, 0, "root", "/root", "/bin/bash"), ++ std::make_tuple("bin", "x", 1, 1, "bin", "/bin", "/sbin/nologin"), ++ std::make_tuple("uidonly", "x", 1, 0, "bin", "/bin", "/sbin/nologin"), ++ std::make_tuple("npt", "*", 66, 77, "", "/etc/ntp", "/sbin/nologin"), ++ std::make_tuple("npt", "*", 66, 77, "", "/etc/ntp", "/sbin/nologin"), ++ std::make_tuple("+npt", "*", 0, 0, "", "/etc/ntp", "/sbin/nologin"), ++ std::make_tuple("-npt", "*", 0, 0, "", "/etc/ntp", "/sbin/nologin") ++ }; ++ ++ for (const auto &elem : testcase) { ++ ASSERT_EQ(util_getpwent_r(f_pw, &pw, buf, sizeof(buf), &ppw), 0); ++ ASSERT_STREQ(pw.pw_name, std::get<0>(elem).c_str()); ++ ASSERT_STREQ(pw.pw_passwd, std::get<1>(elem).c_str()); ++ ASSERT_EQ(pw.pw_uid, std::get<2>(elem)); ++ ASSERT_EQ(pw.pw_gid, std::get<3>(elem)); ++ ASSERT_STREQ(pw.pw_gecos, std::get<4>(elem).c_str()); ++ ASSERT_STREQ(pw.pw_dir, std::get<5>(elem).c_str()); ++ ASSERT_STREQ(pw.pw_shell, std::get<6>(elem).c_str()); ++ EXPECT_TRUE(ppw == &pw); ++ ppw = nullptr; ++ pw = {0}; ++ } ++ ++ fclose(f_pw); ++} ++ ++TEST(utils_pwgr, test_getgrent_r) ++{ ++ std::string path = "../../../../test/cutils/utils_pwgr/group_sample"; ++ FILE *f_gr = fopen(path.c_str(), "r"); ++ ASSERT_NE(f_gr, nullptr); ++ ++ struct group gr{0}; ++ struct group *pgr = nullptr; ++ char buf[BUFSIZ]; ++ size_t i = 0; ++ size_t j = 0; ++ std::vector> string_list{ ++ {}, {}, {}, ++ {"a", "list", "of", "users"}, ++ {"are", "split", "by", "comma"}, ++ {"root", "john", "boob", "jason"} ++ }; ++ ++ std::vector> testcase = { ++ std::make_tuple("root", "x", 0), ++ std::make_tuple("-adm", "x", 4), ++ std::make_tuple("+adm", "x", 4), ++ std::make_tuple("adm", "x", 4), ++ std::make_tuple("adm", "x", 4), ++ std::make_tuple("adm", "x", 4), ++ }; ++ ++ for (; i < string_list.size(); ++i) { ++ ASSERT_EQ(util_getgrent_r(f_gr, &gr, buf, sizeof(buf), &pgr), 0); ++ ASSERT_STREQ(gr.gr_name, std::get<0>(testcase[i]).c_str()); ++ ASSERT_STREQ(gr.gr_passwd, std::get<1>(testcase[i]).c_str()); ++ ASSERT_EQ(gr.gr_gid, std::get<2>(testcase[i])); ++ if (string_list[i].size()) { ++ for (j = 0; j < string_list[i].size(); ++j) { ++ EXPECT_TRUE(strcmp(gr.gr_mem[j], string_list[i][j].c_str()) == 0); ++ } ++ } else { ++ EXPECT_TRUE(gr.gr_mem == nullptr); ++ } ++ EXPECT_TRUE(pgr == &gr); ++ gr = {0}; ++ pgr = nullptr; ++ } ++ ++ fclose(f_gr); ++} +\ No newline at end of file +-- +2.32.0 (Apple Git-132) + diff --git a/iSulad.spec b/iSulad.spec index 5de7ab9..706bd16 100644 --- a/iSulad.spec +++ b/iSulad.spec @@ -1,5 +1,5 @@ %global _version 2.0.13 -%global _release 2 +%global _release 3 %global is_systemd 1 %global enable_shimv2 1 %global is_embedded 1 @@ -16,6 +16,8 @@ BuildRoot: {_tmppath}/iSulad-%{version} Patch0001: 0001-cleancode-http-request.patch Patch0002: 0002-refactor-mount-parse-in-spec-module.patch Patch0003: 0003-support-isula-wait-even-if-it-s-not-oci-image.patch +Patch0004: 0004-add-isula-import-restful-mode.patch +Patch0005: 0005-Adapt-to-bionic-libc-parser-for-passwd-and-group-obj.patch %ifarch x86_64 aarch64 Provides: libhttpclient.so()(64bit) @@ -243,6 +245,12 @@ fi %endif %changelog +* Mon May 5 2022 hejunjie - 2.0.13-3 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: bionic adaptation for pwgr obj parser + * Mon Apr 25 2022 zhangxiaoyu - 2.0.13-2 - Type: bugfix - ID: NA