From 3275e7479760551a36496b3e58b5d3a0c9a77d2a Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Mon, 27 Dec 2021 11:38:28 +0800 Subject: [PATCH] add beget control api Signed-off-by: xionglei6 --- interfaces/innerkits/BUILD.gn | 26 ++- .../innerkits/begetctl_utils/begetctl_utils.c | 196 ++++++++++++++++++ .../begetctl_watcher/begetctl_watcher.c | 42 ++++ .../dynamic_service/dynamic_service.c | 52 ----- interfaces/innerkits/include/begetctl_utils.h | 42 ++++ .../{dynamic_service.h => begetctl_watcher.h} | 70 +++---- ohos.build | 15 +- services/init/include/init_service.h | 3 +- services/init/init_service_manager.c | 27 ++- 9 files changed, 378 insertions(+), 95 deletions(-) create mode 100755 interfaces/innerkits/begetctl_utils/begetctl_utils.c create mode 100755 interfaces/innerkits/begetctl_watcher/begetctl_watcher.c delete mode 100755 interfaces/innerkits/dynamic_service/dynamic_service.c create mode 100755 interfaces/innerkits/include/begetctl_utils.h rename interfaces/innerkits/include/{dynamic_service.h => begetctl_watcher.h} (74%) diff --git a/interfaces/innerkits/BUILD.gn b/interfaces/innerkits/BUILD.gn index e843d918..45a113b4 100755 --- a/interfaces/innerkits/BUILD.gn +++ b/interfaces/innerkits/BUILD.gn @@ -30,6 +30,7 @@ ohos_shared_library("libbegetutil") { "file/init_file.c", "reboot/init_reboot_innerkits.c", "socket/init_socket.c", + "begetctl_utils/begetctl_utils.c", ] sources += fs_manager_sources @@ -39,7 +40,6 @@ ohos_shared_library("libbegetutil") { "//third_party/bounds_checking_function/include", "//base/startup/init_lite/services/include", "//base/startup/init_lite/services/include/param", - "//base/startup/syspara_lite/hals/parameter/include", ] deps = [ "//base/startup/init_lite/services/log:init_log", @@ -49,8 +49,32 @@ ohos_shared_library("libbegetutil") { "//third_party/openssl:libcrypto_static", "//utils/native/base:utils", ] + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + public_configs = [ ":exported_header_files" ] + part_name = "init" + install_images = [ + "system", + "updater", + ] +} + +# watcher lib must separate compilation avoid interdependence. +ohos_shared_library("libbegetctl_watcher") { + sources = [ "begetctl_watcher/begetctl_watcher.c" ] + + include_dirs = [ + "//base/startup/init_lite/services/include", + "//base/startup/init_lite/services/include/param", + "//third_party/bounds_checking_function/include", + ] + deps = [ + "//base/startup/init_lite/services/param/watcher:param_watcheragent", + "//base/startup/init_lite/services/utils:libinit_utils", + "//third_party/bounds_checking_function:libsec_shared", + ] public_configs = [ ":exported_header_files" ] + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] part_name = "init" install_images = [ "system", diff --git a/interfaces/innerkits/begetctl_utils/begetctl_utils.c b/interfaces/innerkits/begetctl_utils/begetctl_utils.c new file mode 100755 index 00000000..0d504c6b --- /dev/null +++ b/interfaces/innerkits/begetctl_utils/begetctl_utils.c @@ -0,0 +1,196 @@ +/* +* Copyright (c) 2021 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "begetctl_utils.h" + +#include +#include +#include +#include + +#include "hilog/log.h" +#include "init_utils.h" +#include "securec.h" +#include "sys_param.h" + +static int StartDynamicProcess(const char *name, const char *extArgv[], int extArgc) +{ + if (name == NULL) { + HILOG_ERROR(LOG_CORE, "Start dynamic service failed, service name is null."); + return -1; + } + int extraArg = 0; + if ((extArgv != NULL) && (extArgc > 0)) { + HILOG_INFO(LOG_CORE, "Start service by extra args"); + extraArg = 1; + } + if (extraArg == 1) { + unsigned int len = 0; + for (int i = 0; i < extArgc; i++) { + len += strlen(extArgv[i]); + } + len += strlen(name) + extArgc + 1; + char *nameValue = (char *)calloc(len, sizeof(char)); + if (nameValue == NULL) { + HILOG_ERROR(LOG_CORE, "Failed calloc err=%{public}d", errno); + return -1; + } + if (strncat_s(nameValue, len, name, strlen(name)) != 0) { + HILOG_ERROR(LOG_CORE, "Failed strncat_s name err=%{public}d", errno); + return -1; + } + for (int j = 0; j < extArgc; j++) { + if (strncat_s(nameValue, len, "|", 1) != 0) { + HILOG_ERROR(LOG_CORE, "Failed strncat_s \"|\"err=%{public}d", errno); + return -1; + } + if (strncat_s(nameValue, len, extArgv[j], strlen(extArgv[j])) != 0) { + HILOG_ERROR(LOG_CORE, "Failed strncat_s err=%{public}d", errno); + return -1; + } + } + HILOG_INFO(LOG_CORE,"nameValue is %{public}s", nameValue); + if (SystemSetParameter("ohos.ctl.start", nameValue) != 0) { + HILOG_ERROR(LOG_CORE, "Set param for %{public}s failed.\n", nameValue); + free(nameValue); + return -1; + } + free(nameValue); + } else { + if (SystemSetParameter("ohos.ctl.start", name) != 0) { + HILOG_ERROR(LOG_CORE, "Set param for %{public}s failed.\n", name); + return -1; + } + } + return 0; +} + +static int StopDynamicProcess(const char *serviceName) +{ + if (serviceName == NULL) { + HILOG_ERROR(LOG_CORE, "Stop dynamic service failed, service is null.\n"); + return -1; + } + if (SystemSetParameter("ohos.ctl.stop", serviceName) != 0) { + HILOG_ERROR(LOG_CORE, "Set param for %{public}s failed.\n", serviceName); + return -1; + } + return 0; +} + +static int GetCurrentServiceStatus(const char *serviceName, char *paramValue, unsigned int valueLen) +{ + char paramName[PARAM_NAME_LEN_MAX] = {0}; + if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.svc.%s", serviceName) == -1) { + HILOG_ERROR(LOG_CORE, "Failed snprintf_s err=%{public}d", errno); + return -1; + } + if (SystemGetParameter(paramName, paramValue, &valueLen) != 0) { + HILOG_ERROR(LOG_CORE, "Failed get paramName."); + return -1; + } + return 0; +} + +static int RestartDynamicProcess(const char *serviceName, const char *extArgv[], int extArgc) +{ + if (serviceName == NULL) { + HILOG_ERROR(LOG_CORE, "Restart dynamic service failed, service is null.\n"); + return -1; + } + char paramValue[PARAM_VALUE_LEN_MAX] = {0}; + unsigned int valueLen = PARAM_VALUE_LEN_MAX; + if (GetCurrentServiceStatus(serviceName, paramValue, valueLen) != 0) { + HILOG_ERROR(LOG_CORE, "Get service status failed.\n"); + return -1; + } + if (strcmp(paramValue, "running") == 0) { + if (StopDynamicProcess(serviceName) != 0) { + HILOG_ERROR(LOG_CORE, "Stop service %{public}s failed", serviceName); + return -1; + } + if (ServiceWaitForStatus(serviceName, "stopped", DEFAULT_PARAM_WAIT_TIMEOUT) != 0) { + HILOG_ERROR(LOG_CORE, "Failed wait service %{public}s stopped", serviceName); + return -1; + } + if (StartDynamicProcess(serviceName, extArgv, extArgc) != 0) { + HILOG_ERROR(LOG_CORE, "Start service %{public}s failed", serviceName); + return -1; + } + } else if (strcmp(paramValue, "stopped") == 0) { + if (StartDynamicProcess(serviceName, extArgv, extArgc) != 0) { + HILOG_ERROR(LOG_CORE, "Start service %{public}s failed", serviceName); + return -1; + } + } else { + HILOG_ERROR(LOG_CORE, "Current service status: %{public}s is not support.", paramValue); + } + return 0; +} + +int ServiceControlWithExtra(const char *serviceName, int action, const char *extArgv[], int extArgc) +{ + if (serviceName == NULL) { + HILOG_ERROR(LOG_CORE, "Service wait failed, service is null.\n"); + return -1; + } + int ret = 0; + switch (action) { + case START: + ret = StartDynamicProcess(serviceName, extArgv, extArgc); + break; + case STOP: + ret = StopDynamicProcess(serviceName); + break; + case RESTART: + ret = RestartDynamicProcess(serviceName, extArgv, extArgc); + break; + default: + HILOG_ERROR(LOG_CORE, "Set service %{public}s action %d error", serviceName, action); + ret = -1; + break; + } + return ret; +} + +int ServiceControl(const char *serviceName, int action) +{ + if (serviceName == 0) { + HILOG_ERROR(LOG_CORE, "Service getctl failed, service is null.\n"); + return -1; + } + int ret = ServiceControlWithExtra(serviceName, action, NULL, 0); + return ret; +} + +// Service status can set "running", "stopping", "stopped", "reseting". waitTimeout(s). +int ServiceWaitForStatus(const char *serviceName, const char *status, int waitTimeout) +{ + if (serviceName == NULL) { + HILOG_ERROR(LOG_CORE, "Service wait failed, service is null.\n"); + return -1; + } + char paramName[PARAM_NAME_LEN_MAX] = {0}; + if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.svc.%s", serviceName) == -1) { + HILOG_ERROR(LOG_CORE, "Failed snprintf_s err=%{public}d", errno); + return -1; + } + if (SystemWaitParameter(paramName, status, waitTimeout) != 0) { + HILOG_ERROR(LOG_CORE, "Wait param for %{public}s failed.\n", paramName); + return -1; + } + HILOG_INFO(LOG_CORE, "Success wait"); + return 0; +} diff --git a/interfaces/innerkits/begetctl_watcher/begetctl_watcher.c b/interfaces/innerkits/begetctl_watcher/begetctl_watcher.c new file mode 100755 index 00000000..cefd5892 --- /dev/null +++ b/interfaces/innerkits/begetctl_watcher/begetctl_watcher.c @@ -0,0 +1,42 @@ +/* +* Copyright (c) 2021 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include "begetctl_watcher.h" + +#include +#include +#include +#include + +#include "hilog/log.h" +#include "init_utils.h" +#include "securec.h" + +int ServiceWatchForStatus(const char *serviceName, void *context, ServiceStatusChangePtr changeCallback) +{ + if (serviceName == NULL) { + HILOG_ERROR(LOG_CORE, "Service wait failed, service is null.\n"); + return -1; + } + char paramName[PARAM_NAME_LEN_MAX] = {0}; + if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.svc.%s", serviceName) == -1) { + HILOG_ERROR(LOG_CORE, "Failed snprintf_s err=%{public}d", errno); + return -1; + } + if (SystemWatchParameter(paramName, changeCallback, context) != 0) { + HILOG_ERROR(LOG_CORE, "Wait param for %{public}s failed.\n", paramName); + return -1; + } + return 0; +} diff --git a/interfaces/innerkits/dynamic_service/dynamic_service.c b/interfaces/innerkits/dynamic_service/dynamic_service.c deleted file mode 100755 index db4a8c02..00000000 --- a/interfaces/innerkits/dynamic_service/dynamic_service.c +++ /dev/null @@ -1,52 +0,0 @@ -/* -* Copyright (c) 2021 Huawei Device Co., Ltd. -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#include "dynamic_service.h" - -#include -#include "hilog/log.h" -#include "parameter.h" - -#undef LOG_TAG -#undef LOG_DOMAIN -#define LOG_TAG "Init" -#define LOG_DOMAIN 0xD000719 - -int32_t StartDynamicProcess(const char *name) -{ - if (name == NULL) { - HILOG_ERROR(LOG_CORE, "Start dynamic service failed, service name is null."); - return -1; - } - if (SetParameter("ohos.ctl.start", name) != 0) { - HILOG_ERROR(LOG_CORE, "Set param for %{public}s failed.\n", name); - return -1; - } - return 0; -} - -int32_t StopDynamicProcess(const char *name) -{ - if (name == NULL) { - HILOG_ERROR(LOG_CORE, "Stop dynamic service failed, service is null.\n"); - return -1; - } - if (SetParameter("ohos.ctl.stop", name) != 0) { - HILOG_ERROR(LOG_CORE, "Set param for %{public}s failed.\n", name); - return -1; - } - return 0; -} - diff --git a/interfaces/innerkits/include/begetctl_utils.h b/interfaces/innerkits/include/begetctl_utils.h new file mode 100755 index 00000000..23796fd7 --- /dev/null +++ b/interfaces/innerkits/include/begetctl_utils.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BEGET_UTILS_API_H +#define BEGET_UTILS_API_H + +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +enum ServiceAction { + START = 0, + STOP = 1, + RESTART = 2, +}; + +int ServiceControlWithExtra(const char *serviceName, int action, const char *extArgv[], int extArgc); +int ServiceControl(const char *serviceName, int action); +int ServiceWaitForStatus(const char *serviceName, const char *status, int waitTimeout); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/interfaces/innerkits/include/dynamic_service.h b/interfaces/innerkits/include/begetctl_watcher.h similarity index 74% rename from interfaces/innerkits/include/dynamic_service.h rename to interfaces/innerkits/include/begetctl_watcher.h index 61bf8bf8..1cb2c30e 100755 --- a/interfaces/innerkits/include/dynamic_service.h +++ b/interfaces/innerkits/include/begetctl_watcher.h @@ -1,36 +1,34 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef DYNAMIC_SERVICE_API_H -#define DYNAMIC_SERVICE_API_H - -#include - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif -#endif - -int32_t StartDynamicProcess(const char *name); -int32_t StopDynamicProcess(const char *name); - -#ifdef __cplusplus -#if __cplusplus -} -#endif -#endif - -#endif // DYNAMIC_SERVICE_API_H \ No newline at end of file +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SERVICE_WATCH_API_H +#define SERVICE_WATCH_API_H + +#include "sys_param.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif +typedef ParameterChangePtr ServiceStatusChangePtr; +int ServiceWatchForStatus(const char *serviceName, void *context, ServiceStatusChangePtr changeCallback); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif diff --git a/ohos.build b/ohos.build index 673b8de0..41ec5650 100755 --- a/ohos.build +++ b/ohos.build @@ -8,22 +8,29 @@ "//base/startup/init_lite/watchdog:watchdog", "//base/startup/init_lite/services/begetctl:begetctl", "//base/startup/init_lite/interfaces/innerkits:libbegetutil", - "//base/startup/init_lite/interfaces/innerkits/file:libfile", - "//base/startup/init_lite/interfaces/innerkits/socket:libsocket" + "//base/startup/init_lite/interfaces/innerkits:libbegetctl_watcher" ], "inner_kits": [{ "header": { "header_files": [ "init_socket.h", - "dynamic_service.h", "init_file.h", "fs_manager/fs_manager_log.h", "fs_manager/fs_manager.h", - "init_reboot.h" + "init_reboot.h", + "begetctl_utils.h" ], "header_base": "//base/startup/init_lite/interfaces/innerkits/include/" }, "name": "//base/startup/init_lite/interfaces/innerkits:libbegetutil" + }, { + "header": { + "header_files": [ + "begetctl_watcher.h" + ], + "header_base": "//base/startup/init_lite/interfaces/innerkits/include/" + }, + "name": "//base/startup/init_lite/interfaces/innerkits:libbegetctl_watcher" } ], "test_list": [ diff --git a/services/init/include/init_service.h b/services/init/include/init_service.h index 48059cfa..54eb6a8f 100755 --- a/services/init/include/init_service.h +++ b/services/init/include/init_service.h @@ -83,6 +83,7 @@ typedef struct { int importance; Perms servPerm; ServiceArgs pathArgs; + ServiceArgs extraArgs; ServiceArgs writePidArgs; CmdLines *restartArg; ServiceSocket *socketCfg; @@ -98,7 +99,7 @@ void NotifyServiceChange(const char *serviceName, const char *change); int IsForbidden(const char *fieldStr); int SetImportantValue(Service *curServ, const char *attrName, int value, int flag); int GetServiceCaps(const cJSON *curArrItem, Service *curServ); -int ServiceExec(const Service *service); +int ServiceExec(Service *service); #ifdef __cplusplus #if __cplusplus diff --git a/services/init/init_service_manager.c b/services/init/init_service_manager.c index 295ae08b..097f996f 100755 --- a/services/init/init_service_manager.c +++ b/services/init/init_service_manager.c @@ -617,6 +617,7 @@ void StartServiceByName(const char *servName, bool checkDynamic) if (checkDynamic && (service->attribute & SERVICE_ATTR_DYNAMIC)) { INIT_LOGI("%s is dynamic service.", servName); + NotifyServiceChange(servName, "stopped"); return; } if (ServiceStart(service) != SERVICE_SUCCESS) { @@ -663,6 +664,25 @@ Service *GetServiceByPid(pid_t pid) return NULL; } +static int SetServiceExtraArgs(Service *service, const char *fullServName) +{ + INIT_ERROR_CHECK(service != NULL && fullServName != NULL, return -1, "Failed get parameters"); + int returnCount = 0; + char *tmpServName = strdup(fullServName); + char **extArgv = SplitStringExt(tmpServName, "|", &returnCount, MAX_PATH_ARGS_CNT); + free(tmpServName); + INIT_ERROR_CHECK(extArgv != NULL && returnCount > 0, return -1, "Split servName: %s failed", fullServName); + service->extraArgs.count = returnCount - 1; + service->extraArgs.argv = (char **)calloc(service->extraArgs.count, sizeof(char *)); + INIT_ERROR_CHECK(service->extraArgs.argv != NULL, FreeStringVector(extArgv, returnCount); return -1, + "Failed calloc err=%d", errno); + for (int i = 0; i < service->extraArgs.count; i++) { + service->extraArgs.argv[i] = strdup(extArgv[i + 1]); + } + FreeStringVector(extArgv, returnCount); + return 0; +} + Service *GetServiceByName(const char *servName) { INIT_ERROR_CHECK(servName != NULL, return NULL, "Failed get servName"); @@ -670,7 +690,12 @@ Service *GetServiceByName(const char *servName) while (node != &g_serviceSpace.services) { Service *service = ListEntry(node, Service, node); if (service != NULL) { - INIT_CHECK_RETURN_VALUE(strcmp(service->name, servName) != 0, service); + if (strcmp(service->name, servName) == 0) { + return service; + } else if (strncmp(service->name, servName, strlen(service->name)) == 0) { + SetServiceExtraArgs(service, servName); + return service; + } } node = node->next; } -- GitLab