提交 91268807 编写于 作者: O openharmony_ci 提交者: Gitee

!42 适配L2 init

Merge pull request !42 from 钟柠/init0628
......@@ -18,21 +18,32 @@ lite_component("initsync") {
}
shared_library("libinitsync_shared") {
sources = [ "src/init_sync.c" ]
sources = [
"src/init_sync.c",
]
cflags = [ "-Wall" ]
include_dirs = [
"//base/startup/init_lite/initsync/include",
"//base/startup/init_lite/interfaces/kits",
"//base/startup/init_lite/services/log",
]
public_deps = [
"//base/startup/init_lite/services/log:init_log",
"//third_party/bounds_checking_function:libsec_shared",
]
public_deps = [ "//third_party/bounds_checking_function:libsec_shared" ]
}
static_library("libinitsync_static") {
sources = [ "src/init_sync.c" ]
sources = [
"src/init_sync.c",
]
cflags = [ "-Wall" ]
include_dirs = [
"//base/startup/init_lite/initsync/include",
"//base/startup/init_lite/interfaces/kits",
"//base/startup/init_lite/services/log",
]
public_deps = [
"//third_party/bounds_checking_function:libsec_static",
]
public_deps = [ "//third_party/bounds_checking_function:libsec_static" ]
}
......@@ -24,19 +24,19 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "init_log.h"
static int SendCmd(int cmd, unsigned long arg)
{
int fd = open(QUICKSTART_NODE, O_RDONLY);
if (fd != -1) {
int ret = ioctl(fd, cmd, arg);
if (ret == -1) {
printf("[ERR][%s,%d] %s!\n", __FUNCTION__, __LINE__, strerror(errno));
INIT_LOGE("[Init] [ERR] %s!\n", strerror(errno));
}
close(fd);
return ret;
}
printf("[ERR][%s,%d] %s!\n", __FUNCTION__, __LINE__, strerror(errno));
INIT_LOGE("[Init] [ERR] %s!\n", strerror(errno));
return fd;
}
......@@ -56,7 +56,7 @@ int NotifyInit(unsigned long event)
int SystemInitStage(QuickstartStage stage)
{
if (stage >= QS_STAGE_LIMIT || stage < QS_STAGE1) {
printf("[ERR][%s,%d] the stage(%d) is not expected!\n", __FUNCTION__, __LINE__, stage);
INIT_LOGE("[Init] the stage(%d) is not expected!\n", stage);
return -1;
}
return SendCmd(QUICKSTART_STAGE(stage), 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.
*/
#ifndef INIT_REBOOT_API_H
#define INIT_REBOOT_API_H
int DoRebootApi(const char *cmdContent);
#endif
/*
* 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 INIT_SOCKET_API_H
#define INIT_SOCKET_API_H
#define OHOS_SOCKET_DIR "/dev/unix/socket"
#define OHOS_SOCKET_ENV_PREFIX "OHOS_SOCKET_"
// parameter is service name
int GetControlSocket(const char *name);
#endif
\ 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.
import("//build/ohos.gni")
ohos_static_library("libreboot") {
sources = [
"//base/startup/init_lite/interfaces/innerkits/reboot/init_reboot_api.c",
]
include_dirs = [
"//base/startup/init_lite/interfaces/innerkits/include",
"//base/startup/init_lite/services/include/param",
"//third_party/bounds_checking_function/include",
"//base/startup/init_lite/services/log",
]
deps = [
"//base/startup/init_lite/services/log:init_log",
"//base/startup/init_lite/services/param:paramclient",
"//third_party/bounds_checking_function:libsec_static",
]
}
/*
* 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 "init_reboot_api.h"
#include <stdio.h>
#include <string.h>
#include "sys_param.h"
#include "securec.h"
#include "init_log.h"
#define SYS_POWER_CTRL "sys.powerctrl."
#define MAX_REBOOT_NAME_SIZE 100
#define MAX_REBOOT_VAUE_SIZE 500
int DoRebootApi(const char *cmdContent)
{
char name[MAX_REBOOT_VAUE_SIZE];
if (cmdContent == NULL) {
INIT_LOGE("DoReboot api error, cmdContent is NULL.\n");
return -1;
}
int length = strlen(cmdContent);
if (length == 0 || length > MAX_REBOOT_VAUE_SIZE) {
INIT_LOGE("DoReboot api error, cmdContent = %s, length = %d.\n", cmdContent, length);
return -1;
}
if (snprintf_s(name, MAX_REBOOT_NAME_SIZE, MAX_REBOOT_NAME_SIZE - 1, "%s%s", SYS_POWER_CTRL, "reboot") < 0) {
INIT_LOGE("DoReboot api error, MAX_REBOOT_NAME_SIZE is not enough\n");
return -1;
}
if (SystemSetParameter(name, cmdContent) != 0) {
INIT_LOGE("DoRebootApi SystemSetParameter error\n");
return -1;
}
return 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.
import("//build/ohos.gni")
ohos_static_library("libsocket") {
sources = [
"//base/startup/init_lite/interfaces/innerkits/socket/init_socket_api.c",
]
include_dirs = [ "//base/startup/init_lite/interfaces/innerkits/include" ]
deps = []
}
/*
* 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 "init_socket_api.h"
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <sys/un.h>
#define N_DEC 10
#define MAX_SOCKET_ENV_PREFIX_LEN 64
#define MAX_SOCKET_DIR_LEN 128
static int GetControlFromEnv(char *path)
{
if (path == NULL) {
return -1;
}
INIT_LOGI("GetControlFromEnv path is %s \n", path);
const char *val = getenv(path);
if (val == NULL) {
INIT_LOGE("GetControlFromEnv val is null %d\n", errno);
return -1;
}
errno = 0;
int fd = strtol(val, NULL, N_DEC);
if (errno) {
return -1;
}
INIT_LOGI("GetControlFromEnv fd is %d \n", fd);
if (fcntl(fd, F_GETFD) < 0) {
INIT_LOGE("GetControlFromEnv errno %d \n", errno);
return -1;
}
return fd;
}
int GetControlSocket(const char *name)
{
if (name == NULL) {
return -1;
}
char path[MAX_SOCKET_ENV_PREFIX_LEN] = {0};
snprintf(path, sizeof(path), OHOS_SOCKET_ENV_PREFIX"%s", name);
INIT_LOGI("GetControlSocket path is %s \n", path);
int fd = GetControlFromEnv(path);
if (fd < 0) {
INIT_LOGE("GetControlFromEnv fail \n");
return -1;
}
struct sockaddr_un addr;
socklen_t addrlen = sizeof(addr);
int ret = getsockname(fd, (struct sockaddr*)&addr, &addrlen);
if (ret < 0) {
INIT_LOGE("GetControlSocket errno %d \n", errno);
return -1;
}
char sockDir[MAX_SOCKET_DIR_LEN] = {0};
snprintf(sockDir, sizeof(sockDir), OHOS_SOCKET_DIR"/%s", name);
INIT_LOGI("sockDir %s \n", sockDir);
INIT_LOGI("addr.sun_path %s \n", addr.sun_path);
if (strncmp(sockDir, addr.sun_path, strlen(sockDir)) == 0) {
return fd;
}
return -1;
}
{
"subsystem": "startup",
"parts": {
"init": {
"module_list": [
"//base/startup/init_lite/services:startup_init"
]
}
}
}
......@@ -20,17 +20,24 @@ if (defined(ohos_lite)) {
]
sources = [
"src/init_adapter.c",
"src/init_capability.c",
"src/init_cmds.c",
"src/init_import.c",
"src/init_jobs.c",
"src/init_read_cfg.c",
"src/init_reboot.c",
"src/init_service.c",
"src/init_service_manager.c",
"src/init_service_socket.c",
"src/init_signal_handler.c",
"src/init_utils.c",
"src/main.c",
]
include_dirs = [
"include",
"//base/startup/init_lite/services/include",
"//base/startup/init_lite/services/param/include",
"//base/startup/init_lite/services/log",
"//third_party/cJSON",
"//third_party/bounds_checking_function/include",
"//base/startup/syspara_lite/interfaces/kits",
......@@ -39,8 +46,9 @@ if (defined(ohos_lite)) {
cflags = [ "-Wall" ]
deps = [
"//base/startup/syspara_lite/frameworks/parameter:parameter",
"//base/startup/init_lite/initsync:initsync",
"//base/startup/init_lite/services/log:init_log",
"//base/startup/syspara_lite/frameworks/parameter:parameter",
"//build/lite/config/component/cJSON:cjson_shared",
"//third_party/bounds_checking_function:libsec_shared",
]
......@@ -74,7 +82,6 @@ if (defined(ohos_lite)) {
}
} else {
import("//build/ohos.gni")
ohos_executable("updaterueventd") {
sources = [
"src/list.c",
......@@ -83,40 +90,72 @@ if (defined(ohos_lite)) {
include_dirs = [
"include",
"//third_party/bounds_checking_function/include",
"//base/startup/init_lite/services/log",
]
deps = [
"//base/startup/init_lite/services/log:init_log",
"//third_party/bounds_checking_function:libsec_static",
]
deps = [ "//third_party/bounds_checking_function:libsec_static" ]
install_enable = true
part_name = "updater"
part_name = "init"
}
ohos_executable("updaterinit") {
ohos_executable("init") {
sources = [
"src/device.c",
"src/init_adapter.c",
"src/init_capability.c",
"src/init_cmds.c",
"src/init_import.c",
"src/init_jobs.c",
"src/init_read_cfg.c",
"src/init_reboot.c",
"src/init_service.c",
"src/init_service_manager.c",
"src/init_service_socket.c",
"src/init_signal_handler.c",
"src/init_utils.c",
"src/main.c",
]
include_dirs = [
"include",
"//base/startup/init_lite/services/include/param",
"//base/startup/init_lite/services/include",
"//base/startup/init_lite/services/log",
"//third_party/cJSON",
"//third_party/bounds_checking_function/include",
"//third_party/libuv/include",
]
deps = [
"//base/startup/init_lite/services/log:init_log",
"//base/startup/init_lite/services/param:paramservice",
"//third_party/bounds_checking_function:libsec_static",
"//third_party/cJSON:cjson_static",
]
if (use_musl) {
deps += [
"//third_party/mksh:sh",
"//third_party/toybox:toybox",
]
}
install_enable = true
part_name = "updater"
part_name = "init"
}
ohos_prebuilt_etc("init.cfg") {
source = "//device/hisilicon/hi3516dv300/updater/init.cfg"
relative_install_dir = "init"
subsystem_name = "updater"
part_name = "init"
}
group("startup_init") {
deps = [
":init",
":init.cfg",
":updaterueventd",
"//base/startup/init_lite/services/param:getparam",
"//base/startup/init_lite/services/param:paramclient",
"//base/startup/init_lite/services/param:paramservice",
"//base/startup/init_lite/services/param:setparam",
"//base/startup/init_lite/services/reboot:reboot",
]
}
}
......@@ -21,9 +21,11 @@
extern "C" {
#endif
#endif
#include <sys/types.h>
void MountBasicFs();
void CreateDeviceNode();
int MakeSocketDir(const char *path, mode_t mode);
#ifdef __cplusplus
#if __cplusplus
......
......@@ -16,10 +16,10 @@
#ifndef BASE_STARTUP_INITLITE_ADAPTER_H
#define BASE_STARTUP_INITLITE_ADAPTER_H
#ifdef __LINUX__
#include <linux/capability.h>
#else
#if defined OHOS_LITE && !defined __LINUX__
#include <sys/capability.h>
#else
#include <linux/capability.h>
#endif
#ifdef __cplusplus
......@@ -28,7 +28,7 @@ extern "C" {
#endif
#endif
#ifdef __LINUX__
#ifndef OHOS_LITE
/* Control the ambient capability set */
#ifndef PR_CAP_AMBIENT
#define PR_CAP_AMBIENT 47
......
/*
* 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 INIT_CAPABILITY_H
#define INIT_CAPABILITY_H
#include "cJSON.h"
#include "init_service.h"
int GetServiceCaps(const cJSON* curArrItem, Service* curServ);
#endif
......@@ -22,10 +22,11 @@ extern "C" {
#endif
#endif
#define MAX_CMD_NAME_LEN 10
#define MAX_CMD_CONTENT_LEN 128
#define MAX_CMD_CNT_IN_ONE_JOB 30
#define MAX_CMD_NAME_LEN 32
#define MAX_CMD_CONTENT_LEN 256
#define MAX_CMD_CNT_IN_ONE_JOB 200
#define MAX_COPY_BUF_SIZE 256
#define DEFAULT_COPY_ARGS_CNT 2
// one cmd line
typedef struct {
char name[MAX_CMD_NAME_LEN + 1];
......@@ -35,6 +36,8 @@ typedef struct {
void ParseCmdLine(const char* cmdStr, CmdLine* resCmd);
void DoCmd(const CmdLine* curCmd);
void DoCmdByName(const char *name, const char *cmdContent);
const char *GetMatchCmd(const char *cmdStr);
#ifdef __cplusplus
#if __cplusplus
}
......
/*
* 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 BASE_STARTUP_INITLITE_IMPORT_H
#define BASE_STARTUP_INITLITE_IMPORT_H
#include "cJSON.h"
void ParseAllImports(cJSON *root);
#endif
\ No newline at end of file
......@@ -25,7 +25,7 @@ extern "C" {
#endif
#endif
#define MAX_JOB_NAME_LEN 32
#define MAX_JOB_NAME_LEN 64
// one job, could have many cmd lines
typedef struct {
......@@ -37,7 +37,7 @@ typedef struct {
void ParseAllJobs(const cJSON* fileRoot);
void DoJob(const char* jobName);
void ReleaseAllJobs();
void DumpAllJobs();
#ifdef __cplusplus
#if __cplusplus
}
......
文件模式从 100755 更改为 100644
......@@ -21,10 +21,16 @@
extern "C" {
#endif
#endif
#ifndef OHOS_LITE
#define INIT_CONFIGURATION_FILE "/init.cfg"
#else
#define INIT_CONFIGURATION_FILE "/etc/init.cfg"
#endif
#define MAX_PATH_ARGS_CNT 20
#define MAX_ONE_ARG_LEN 200 // max length of one param/path
void InitReadCfg();
void ParseInitCfg(const char *configFile);
#ifdef __cplusplus
#if __cplusplus
......
/*
* Copyright (c) 2020 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 INIT_REBOOT_H
#define INIT_REBOOT_H
void DoReboot(const char *value);
#endif
......@@ -17,6 +17,8 @@
#define BASE_STARTUP_INITLITE_SERVICE_H
#include <sys/types.h>
#include "init_cmds.h"
#include "init_service_socket.h"
#ifdef __cplusplus
#if __cplusplus
......@@ -34,8 +36,11 @@ extern "C" {
#define SERVICE_ATTR_NEED_RESTART 0x004 // will restart in the near future
#define SERVICE_ATTR_NEED_STOP 0x008 // will stop in reap
#define SERVICE_ATTR_IMPORTANT 0x010 // will reboot if it crash
#define SERVICE_ATTR_CRITICAL 0x020 // critical, will reboot if it crash 4 times in 4 minutes
#define SERVICE_ATTR_DISABLED 0x040 // disabled
#define MAX_SERVICE_NAME 32
#define MAX_WRITEPID_FILES 100
#define CAP_NUM 2
......@@ -43,12 +48,17 @@ extern "C" {
typedef struct {
uid_t uID;
gid_t *gIDs;
unsigned int gidsCnt;
gid_t *gIDArray;
int gIDCnt;
unsigned int *caps;
unsigned int capsCnt;
} Perms;
struct OnRestartCmd {
CmdLine *cmdLine;
int cmdNum;
};
typedef struct {
char name[MAX_SERVICE_NAME + 1];
char** pathArgs;
......@@ -56,8 +66,13 @@ typedef struct {
int pid;
int crashCnt;
time_t firstCrashTime;
int criticalCrashCnt; // count for critical
time_t firstCriticalCrashTime; // record for critical
char *writepidFiles[MAX_WRITEPID_FILES];
unsigned int attribute;
Perms servPerm;
struct OnRestartCmd *onRestart;
struct ServiceSocket *socketCfg;
} Service;
int ServiceStart(Service *service);
......
......@@ -17,6 +17,7 @@
#define BASE_STARTUP_INITLITE_SERVICEMANAGER_H
#include "init_service.h"
#include "cJSON.h"
#ifdef __cplusplus
#if __cplusplus
......@@ -24,10 +25,24 @@ extern "C" {
#endif
#endif
#define UID_STR_IN_CFG "uid"
#define GID_STR_IN_CFG "gid"
#define ONCE_STR_IN_CFG "once"
#define IMPORTANT_STR_IN_CFG "importance"
#define BIN_SH_NOT_ALLOWED "/bin/sh"
#define CRITICAL_STR_IN_CFG "critical"
#define DISABLED_STR_IN_CFG "disabled"
#define MAX_SERVICES_CNT_IN_FILE 100
void RegisterServices(Service* services, int servicesCnt);
void StartServiceByName(const char* serviceName);
void StopServiceByName(const char* serviceName);
void StopAllServices();
void StopAllServicesBeforeReboot();
void ReapServiceByPID(int pid);
void ParseAllServices(const cJSON* fileRoot);
void DumpAllServices();
#ifdef __cplusplus
#if __cplusplus
......
/*
* 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 INIT_SERVICE_SOCKET_
#define INIT_SERVICE_SOCKET_
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
struct ServiceSocket;
struct ServiceSocket
{
char *name; // service name
int type; // socket type
uid_t uid; // uid
gid_t gid; // gid
bool passcred; // setsocketopt
mode_t perm; // Setting permissions
struct ServiceSocket *next;
};
int DoCreateSocket(struct ServiceSocket *sockopt);
#endif
/*
* 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 INIT_UTILS_H
#define INIT_UTILS_H
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
struct CmdArgs {
int argc;
char **argv;
};
struct CmdArgs* GetCmd(const char *cmdContent, const char *delim);
void FreeCmd(struct CmdArgs **cmd);
int DecodeUid(const char *name);
void CheckAndCreateDir(const char *fileName);
char* ReadFileToBuf(const char *configFile);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // INIT_UTILS_H
/*
* Copyright (c) 2020 Huawei Device Co., Ltd.
* 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
* 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,
......@@ -22,10 +22,13 @@ extern "C" {
#endif
#endif
struct ListNode {
typedef struct ListNode {
struct ListNode *next;
struct ListNode *prev;
};
} ListNode;
#define ListEmpty(node) ((node).next == &(node) && (node).prev == &(node))
#define ListEntry(ptr, type, member) (type *)((char *)(ptr) - offsetof(type, member))
void ListInit(struct ListNode *list);
void ListAddTail(struct ListNode *list, struct ListNode *item);
......
/*
* Copyright (c) 2020 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 BASE_STARTUP_INIT_PARAM_H
#define BASE_STARTUP_INIT_PARAM_H
#include <stdio.h>
#include "cJSON.h"
#include "sys_param.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef enum {
EVENT_PROPERTY, // 参数修改事件
EVENT_BOOT
} EventType;
/**
* Init 接口
* 初始化参数服务
*
*/
void InitParamService();
/**
* 对Init接口
* 启动trigger服务。
*
*/
void StartTriggerService();
/**
* Init 接口
* 启动参数服务,在main启动的最后调用,阻赛当前线程
*
*/
int StartParamService();
/**
* Init 接口
* 停止参数服务
*
*/
void StopParamService();
/**
* Init 接口
* 加载默认的参数值
*
*/
int LoadDefaultParams(const char *fileName);
/**
* Init 接口
* 安全使用,加载参数的信息,包括selinux label 等
*
*/
int LoadParamInfos(const char *fileName);
/**
* Init 接口
* 加载默认参数。
*
*/
int LoadPersistParams();
/**
* Init 接口
* 设置参数,主要用于其他进程使用,通过管道修改参数
*
*/
int SystemWriteParam(const char *name, const char *value);
/**
* Init 接口
* 查询参数。
*
*/
int SystemReadParam(const char *name, char *value, unsigned int *len);
/**
* 对Init接口
* 触发一个trigger操作。
*
*/
void PostTrigger(EventType type, void *content, u_int32_t contentLen);
/**
* 对Init接口
* 触发一个参数trigger操作。
*
*/
void PostParamTrigger(const char *name, const char *value);
/**
* 对Init接口
* 解析trigger文件。
*
*/
int ParseTriggerConfig(cJSON *fileRoot);
/**
* 对Init接口
* 按名字执行对应的trigger。
*
*/
void DoTriggerExec(const char *content);
/**
* 对Init接口
* 按名字执行对应的trigger。
*
*/
int SystemTraversalParam(void (*traversalParameter)(ParamHandle handle, void* cookie), void* cookie);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif
\ No newline at end of file
/*
* Copyright (c) 2020 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 BASE_STARTUP_SYS_PARAM_H
#define BASE_STARTUP_SYS_PARAM_H
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#define PARAM_VALUE_LEN_MAX 96
typedef u_int32_t ParamHandle;
typedef struct {
u_int32_t serial;
ParamHandle handle;
char value[PARAM_VALUE_LEN_MAX];
} ParamCacheNode;
typedef const char *(*ParamEvaluatePtr)(u_int32_t cacheCount, ParamCacheNode *node);
typedef struct {
pthread_mutex_t lock;
u_int32_t serial;
u_int32_t cacheCount;
ParamEvaluatePtr evaluate;
ParamCacheNode *cacheNode;
} ParamCache;
/**
* 对外接口
* 设置参数,主要用于其他进程使用,通过管道修改参数。
*
*/
int SystemSetParameter(const char *name, const char *value);
/**
* 对外接口
* 查询参数,主要用于其他进程使用,需要给定足够的内存保存参数。
* 如果 value == null,获取value的长度
* 否则value的大小认为是len
*
*/
int SystemGetParameter(const char *name, char *value, unsigned int *len);
/**
* 外部接口
* 遍历参数。
*
*/
int SystemTraversalParameter(void (*traversalParameter)(ParamHandle handle, void* cookie), void* cookie);
/**
* 外部接口
* 查询参数,主要用于其他进程使用,需要给定足够的内存保存参数。
* 如果 value == null,获取value的长度
* 否则value的大小认为是len
*
*/
int SystemGetParameterName(ParamHandle handle, char *name, unsigned int len);
/**
* 外部接口
* 获取参数值。
*
*/
int SystemGetParameterValue(ParamHandle handle, char *value, unsigned int *len);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif
\ 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.
if (defined(ohos_lite)) {
static_library("init_log") {
sources = [ "init_log.c" ]
public_deps = [ "//third_party/bounds_checking_function:libsec_static" ]
}
} else {
import("//build/ohos.gni")
ohos_static_library("init_log") {
sources = [ "init_log.c" ]
deps = [ "//third_party/bounds_checking_function:libsec_static" ]
part_name = "startup"
subsystem_name = "startup"
}
}
/*
* 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 "init_log.h"
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "securec.h"
#define UNUSED(x) (void)(x)
#define MAX_FORMAT_SIZE 1024
#define MAX_LOG_SIZE 2048
#define BASE_YEAR 1900
static InitLogLevel g_logLevel = INIT_INFO;
static const char *LOG_LEVEL_STR[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" };
void SetLogLevel(InitLogLevel logLevel)
{
g_logLevel = logLevel;
}
void InitLog(const char *tag, InitLogLevel logLevel, const char *fileName, int line, const char *fmt, ...)
{
if (logLevel < g_logLevel) {
return;
}
va_list vargs;
va_start(vargs, fmt);
char tmpFmt[MAX_FORMAT_SIZE];
if (vsnprintf_s(tmpFmt, MAX_FORMAT_SIZE, MAX_FORMAT_SIZE, fmt, vargs) == -1) {
return;
}
time_t logTime;
time(&logTime);
struct tm *t = gmtime(&logTime);
char logInfo[MAX_LOG_SIZE];
if (snprintf_s(logInfo, MAX_LOG_SIZE, MAX_LOG_SIZE, "%s %d-%d-%d %d:%d %s:%d [%s] [pid=%d] %s", tag,
(t->tm_year + BASE_YEAR), (t->tm_mon + 1), t->tm_mday, t->tm_hour, t->tm_min, fileName, line,
LOG_LEVEL_STR[logLevel], getpid(), tmpFmt) == -1) {
return;
}
printf("%s", logInfo );
#if 0
int fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC | O_APPEND );
if (fd < 1) {
printf("xxxxxxxxxxxxxxx open failed. %d\n", errno);
return;
}
if (write(fd, logInfo, strlen(logInfo)) < -1) {
printf("xxxxxxxxxxxxxxx write failed.%d\n", errno);
close(fd);
return;
}
close(fd);
#endif
va_end(vargs);
}
/*
* 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 INIT_LOG_H
#define INIT_LOG_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef enum InitLogLevel {
INIT_DEBUG = 0,
INIT_INFO,
INIT_WARN,
INIT_ERROR,
INIT_FATAL
} InitLogLevel;
#define __FILE_NAME__ (strrchr((__FILE__), '/') ? strrchr((__FILE__), '/') + 1 : (__FILE__))
#ifdef OHOS_LITE
#define INIT_LOGE(format, ...) printf("%s %d: "format, __FILE_NAME__, __LINE__, ##__VA_ARGS__)
#define INIT_LOGW(format, ...) printf("%s %d: "format, __FILE_NAME__, __LINE__, ##__VA_ARGS__)
#define INIT_LOGI(format, ...) printf("%s %d: "format, __FILE_NAME__, __LINE__, ##__VA_ARGS__)
#define INIT_LOGD(format, ...) printf("%s %d: "format, __FILE_NAME__, __LINE__, ##__VA_ARGS__)
#else
#define INIT_LOGD(format, ...) InitLog("[Init]", INIT_DEBUG, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__)
#define INIT_LOGI(format, ...) InitLog("[Init]", INIT_INFO, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__)
#define INIT_LOGW(format, ...) InitLog("[Init]", INIT_WARN, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__)
#define INIT_LOGE(format, ...) InitLog("[Init]", INIT_ERROR, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__)
#define INIT_LOGF(format, ...) InitLog("[Init]", INIT_FATAL, (__FILE_NAME__), (__LINE__), format, ##__VA_ARGS__)
void InitLog(const char *tag, InitLogLevel logLevel, const char *fileName, int line, const char *fmt, ...);
void SetLogLevel(InitLogLevel logLevel);
void Logger(InitLogLevel level, const char *format, ...);
#endif
#define INIT_ERROR_CHECK(ret, statement, format, ...) \
if (!(ret)) { \
INIT_LOGE(format, ##__VA_ARGS__); \
statement; \
}
#define INIT_CHECK_ONLY_RETURN(ret, statement) \
if (!(ret)) { \
statement; \
}
#ifdef SUPPORT_HILOG
#include "hilog/log.h"
static constexpr OHOS::HiviewDFX::HiLogLabel STARTUP_LABEL = {LOG_CORE, 0, "STARTUP"};
InitLogLevel level_;
int JudgeLevel(const InitLogLevel level) { return return; }
#define STARTUP_LOG(LEVEL, LABEL, Level, fmt, ...) \
InitLog("[Init]", LEVEL, __FILE_NAME__, (__LINE__), fmt, ##__VA_ARGS__); \
if (JudgeLevel(InitLogLevel::LEVEL)) \
OHOS::HiviewDFX::HiLog::Level(STARTUP_LABEL, "[%{public}s(%{public}d)] " fmt, \
__FILE_NAME__, __LINE__, ##__VA_ARGS__)
#else
#define STARTUP_LOG(LEVEL, LABEL, Level, fmt, ...) \
printf("[%s:%d][%s:%d] " fmt "\n", LABEL, getpid(), __FILE_NAME__, __LINE__, ##__VA_ARGS__);
#endif
#define STARTUP_LOGI(LABEL, fmt, ...) STARTUP_LOG(INIT_INFO, LABEL, Info, fmt, ##__VA_ARGS__)
#define STARTUP_LOGE(LABEL, fmt, ...) STARTUP_LOG(INIT_ERROR, LABEL, Error, fmt, ##__VA_ARGS__)
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // INIT_LOG_H
# Copyright (c) 2020 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.
import("//build/ohos.gni")
ohos_static_library("paramservice") {
sources = [
"//base/startup/init_lite/services/src/init_utils.c",
"manager/param_cache.c",
"manager/param_manager.c",
"manager/param_trie.c",
"service/param_persist.c",
"service/param_service.c",
"trigger/trigger_checker.c",
"trigger/trigger_manager.c",
"trigger/trigger_processor.c",
]
include_dirs = [
"include",
"//base/startup/init_lite/services/include/param",
"//base/startup/init_lite/services/include",
"//base/startup/init_lite/services/log",
"//third_party/libuv/include",
"//third_party/cJSON",
]
deps = [
"//third_party/bounds_checking_function:libsec_static",
"//third_party/libuv:uv_static",
]
part_name = "init"
subsystem_name = "startup"
}
ohos_static_library("paramclient") {
sources = [
"//base/startup/init_lite/services/src/init_utils.c",
"client/param_request.c",
"manager/param_cache.c",
"manager/param_manager.c",
"manager/param_trie.c",
]
include_dirs = [
"include",
"//base/startup/init_lite/services/include/param",
"//base/startup/init_lite/services/include",
"//base/startup/init_lite/services/log",
"//third_party/libuv/include",
"//third_party/cJSON",
]
deps = [
"//base/startup/init_lite/services/log:init_log",
"//third_party/bounds_checking_function:libsec_static",
"//third_party/libuv:uv_static",
]
part_name = "init"
subsystem_name = "startup"
}
ohos_executable("getparam") {
sources = [ "cmd/param_get.c" ]
include_dirs = [
"include",
"//base/startup/init_lite/services/include/param",
"//base/startup/init_lite/services/include",
"//base/startup/init_lite/services/log",
]
deps = [
"//base/startup/init_lite/services/param:paramclient",
"//third_party/bounds_checking_function:libsec_static",
"//third_party/cJSON:cjson_static",
]
install_enable = true
part_name = "init"
}
ohos_executable("setparam") {
sources = [ "cmd/param_set.c" ]
include_dirs = [
"include",
"//base/startup/init_lite/services/include/param",
"//base/startup/init_lite/services/include",
"//base/startup/init_lite/services/log",
]
deps = [
"//base/startup/init_lite/services/param:paramclient",
"//third_party/bounds_checking_function:libsec_static",
"//third_party/cJSON:cjson_static",
]
install_enable = true
part_name = "init"
}
/*
* 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 "param_request.h"
#include <string.h>
#include <unistd.h>
#include <time.h>
#include "param_manager.h"
#include "uv.h"
#define LABEL "Client"
#define BUFFER_SIZE 200
#define ParamEntry(ptr, type, member) (type *)((char *)(ptr) - offsetof(type, member))
static ParamWorkSpace g_paramWorkSpaceReadOnly = {ATOMIC_VAR_INIT(0), {}, {}, {}};
static void OnWrite(uv_write_t *req, int status)
{
PARAM_LOGI("OnWrite status %d", status);
}
static void OnReceiveAlloc(uv_handle_t* handle, size_t suggestedSize, uv_buf_t* buf)
{
// 这里需要按实际回复大小申请内存,不需要大内存
buf->base = (char *)malloc(sizeof(ResponseMsg));
buf->len = sizeof(ResponseMsg);
PARAM_LOGI("OnReceiveAlloc handle %p %zu", handle, suggestedSize);
}
static void OnReceiveResponse(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
{
RequestNode *req = ParamEntry(handle, RequestNode, handle);
PARAM_LOGI("OnReceiveResponse %p", handle);
if (nread <= 0 || buf == NULL || handle == NULL || buf->base == NULL) {
if (buf != NULL && buf->base != NULL) {
free(buf->base);
}
if (handle != NULL) {
uv_close((uv_handle_t*)handle, NULL);
uv_stop(req->loop);
}
return;
}
ResponseMsg *response = (ResponseMsg *)(buf->base);
PARAM_CHECK(response != NULL, return, "The response is null");
PARAM_LOGI("OnReceiveResponse %p cmd %d result: %d", handle, response->type, response->result);
switch (response->type) {
case SET_PARAM:
req->result = response->result;
break;
default:
PARAM_LOGE("not supported the command: %d", response->type);
break;
}
PARAM_LOGE("Close handle %p", handle);
free(buf->base);
uv_close((uv_handle_t*)handle, NULL);
uv_stop(req->loop);
}
static void OnConnection(uv_connect_t *connect, int status)
{
PARAM_CHECK(status >= 0, return, "Failed to conntect status %s", uv_strerror(status));
RequestNode *request = ParamEntry(connect, RequestNode, connect);
PARAM_LOGI("Connect to server handle %p", &(request->handle));
uv_buf_t buf = uv_buf_init((char*)&request->msg, request->msg.contentSize + sizeof(request->msg));
int ret = uv_write2(&request->wr, (uv_stream_t*)&(request->handle), &buf, 1, (uv_stream_t*)&(request->handle), OnWrite);
PARAM_CHECK(ret >= 0, return, "Failed to uv_write2 porperty");
// read result
ret = uv_read_start((uv_stream_t*)&(request->handle), OnReceiveAlloc, OnReceiveResponse);
PARAM_CHECK(ret >= 0, return, "Failed to uv_read_start response");
}
static int StartRequest(int cmd, RequestNode *request)
{
PARAM_CHECK(request != NULL, return -1, "Invalid request");
request->result = -1;
request->msg.type = cmd;
request->loop = uv_loop_new();
uv_pipe_init(request->loop, &request->handle, 1);
uv_pipe_connect(&request->connect, &request->handle, PIPE_NAME, OnConnection);
uv_run(request->loop, UV_RUN_DEFAULT);
uv_loop_delete(request->loop);
int result = request->result;
free(request);
return result;
}
int SystemSetParameter(const char *name, const char *value)
{
PARAM_CHECK(name != NULL && value != NULL, return -1, "Invalid param");
int ret = CheckParamName(name, 0);
PARAM_CHECK(ret == 0, return ret, "Illegal param name");
PARAM_LOGI("StartRequest %s", name);
u_int32_t msgSize = sizeof(RequestMsg) + strlen(name) + strlen(value) + 2;
RequestNode *request = (RequestNode *)malloc(sizeof(RequestNode) + msgSize);
PARAM_CHECK(request != NULL, return -1, "Failed to malloc for connect");
memset_s(request, sizeof(RequestNode), 0, sizeof(RequestNode));
// 带字符串结束符
int contentSize = BuildParamContent(request->msg.content, msgSize - sizeof(RequestMsg), name, value);
PARAM_CHECK(contentSize > 0, free(request); return -1, "Failed to copy porperty");
request->msg.contentSize = contentSize;
return StartRequest(SET_PARAM, request);
}
int SystemGetParameter(const char *name, char *value, unsigned int *len)
{
PARAM_CHECK(name != NULL && len != NULL, return -1, "The name or value is null");
InitParamWorkSpace(&g_paramWorkSpaceReadOnly, 1, NULL);
ParamHandle handle = 0;
int ret = ReadParamWithCheck(&g_paramWorkSpaceReadOnly, name, &handle);
PARAM_CHECK(ret == 0, return ret, "Can not get param for %s", name);
return ReadParamValue(&g_paramWorkSpaceReadOnly, handle, value, len);
}
int SystemGetParameterName(ParamHandle handle, char *name, unsigned int len)
{
PARAM_CHECK(name != NULL && handle != 0, return -1, "The name is null");
InitParamWorkSpace(&g_paramWorkSpaceReadOnly, 1, NULL);
return ReadParamName(&g_paramWorkSpaceReadOnly, handle, name, len);
}
int SystemGetParameterValue(ParamHandle handle, char *value, unsigned int *len)
{
PARAM_CHECK(len != NULL && handle != 0, return -1, "The value is null");
InitParamWorkSpace(&g_paramWorkSpaceReadOnly, 1, NULL);
return ReadParamValue(&g_paramWorkSpaceReadOnly, handle, value, len);
}
int SystemTraversalParameter(void (*traversalParameter)(ParamHandle handle, void* cookie), void* cookie)
{
PARAM_CHECK(traversalParameter != NULL, return -1, "The param is null");
InitParamWorkSpace(&g_paramWorkSpaceReadOnly, 1, NULL);
return TraversalParam(&g_paramWorkSpaceReadOnly, traversalParameter, cookie);
}
const char *SystemDetectParamChange(ParamCache *cache,
ParamEvaluatePtr evaluate, u_int32_t count, const char *parameters[][2])
{
PARAM_CHECK(cache != NULL && evaluate != NULL && parameters != NULL, return NULL, "The param is null");
return DetectParamChange(&g_paramWorkSpaceReadOnly, cache, evaluate, count, parameters);
}
/*
* 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 <string.h>
#include <stdio.h>
#include "sys_param.h"
#define HELP_PARAM "--help"
#define BUFFER_SIZE 256
static void ProcessParam(ParamHandle handle, void* cookie)
{
SystemGetParameterName(handle, (char*)cookie, BUFFER_SIZE);
u_int32_t size = BUFFER_SIZE;
SystemGetParameterValue(handle, ((char*)cookie) + BUFFER_SIZE, &size);
printf("\t%s = %s \n", (char*)cookie, ((char*)cookie) + BUFFER_SIZE);
}
int main(int argc, char* argv[])
{
if (argc == 1) { // 显示所有的记录
char value[BUFFER_SIZE + BUFFER_SIZE] = {0};
SystemTraversalParameter(ProcessParam, (void*)value);
return 0;
}
if (argc == 2 && strncmp(argv[1], HELP_PARAM, strlen(HELP_PARAM)) == 0) { // 显示帮助
printf("usage: getparam NAME VALUE\n");
return 0;
}
if (argc != 2) {
printf("usage: getparam NAME VALUE\n");
return 0;
}
char value[BUFFER_SIZE] = {0};
u_int32_t size = BUFFER_SIZE;
int ret = SystemGetParameter(argv[1], value, &size);
if (ret == 0) {
printf("getparam %s %s \n", argv[1], value);
} else {
printf("getparam %s %s fail\n", argv[1], value);
}
}
/*
* 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 <string.h>
#include <stdio.h>
#include "sys_param.h"
#define HELP_PARAM "--help"
int main(int argc, char* argv[])
{
if (argc == 1 || argc > 3) {
printf("setparam: Need 2 arguments (see \"setparam --help\")\n");
return 0;
}
if (argc == 2 && strncmp(argv[1], HELP_PARAM, strlen(HELP_PARAM)) == 0) {
printf("usage: setparam NAME VALUE\n");
return 0;
}
int ret = SystemSetParameter(argv[1], argv[2]);
if (ret == 0) {
printf("setparam %s %s success\n", argv[1], argv[2]);
} else {
printf("setparam %s %s fail\n", argv[1], argv[2]);
}
}
/*
* Copyright (c) 2020 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 BASE_STARTUP_PARAM_MANAGER_H
#define BASE_STARTUP_PARAM_MANAGER_H
#include <stdio.h>
#include <string.h>
#include "init_log.h"
#include "sys_param.h"
#include "param_trie.h"
#include "securec.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef enum {
PARAM_CODE_INVALID_PARAM = 100,
PARAM_CODE_INVALID_NAME,
PARAM_CODE_INVALID_VALUE,
PARAM_CODE_REACHED_MAX,
PARAM_CODE_PERMISSION_DENIED,
PARAM_CODE_READ_ONLY_PROPERTY,
PARAM_CODE_NOT_SUPPORT,
PARAM_CODE_ERROR_MAP_FILE,
PARAM_CODE_NOT_FOUND_PROP,
PARAM_CODE_NOT_INIT
} PARAM_CODE;
#define IS_READY_ONLY(name) strncmp((name), "ro.", strlen("ro.")) == 0
#define LABEL_STRING_LEN 128
#ifdef STARTUP_LOCAL
#define PIPE_NAME "/tmp/paramservice"
#define PARAM_STORAGE_PATH "/media/sf_ubuntu/test/__parameters__/param_storage"
#define PARAM_PERSIST_PATH "/media/sf_ubuntu/test/param/persist_parameters"
#define PARAM_INFO_PATH "/media/sf_ubuntu/test/__parameters__/param_info"
#else
#define PIPE_NAME "/dev/unix/socket/paramservice"
#define PARAM_STORAGE_PATH "/dev/__parameters__/param_storage"
#define PARAM_PERSIST_PATH "/data/param/persist_parameters"
#define PARAM_INFO_PATH "/dev/__parameters__/param_info"
#endif
#define SUBSTR_INFO_NAME 0
#define SUBSTR_INFO_LABEL 1
#define SUBSTR_INFO_TYPE 2
#define SUBSTR_INFO_MAX 4
#define WORKSPACE_FLAGS_INIT 0x01
#define WORKSPACE_FLAGS_LOADED 0x02
#define PARAM_LOGI(fmt, ...) STARTUP_LOGI(LABEL, fmt, ##__VA_ARGS__)
#define PARAM_LOGE(fmt, ...) STARTUP_LOGE(LABEL, fmt, ##__VA_ARGS__)
#define PARAM_CHECK(retCode, exper, ...) \
if (!(retCode)) { \
PARAM_LOGE(__VA_ARGS__); \
exper; \
}
#define futex(addr1, op, val, rel, addr2, val3) \
syscall(SYS_futex, addr1, op, val, rel, addr2, val3)
#define futex_wait_always(addr1) \
syscall(SYS_futex, addr1, FUTEX_WAIT, *(int*)(addr1), 0, 0, 0)
#define futex_wake_single(addr1) \
syscall(SYS_futex, addr1, FUTEX_WAKE, 1, 0, 0, 0)
typedef struct UserCred {
pid_t pid;
uid_t uid;
gid_t gid;
} UserCred;
typedef struct {
char label[LABEL_STRING_LEN];
UserCred cred;
} ParamSecurityLabel;
typedef struct ParamAuditData {
const UserCred *cr;
const char *name;
} ParamAuditData;
typedef struct {
atomic_uint_least32_t flags;
WorkSpace paramLabelSpace;
WorkSpace paramSpace;
ParamSecurityLabel label;
} ParamWorkSpace;
typedef struct {
atomic_uint_least32_t flags;
WorkSpace persistWorkSpace;
} ParamPersistWorkSpace;
typedef struct {
char value[128];
} SubStringInfo;
int InitParamWorkSpace(ParamWorkSpace *workSpace, int onlyRead, const char *context);
void CloseParamWorkSpace(ParamWorkSpace *workSpace);
int ReadParamWithCheck(ParamWorkSpace *workSpace, const char *name, ParamHandle *handle);
int ReadParamValue(ParamWorkSpace *workSpace, ParamHandle handle, char *value, u_int32_t *len);
int ReadParamName(ParamWorkSpace *workSpace, ParamHandle handle, char *name, u_int32_t len);
u_int32_t ReadParamSerial(ParamWorkSpace *workSpace, ParamHandle handle);
int AddParam(WorkSpace *workSpace, const char *name, const char *value);
int WriteParam(WorkSpace *workSpace, const char *name, const char *value);
int WriteParamWithCheck(ParamWorkSpace *workSpace,
const ParamSecurityLabel *srcLabel, const char *name, const char *value);
int WriteParamInfo(ParamWorkSpace *workSpace, SubStringInfo *info, int subStrNumber);
int CheckParamValue(WorkSpace *workSpace, const TrieDataNode *node, const char *name, const char *value);
int CheckParamName(const char *name, int paramInfo);
int CanReadParam(ParamWorkSpace *workSpace, u_int32_t labelIndex, const char *name);
int CanWriteParam(ParamWorkSpace *workSpace,
const ParamSecurityLabel *srcLabel, const TrieDataNode *node, const char *name, const char *value);
int CheckMacPerms(ParamWorkSpace *workSpace,
const ParamSecurityLabel *srcLabel, const char *name, u_int32_t labelIndex);
int CheckControlParamPerms(ParamWorkSpace *workSpace,
const ParamSecurityLabel *srcLabel, const char *name, const char *value);
int GetSubStringInfo(const char *buff, u_int32_t buffLen, char delimiter, SubStringInfo *info, int subStrNumber);
int BuildParamContent(char *content, u_int32_t contentSize, const char *name, const char *value);
ParamWorkSpace *GetParamWorkSpace();
typedef void (*TraversalParamPtr)(ParamHandle handle, void* context);
typedef struct {
TraversalParamPtr traversalParamPtr;
void *context;
} ParamTraversalContext;
int TraversalParam(ParamWorkSpace *workSpace, TraversalParamPtr walkFunc, void *cookie);
const char *DetectParamChange(ParamWorkSpace *workSpace, ParamCache *cache,
ParamEvaluatePtr evaluate, u_int32_t count, const char *parameters[][2]);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif
\ No newline at end of file
/*
* Copyright (c) 2020 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 BASE_STARTUP_PARAM_REQUEST_H
#define BASE_STARTUP_PARAM_REQUEST_H
#include <stdio.h>
#include "sys_param.h"
#include "param_manager.h"
#include "uv.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef enum RequestType {
SET_PARAM,
GET_PARAM,
} RequestType;
typedef struct {
ParamSecurityLabel securitylabel;
RequestType type;
int contentSize;
char content[0];
} RequestMsg;
typedef struct {
RequestType type;
int result;
int contentSize;
char content[0];
} ResponseMsg;
typedef struct {
uv_loop_t *loop;
uv_connect_t connect;
uv_pipe_t handle;
uv_write_t wr;
int result;
RequestMsg msg;
} RequestNode;
typedef struct {
uv_write_t writer;
ResponseMsg msg;
} ResponseNode;
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif
\ No newline at end of file
/*
* Copyright (c) 2020 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 BASE_STARTUP_PARAM_SERVICE_H
#define BASE_STARTUP_PARAM_SERVICE_H
#include <stdio.h>
#include "sys_param.h"
#include "param_manager.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
int InitPersistParamWorkSpace(const char *context);
int RefreshPersistParams(ParamWorkSpace *workSpace, const char *context);
void ClosePersistParamWorkSpace();
int WritePersistParam(const char *name, const char *value);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif
\ No newline at end of file
/*
* Copyright (c) 2020 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 BASE_STARTUP_PARAM_TRIE_H
#define BASE_STARTUP_PARAM_TRIE_H
#include <linux/futex.h>
#include <stdatomic.h>
#include <stdio.h>
#include <string.h>
#include <sys/syscall.h>
#include "init_log.h"
#include "sys_param.h"
#include "securec.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#define PARAM_WORKSPACE_MAX 64*1024
#define TRIE_SERIAL_DIRTY_OFFSET 1
#define TRIE_SERIAL_KEY_LEN_OFFSET 24
#define TRIE_SERIAL_DATA_LEN_OFFSET 16
#define FILENAME_LEN_MAX 255
#define TRIE_DATA_LEN_MAX 128
#define NODE_INDEX unsigned int
#define TRIE_NODE_HEADER \
atomic_uint_least32_t serial; \
NODE_INDEX left; \
NODE_INDEX right;
#define DATA_ENTRY_KEY_LEN(entry) (entry)->dataLength >> TRIE_SERIAL_KEY_LEN_OFFSET
#define DATA_ENTRY_DATA_LEN(entry) (((entry)->dataLength >> TRIE_SERIAL_DATA_LEN_OFFSET) & 0x00FF)
#define DATA_ENTRY_DIRTY(serial) ((serial) & 1)
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#define __futex(ftx, op, value, timeout, bitset) \
syscall(__NR_futex, ftx, op, value, timeout, NULL, bitset)
#define futex_wake(ftx, count) __futex(ftx, FUTEX_WAKE, count, NULL, 0)
#define futex_wait(ftx, value, timeout) __futex(ftx, FUTEX_WAIT, value, timeout, 0)
typedef struct {
TRIE_NODE_HEADER;
char key[0];
} TrieNode;
typedef struct {
TRIE_NODE_HEADER;
NODE_INDEX child;
NODE_INDEX labelIndex;
NODE_INDEX dataIndex;
char key[0];
} TrieDataNode;
typedef struct {
atomic_uint_least32_t serial;
atomic_uint_least32_t dataLength;
char data[0];
} DataEntry;
typedef struct {
atomic_uint_least32_t serial;
u_int32_t currOffset;
u_int32_t firstNode;
u_int32_t dataSize;
u_int32_t reserved_[28];
char data[0];
} WorkArea;
struct WorkSpace_;
typedef u_int32_t (*AllocTrieNodePtr)(struct WorkSpace_ *workSpace, const char *key, u_int32_t keyLen);
typedef int (*CompareTrieNodePtr)(TrieNode *node, const char *key2, u_int32_t key2Len);
typedef struct WorkSpace_ {
char fileName[FILENAME_LEN_MAX + 1];
WorkArea *area;
TrieNode *rootNode;
AllocTrieNodePtr allocTrieNode;
CompareTrieNodePtr compareTrieNode;
} WorkSpace;
u_int32_t GetWorkSpaceSerial(WorkSpace *workSpace);
int CompareTrieNode(TrieNode *node, const char *key, u_int32_t keyLen);
u_int32_t AllocateTrieNode(WorkSpace *workSpace, const char *key, u_int32_t keyLen);
int CompareTrieDataNode(TrieNode *node, const char *key, u_int32_t keyLen);
u_int32_t AllocateTrieDataNode(WorkSpace *workSpace, const char *key, u_int32_t keyLen);
u_int32_t GetTrieNodeOffset(WorkSpace *workSpace, const TrieNode *current);
TrieNode *GetTrieNode(WorkSpace *workSpace, NODE_INDEX *index);
u_int32_t GetTrieKeyLen(TrieNode *current);
void SaveIndex(NODE_INDEX *index, u_int32_t offset);
TrieDataNode *AddTrieDataNode(WorkSpace *workSpace, const char *key, u_int32_t keyLen);
TrieDataNode *AddToSubTrie(WorkSpace *workSpace, TrieDataNode *dataNode, const char *key, u_int32_t keyLen);
TrieDataNode *FindSubTrie(WorkSpace *workSpace, TrieDataNode *dataNode, const char *key, u_int32_t keyLen);
TrieDataNode *FindTrieDataNode(WorkSpace *workSpace, const char *key, u_int32_t keyLen, int matchPrefix);
TrieNode *AddTrieNode(WorkSpace *workSpace, TrieNode *root, const char *key, u_int32_t keyLen);
TrieNode *FindTrieNode(WorkSpace *workSpace, TrieNode *tree, const char *key, u_int32_t keyLen);
int InitWorkSpace_(WorkSpace *workSpace, int mode, int prot, u_int32_t spaceSize, int readOnly);
int InitPersistWorkSpace(const char *fileName, WorkSpace *workSpace);
int InitWorkSpace(const char *fileName, WorkSpace *workSpace, int onlyRead);
void CloseWorkSpace(WorkSpace *workSpace);
typedef int (*TraversalTrieNodePtr)(WorkSpace *workSpace, TrieNode *node, void *cookie);
int TraversalTrieNode(WorkSpace *workSpace, TrieNode *root, TraversalTrieNodePtr walkFunc, void *cookie);
int TraversalTrieDataNode(WorkSpace *workSpace, TrieDataNode *current, TraversalTrieNodePtr walkFunc, void *cookie);
u_int32_t AddData(WorkSpace *workSpace, const char *key, u_int32_t keyLen, const char *value, u_int32_t valueLen);
int UpdateDataValue(DataEntry *entry, const char *value);
int GetDataName(const DataEntry *entry, char *name, u_int32_t len);
int GetDataValue(const DataEntry *entry, char *value, u_int32_t len);
u_int32_t GetDataSerial(const DataEntry *entry);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // BASE_STARTUP_PARAM_TRIE_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 STARTUP_TRIGER_CHECKER_H
#define STARTUP_TRIGER_CHECKER_H
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#define SUPPORT_DATA_BUFFER_MAX 128
#define CONDITION_EXTEND_LEN 32
#define LOGIC_DATA_FLAGS_ORIGINAL 0x1
#define LOGIC_DATA_FLAGS_TRUE 0x08
#define LOGIC_DATA_TEST_FLAG(data, flag) (((data)->flags & flag) == (flag))
#define LOGIC_DATA_SET_FLAG(data, flag) (data)->flags |= (flag)
#define LOGIC_DATA_CLEAR_FLAG(data, flag) (data)->flags &= ~(flag)
typedef struct {
u_int32_t flags;
u_int32_t startIndex;
u_int32_t endIndex;
} LogicData;
typedef struct {
int dataNumber;
int endIndex;
int dataUnit;
char *conditionName;
char *conditionContent;
char *inputName;
char *inputContent;
char *readContent;
char *data;
} LogicCalculator;
int CalculatorInit(LogicCalculator *calculator, int dataNumber, int dataUnit, int needCondition);
void CalculatorFree(LogicCalculator *calculator);
int ConvertInfixToPrefix(const char *condition, char *prefix, u_int32_t prefixLen);
int ComputeCondition(LogicCalculator *calculator, const char *condition);
int GetValueFromContent(const char *content, u_int32_t contentSize, u_int32_t start, char *value, u_int32_t valueSize);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // STARTUP_TRIGER_CHECKER_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 STARTUP_TRIGER_MANAGER_H
#define STARTUP_TRIGER_MANAGER_H
#include <pthread.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
#include "init_log.h"
#include "param_manager.h"
#include "securec.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#define TRIGGER_CMD "trigger "
#define TRIGGER_ARR_NAME_IN_JSON "jobs"
#define CMDS_ARR_NAME_IN_JSON "cmds"
#define MAX_TRIGGER_CMD_NAME_LEN 32
#define MAX_TRIGGER_NAME_LEN 64
#define MAX_TRIGGER_TYPE_LEN 16
#define TRIGGER_NODE_IN_QUEUE(trigger) \
(atomic_load_explicit(&(trigger)->serial, memory_order_relaxed) & 0x01)
#define TRIGGER_NODE_SET_QUEUE_FLAG(trigger) \
atomic_store_explicit(&(trigger)->serial, (trigger)->serial | 0x01, memory_order_relaxed)
#define TRIGGER_NODE_CLEAR_QUEUE_FLAG(trigger) \
atomic_store_explicit(&(trigger)->serial, (trigger)->serial & ~0x01, memory_order_relaxed)
typedef enum {
TRIGGER_BOOT = 0,
TRIGGER_PROPERTY,
TRIGGER_UNKNOW,
TRIGGER_MAX
}TriggerType;
// Command对象列表,主要存储每个triger需要执行那些Command操作。
typedef struct CommandNode {
atomic_uint_least32_t next;
char name[MAX_TRIGGER_CMD_NAME_LEN];
char content[0];
} CommandNode;
typedef struct {
atomic_uint_least32_t serial;
atomic_uint_least32_t next;
atomic_uint_least32_t firstCmd;
atomic_uint_least32_t lastCmd;
int type;
char name[MAX_TRIGGER_NAME_LEN];
char condition[0];
} TriggerNode;
typedef struct {
atomic_uint_least32_t serial;
u_int32_t dataSize;
u_int32_t startSize;
u_int32_t currOffset;
char data[0];
} TriggerArea;
typedef struct {
atomic_uint_least32_t firstTrigger;
atomic_uint_least32_t lastTrigger;
} TriggerHeader;
typedef struct {
u_int32_t *executeQueue;
u_int32_t queueCount;
u_int32_t startIndex;
u_int32_t endIndex;
pthread_mutex_t mutex;
} TriggerExecuteQueue;
typedef struct TriggerWorkSpace {
TriggerExecuteQueue executeQueue;
TriggerHeader header[TRIGGER_MAX];
TriggerArea *area;
} TriggerWorkSpace;
int InitTriggerWorkSpace(TriggerWorkSpace *workSpace);
int ParseTrigger(TriggerWorkSpace *workSpace, cJSON *triggerItem);
typedef int (*TRIGGER_MATCH)(TriggerNode *trigger, void *content, u_int32_t contentSize);
typedef int (*PARAM_CHECK_DONE) (TriggerNode *trigger, u_int32_t index);
typedef int (*CMD_EXECUTE) (TriggerNode *trigger, const char *cmdName, const char *command);
TriggerNode *GetTriggerByName(TriggerWorkSpace *workSpace, const char *triggerName, u_int32_t *triggerIndex);
int ExecuteTrigger(TriggerWorkSpace *workSpace, TriggerNode *trigger, CMD_EXECUTE cmdExecuter);
int CheckTrigger(TriggerWorkSpace *workSpace,
int type, void *content, u_int32_t contentSize, PARAM_CHECK_DONE triggerExecuter);
int CheckParamTrigger(TriggerWorkSpace *workSpace,
const char *content, u_int32_t contentSize, PARAM_CHECK_DONE triggerExecuter);
TriggerNode *ExecuteQueuePop(TriggerWorkSpace *workSpace);
int ExecuteQueuePush(TriggerWorkSpace *workSpace, TriggerNode *trigger, u_int32_t index);
int ExecuteQueueSize(TriggerWorkSpace *workSpace);
TriggerWorkSpace *GetTriggerWorkSpace();
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // STARTUP_TRIGER_MANAGER_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 BASE_STARTUP_EVENT_MANAGER_H
#define BASE_STARTUP_EVENT_MANAGER_H
#include <stdio.h>
#include "sys_param.h"
#include "init_param.h"
#include "trigger_manager.h"
#include "uv.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef struct TriggerEvent {
uv_work_t request;
EventType type;
} TriggerEvent;
typedef struct {
uv_work_t request;
EventType type;
u_int32_t contentSize;
char content[0];
} TriggerDataEvent;
typedef struct TriggerExecute {
TriggerEvent event;
TriggerNode *trigger;
} TriggerExecute;
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif
\ No newline at end of file
/*
* Copyright (c) 2020 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 "sys_param.h"
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include "param_manager.h"
#define LABEL "Manager"
#define MAX_PROPERT_IN_WATCH 5
#define NORMAL_MEMORY_FOR_PARAM_CACHE 4 * 1024
static WorkSpace g_workSpace;
static pthread_mutex_t cacheLock = PTHREAD_MUTEX_INITIALIZER;
static int InitNormalMemory(WorkSpace *workSpace, u_int32_t spaceSize)
{
PARAM_CHECK(workSpace != NULL, return -1, "Invalid param");
if (workSpace->area != NULL) {
return 0;
}
void *areaAddr = (void *)mmap(NULL, spaceSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_POPULATE | MAP_ANON, -1, 0);
PARAM_CHECK(areaAddr != MAP_FAILED, return -1, "Failed to map memory error %s", strerror(errno));
workSpace->area = (WorkArea*)areaAddr;
atomic_init(&workSpace->area->serial, 0);
workSpace->area->dataSize = spaceSize;
workSpace->area->currOffset = sizeof(WorkArea);
PARAM_LOGI("InitNormalMemory success, currOffset %u firstNode %u dataSize %u",
workSpace->area->currOffset, workSpace->area->firstNode, workSpace->area->dataSize);
return 0;
}
static ParamCacheNode *AllocParamCacheNode(WorkSpace *workSpace, u_int32_t size)
{
PARAM_CHECK(workSpace != NULL, return 0, "Invalid param");
PARAM_CHECK((workSpace->area->currOffset + size) < workSpace->area->dataSize, return 0,
"Failed to allocate currOffset %d, dataSize %d", workSpace->area->currOffset, workSpace->area->dataSize);
ParamCacheNode *cache = (ParamCacheNode *)(workSpace->area->data + workSpace->area->currOffset);
workSpace->area->currOffset += size;
return cache;
}
static int CreateParamCache(ParamCache *cache, ParamWorkSpace *workSpace, ParamEvaluatePtr evaluate)
{
PARAM_CHECK(cache != NULL && evaluate != NULL, return -1, "Invalid param");
if (cache->cacheNode != NULL) {
return 0;
}
int ret = InitNormalMemory(&g_workSpace, NORMAL_MEMORY_FOR_PARAM_CACHE);
PARAM_CHECK(ret == 0, return -1, "Failed to init normal memory");
pthread_mutex_init(&cache->lock, NULL);
cache->serial = GetWorkSpaceSerial(&workSpace->paramSpace);
cache->cacheCount = 0;
cache->evaluate = evaluate;
cache->cacheNode = (ParamCacheNode *)AllocParamCacheNode(&g_workSpace,
sizeof(ParamCache) * MAX_PROPERT_IN_WATCH);
PARAM_CHECK(cache->cacheNode != NULL, return -1, "Failed to malloc memory");
return 0;
}
static int AddParamNode(ParamCache *cache, ParamWorkSpace *workSpace, const char *name, const char *defValue)
{
PARAM_CHECK(cache != NULL && name != NULL, return -1, "Invalid param");
PARAM_CHECK(cache->cacheCount < MAX_PROPERT_IN_WATCH, return -1, "Full param in cache");
ParamCacheNode *cacheNode = &cache->cacheNode[cache->cacheCount++];
int ret = memcpy_s(cacheNode->value, sizeof(cacheNode->value), defValue, strlen(defValue));
PARAM_CHECK(ret == 0, return -1, "Failed to copy default value");
ret = ReadParamWithCheck(workSpace, name, &cacheNode->handle);
PARAM_CHECK(ret == 0, return -1, "Failed to read param");
cacheNode->serial = ReadParamSerial(workSpace, cacheNode->handle);
return ret;
}
static int CheckCacheNode(ParamWorkSpace *workSpace, ParamCacheNode *cacheNode)
{
return cacheNode && ReadParamSerial(workSpace, cacheNode->handle) != cacheNode->serial;
}
static void RefreshCacheNode(ParamWorkSpace *workSpace, ParamCacheNode *cacheNode)
{
cacheNode->serial = ReadParamSerial(workSpace, cacheNode->handle);
u_int32_t len = sizeof(cacheNode->value);
ReadParamValue(workSpace, cacheNode->handle, cacheNode->value, &len);
}
static const char *TestParamCache(ParamCache *cache, ParamWorkSpace *workSpace)
{
int changeDetected = 0;
if (pthread_mutex_trylock(&cache->lock)) {
return cache->evaluate(cache->cacheCount, cache->cacheNode);
}
if (GetWorkSpaceSerial(&workSpace->paramSpace) != cache->serial) {
changeDetected = 1;
}
for (u_int32_t i = 0; (i < cache->cacheCount) && changeDetected == 0; i++) {
changeDetected = CheckCacheNode(workSpace, &cache->cacheNode[i]);
}
if (changeDetected) {
for (u_int32_t i = 0; i < cache->cacheCount; i++) {
RefreshCacheNode(workSpace, &cache->cacheNode[i]);
}
cache->serial = GetWorkSpaceSerial(&workSpace->paramSpace);
}
pthread_mutex_unlock(&cache->lock);
return cache->evaluate(cache->cacheCount, cache->cacheNode);
}
const char *DetectParamChange(ParamWorkSpace *workSpace, ParamCache *cache,
ParamEvaluatePtr evaluate, u_int32_t count, const char *parameters[][2])
{
pthread_mutex_lock(&cacheLock);
while (cache->cacheCount == 0) {
int ret = CreateParamCache(cache, workSpace, evaluate);
PARAM_CHECK(ret == 0, break, "Failed to create cache");
for (u_int32_t i = 0; i < count; i++) {
ret = AddParamNode(cache, workSpace, parameters[i][0], parameters[i][1]);
PARAM_CHECK(ret == 0, break, "Failed to add param cache");
}
PARAM_CHECK(ret == 0, break, "Failed to add param cache");
}
pthread_mutex_unlock(&cacheLock);
return TestParamCache(cache, workSpace);
}
此差异已折叠。
此差异已折叠。
/*
* Copyright (c) 2020 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 "sys_param.h"
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include "param_manager.h"
#include "param_trie.h"
#define LABEL "Manager"
#define MAX_BUFF 256
typedef struct {
WorkSpace *workSpace;
WorkSpace *persistWorkSpace;
char *buffer;
} PersistContext;
static ParamPersistWorkSpace g_persistWorkSpace = {ATOMIC_VAR_INIT(0), };
static int ProcessParamTraversal(WorkSpace *workSpace, TrieNode *node, void *cookie)
{
PARAM_CHECK(workSpace != 0 && node != NULL && cookie != NULL, return -1, "Invalid param");
TrieDataNode *current = (TrieDataNode *)node;
if (current == NULL || current->dataIndex == 0) {
return 0;
}
DataEntry *entry = (DataEntry *)GetTrieNode(workSpace, &current->dataIndex);
if (entry == NULL) {
return -1;
}
PersistContext *persistContext = (PersistContext *)cookie;
int ret = GetDataName(entry, persistContext->buffer, MAX_BUFF);
if (strncmp(persistContext->buffer, "persist.", strlen("persist.")) != 0) {
return 0;
}
ret |= GetDataValue(entry, persistContext->buffer + MAX_BUFF, MAX_BUFF);
if (ret == 0) { // 只支持新建
//PARAM_LOGI("Insert new persist param from normal param %s %s",
// persistContext->buffer, persistContext->buffer + MAX_BUFF);
ret = AddParam(persistContext->persistWorkSpace, persistContext->buffer, persistContext->buffer + MAX_BUFF);
}
PARAM_CHECK(ret == 0, return ret, "Failed to add persist param");
return ret;
}
static int ProcessPersistPropertTraversal(WorkSpace *workSpace, TrieNode *node, void *cookie)
{
TrieDataNode *current = (TrieDataNode *)node;
if (current == NULL || current->dataIndex == 0) {
return 0;
}
DataEntry *entry = (DataEntry *)GetTrieNode(workSpace, &current->dataIndex);
if (entry == NULL) {
return -1;
}
PersistContext *persistContext = (PersistContext *)cookie;
int ret = GetDataName(entry, persistContext->buffer, MAX_BUFF);
ret |= GetDataValue(entry, persistContext->buffer + MAX_BUFF, MAX_BUFF);
if (ret == 0) {
//PARAM_LOGI("update normal param %s %s from persist param %u",
// persistContext->buffer, persistContext->buffer + MAX_BUFF, current->dataIndex);
ret = WriteParam(persistContext->workSpace, persistContext->buffer, persistContext->buffer + MAX_BUFF);
}
PARAM_CHECK(ret == 0, return ret, "Failed to add persist param");
return ret;
}
int InitPersistParamWorkSpace(const char *context)
{
u_int32_t flags = atomic_load_explicit(&g_persistWorkSpace.flags, memory_order_relaxed);
if ((flags & WORKSPACE_FLAGS_INIT) == WORKSPACE_FLAGS_INIT) {
return 0;
}
g_persistWorkSpace.persistWorkSpace.compareTrieNode = CompareTrieDataNode;
g_persistWorkSpace.persistWorkSpace.allocTrieNode = AllocateTrieDataNode;
int ret = InitPersistWorkSpace(PARAM_PERSIST_PATH, &g_persistWorkSpace.persistWorkSpace);
PARAM_CHECK(ret == 0, return ret, "Failed to init persist param");
atomic_store_explicit(&g_persistWorkSpace.flags, WORKSPACE_FLAGS_INIT, memory_order_release);
return ret;
}
int RefreshPersistParams(ParamWorkSpace *workSpace, const char *context)
{
int ret = InitPersistParamWorkSpace(context);
PARAM_CHECK(ret == 0, return ret, "Failed to init persist param");
u_int32_t flags = atomic_load_explicit(&g_persistWorkSpace.flags, memory_order_relaxed);
if ((flags & WORKSPACE_FLAGS_LOADED) == WORKSPACE_FLAGS_LOADED) {
PARAM_LOGE("RefreshPersistParams has been loaded");
return 0;
}
// 申请临时的缓存,用于数据读取
char *buffer = (char *)malloc(MAX_BUFF + MAX_BUFF);
PARAM_CHECK(buffer != NULL, return -1, "Failed to malloc memory for param");
PersistContext persistContext = {
&workSpace->paramSpace, &g_persistWorkSpace.persistWorkSpace, buffer
};
// 遍历当前的参数,并把persist的写入
ret = TraversalTrieDataNode(&workSpace->paramSpace,
(TrieDataNode *)workSpace->paramSpace.rootNode, ProcessParamTraversal, &persistContext);
// 修改默认参数值
ret = TraversalTrieDataNode(&g_persistWorkSpace.persistWorkSpace,
(TrieDataNode *)g_persistWorkSpace.persistWorkSpace.rootNode, ProcessPersistPropertTraversal, &persistContext);
atomic_store_explicit(&g_persistWorkSpace.flags, flags | WORKSPACE_FLAGS_LOADED, memory_order_release);
free(buffer);
return ret;
}
void ClosePersistParamWorkSpace()
{
CloseWorkSpace(&g_persistWorkSpace.persistWorkSpace);
atomic_store_explicit(&g_persistWorkSpace.flags, 0, memory_order_release);
}
int WritePersistParam(const char *name, const char *value)
{
PARAM_CHECK(value != NULL && name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param");
if (strncmp(name, "persist.", strlen("persist.")) != 0) {
return 0;
}
int ret = InitPersistParamWorkSpace("");
PARAM_CHECK(ret == 0, return ret, "Failed to init persist param");
u_int32_t flags = atomic_load_explicit(&g_persistWorkSpace.flags, memory_order_relaxed);
if ((flags & WORKSPACE_FLAGS_LOADED) != WORKSPACE_FLAGS_LOADED) {
return 0;
}
return WriteParam(&g_persistWorkSpace.persistWorkSpace, name, value);
}
/*
* Copyright (c) 2020 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 "param_service.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "sys_param.h"
#include "param_manager.h"
#include "param_request.h"
#include "init_param.h"
#include "uv.h"
#define BUFFER_SIZE 256
#define LABEL "Server"
static char *g_initContext = "";
static ParamWorkSpace g_paramWorkSpace = {ATOMIC_VAR_INIT(0), {}, {}, {}};
void InitParamService()
{
int ret = InitParamWorkSpace(&g_paramWorkSpace, 0, g_initContext);
PARAM_CHECK(ret == 0, return, "Init parameter workspace fail");
}
int LoadDefaultParams(const char *fileName)
{
u_int32_t flags = atomic_load_explicit(&g_paramWorkSpace.flags, memory_order_relaxed);
if ((flags & WORKSPACE_FLAGS_INIT) != WORKSPACE_FLAGS_INIT) {
return PARAM_CODE_NOT_INIT;
}
FILE *fp = fopen(fileName, "r");
PARAM_CHECK(fp != NULL, return -1, "Open file %s fail", fileName);
char buff[BUFFER_SIZE];
SubStringInfo *info = malloc(sizeof(SubStringInfo) * (SUBSTR_INFO_LABEL + 1));
while(fgets(buff, BUFFER_SIZE, fp) != NULL) {
int subStrNumber = GetSubStringInfo(buff, strlen(buff), '=', info, SUBSTR_INFO_LABEL + 1);
if (subStrNumber <= SUBSTR_INFO_LABEL) {
continue;
}
if (strncmp(info[0].value, "ctl.", strlen("ctl.")) == 0) {
PARAM_LOGE("Do not set ctl. parameters from init %s", info[0].value);
continue;
}
if (strcmp(info[0].value, "selinux.restorecon_recursive") == 0) {
PARAM_LOGE("Do not set selinux.restorecon_recursive from init %s", info[0].value);
continue;
}
int ret = CheckParamName(info[0].value, 0);
PARAM_CHECK(ret == 0, continue, "Illegal param name %s", info[0].value);
ret = WriteParam(&g_paramWorkSpace.paramSpace, info[0].value, info[1].value);
PARAM_CHECK(ret == 0, continue, "Failed to set param %d %s", ret, buff);
}
fclose(fp);
free(info);
PARAM_LOGI("LoadDefaultParams proterty success %s", fileName);
return 0;
}
int LoadParamInfos(const char *fileName)
{
u_int32_t flags = atomic_load_explicit(&g_paramWorkSpace.flags, memory_order_relaxed);
if ((flags & WORKSPACE_FLAGS_INIT) != WORKSPACE_FLAGS_INIT) {
return PARAM_CODE_NOT_INIT;
}
FILE *fp = fopen(fileName, "r");
PARAM_CHECK(fp != NULL, return -1, "Open file %s fail", fileName);
SubStringInfo *info = malloc(sizeof(SubStringInfo) * SUBSTR_INFO_MAX);
char buff[BUFFER_SIZE];
int infoCount = 0;
while(fgets(buff, BUFFER_SIZE, fp) != NULL) {
int subStrNumber = GetSubStringInfo(buff, strlen(buff), ' ', info, SUBSTR_INFO_MAX);
if (subStrNumber <= 0) {
continue;
}
int ret = WriteParamInfo(&g_paramWorkSpace, info, subStrNumber);
PARAM_CHECK(ret == 0, continue, "Failed to write param info %d %s", ret, buff);
infoCount++;
}
fclose(fp);
free(info);
PARAM_LOGI("Load parameter info %d success %s", infoCount, fileName);
return 0;
}
static int ProcessParamSet(RequestMsg *msg)
{
PARAM_CHECK(msg != NULL, return PARAM_CODE_INVALID_PARAM, "Failed to check param");
SubStringInfo info[3];
int ret = GetSubStringInfo(msg->content, msg->contentSize, '=', info, sizeof(info)/sizeof(info[0]));
PARAM_CHECK(ret >= 2, return ret, "Failed to get name from content %s", msg->content);
PARAM_LOGI("ProcessParamSet name %s value: %s", info[0].value, info[1].value);
ret = WriteParamWithCheck(&g_paramWorkSpace, &msg->securitylabel, info[0].value, info[1].value);
PARAM_CHECK(ret == 0, return ret, "Failed to set param %d name %s %s", ret, info[0].value, info[1].value);
ret = WritePersistParam(info[0].value, info[1].value);
PARAM_CHECK(ret == 0, return ret, "Failed to set param");
// notify event to process trigger
PostTrigger(EVENT_PROPERTY, msg->content, msg->contentSize);
return 0;
}
static void OnClose(uv_handle_t *handle)
{
free(handle);
}
static void OnReceiveAlloc(uv_handle_t *handle, size_t suggestedSize, uv_buf_t* buf)
{
// 这里需要按实际消息的大小申请内存,取最大消息的长度
buf->len = sizeof(RequestMsg) + BUFFER_SIZE * 2;
buf->base = (char *)malloc(buf->len);
}
static void OnWriteResponse(uv_write_t *req, int status)
{
// 发送成功,释放请求内存
PARAM_LOGI("OnWriteResponse status %d", status);
ResponseNode *node = (ResponseNode*)req;
free(node);
}
static void SendResponse(uv_stream_t *handle, RequestType type, int result, void *content, int size)
{
int ret = 0;
// 申请整块内存,用于回复数据和写请求
ResponseNode *response = (ResponseNode *)malloc(sizeof(ResponseNode) + size);
PARAM_CHECK(response != NULL, return, "Failed to alloc memory for response");
response->msg.type = type;
response->msg.contentSize = size;
response->msg.result = result;
if (content != NULL && size != 0) {
ret = memcpy_s(response->msg.content, size, content, size);
PARAM_CHECK(ret == 0, return, "Failed to copy content");
}
uv_buf_t buf = uv_buf_init((char *)&response->msg, sizeof(response->msg) + size);
ret = uv_write2(&response->writer, handle, &buf, 1, handle, OnWriteResponse);
PARAM_CHECK(ret >= 0, return, "Failed to uv_write2 ret %s", uv_strerror(ret));
}
static void OnReceiveRequest(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
{
if (nread <= 0 || buf == NULL || buf->base == NULL) {
uv_close((uv_handle_t*)handle, OnClose);
free(buf->base);
return;
}
int freeHandle = 1;
RequestMsg *msg = (RequestMsg *)buf->base;
switch (msg->type) {
case SET_PARAM: {
freeHandle = 0;
int ret = ProcessParamSet(msg);
SendResponse(handle, SET_PARAM, ret, NULL, 0);
break;
}
default:
PARAM_LOGE("not supported the command: %d", msg->type);
break;
}
free(buf->base);
uv_close((uv_handle_t*)handle, OnClose);
}
static void OnConnection(uv_stream_t *server, int status)
{
PARAM_CHECK(status >= 0, return, "Error status %d", status);
PARAM_CHECK(server != NULL, return, "Error server");
uv_pipe_t *stream = (uv_pipe_t*)malloc(sizeof(uv_pipe_t));
PARAM_CHECK(stream != NULL, return, "Failed to alloc stream");
int ret = uv_pipe_init(uv_default_loop(), (uv_pipe_t*)stream, 1);
PARAM_CHECK(ret == 0, free(stream); return, "Failed to uv_pipe_init %d", ret);
stream->data = server;
ret = uv_accept(server, (uv_stream_t *)stream);
PARAM_CHECK(ret == 0, uv_close((uv_handle_t*)stream, NULL); free(stream);
return, "Failed to uv_accept %d", ret);
ret = uv_read_start((uv_stream_t *)stream, OnReceiveAlloc, OnReceiveRequest);
PARAM_CHECK(ret == 0, uv_close((uv_handle_t*)stream, NULL); free(stream);
return, "Failed to uv_read_start %d", ret);
}
void StopParamService()
{
uv_fs_t req;
uv_fs_unlink(uv_default_loop(), &req, PIPE_NAME, NULL);
CloseParamWorkSpace(&g_paramWorkSpace);
ClosePersistParamWorkSpace();
uv_stop(uv_default_loop());
PARAM_LOGI("StopParamService.");
}
int StartParamService()
{
PARAM_LOGI("StartParamService.");
uv_fs_t req;
uv_fs_unlink(uv_default_loop(), &req, PIPE_NAME, NULL);
uv_pipe_t pipeServer;
int ret = uv_pipe_init(uv_default_loop(), &pipeServer, 0);
PARAM_CHECK(ret == 0, return ret, "Failed to uv_pipe_init %d", ret);
ret = uv_pipe_bind(&pipeServer, PIPE_NAME);
PARAM_CHECK(ret == 0, return ret, "Failed to uv_pipe_bind %d %s", ret, uv_err_name(ret));
ret = uv_listen((uv_stream_t*)&pipeServer, SOMAXCONN, OnConnection);
PARAM_CHECK(ret == 0, return ret, "Failed to uv_listen %d %s", ret, uv_err_name(ret));
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
PARAM_LOGI("Start service exit.");
return 0;
}
int SystemWriteParam(const char *name, const char *value)
{
PARAM_CHECK(name != NULL && value != NULL, return -1, "The name is null");
PARAM_LOGI("SystemWriteParam name %s value: %s", name, value);
int ret = WriteParamWithCheck(&g_paramWorkSpace, &g_paramWorkSpace.label, name, value);
//PARAM_LOGI("SystemWriteParam name %s value: %s", name, value);
if (ret == 0) {
ret = WritePersistParam(name, value);
PARAM_CHECK(ret == 0, return ret, "Failed to set param");
} else {
PARAM_LOGE("Failed to set param %d name %s %s", ret, name, value);
}
// notify event to process trigger
PostParamTrigger(name, value);
return 0;
}
int SystemReadParam(const char *name, char *value, unsigned int *len)
{
PARAM_CHECK(name != NULL && len != NULL, return -1, "The name is null");
ParamHandle handle = 0;
int ret = ReadParamWithCheck(&g_paramWorkSpace, name, &handle);
if (ret == 0) {
ret = ReadParamValue(&g_paramWorkSpace, handle, value, len);
}
return ret;
}
ParamWorkSpace *GetParamWorkSpace()
{
return &g_paramWorkSpace;
}
int LoadPersistParams()
{
return RefreshPersistParams(&g_paramWorkSpace, g_initContext);
}
int SystemTraversalParam(void (*traversalParameter)(ParamHandle handle, void* cookie), void* cookie)
{
PARAM_CHECK(traversalParameter != NULL, return -1, "The param is null");
return TraversalParam(&g_paramWorkSpace, traversalParameter, cookie);
}
\ 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.
*/
#include "trigger_checker.h"
#include <ctype.h>
#include "trigger_manager.h"
#include "param_service.h"
#define LABEL "Trigger"
// 申请整块能存作为计算的节点
int CalculatorInit(LogicCalculator *calculator, int dataNumber, int dataUnit, int needCondition)
{
PARAM_CHECK(calculator != NULL, return -1, "Invalid param");
int dataSize = dataUnit * dataNumber;
if (needCondition) {
dataSize += 5 * SUPPORT_DATA_BUFFER_MAX;
}
calculator->data = (char *)malloc(dataSize);
PARAM_CHECK(calculator->data != NULL, return -1, "Failed to malloc for calculator");
calculator->dataNumber = dataNumber;
calculator->endIndex = 0;
calculator->dataUnit = dataUnit;
dataSize = dataUnit * dataNumber;
calculator->conditionName = calculator->data + dataSize;
dataSize += SUPPORT_DATA_BUFFER_MAX;
calculator->conditionContent = calculator->data + dataSize;
dataSize += SUPPORT_DATA_BUFFER_MAX;
calculator->inputName = calculator->data + dataSize;
dataSize += SUPPORT_DATA_BUFFER_MAX;
calculator->inputContent = calculator->data + dataSize;
dataSize += SUPPORT_DATA_BUFFER_MAX;
calculator->readContent = calculator->data + dataSize;
return 0;
}
void CalculatorFree(LogicCalculator *calculator)
{
PARAM_CHECK(calculator != NULL, return, "Invalid param");
free(calculator->data);
calculator->data = NULL;
}
static void CalculatorClear(LogicCalculator *calculator)
{
PARAM_CHECK(calculator != NULL, return, "Invalid param");
calculator->endIndex = 0;
}
static int CalculatorPushChar(LogicCalculator *calculator, char data)
{
PARAM_CHECK(calculator != NULL, return -1, "Invalid param");
PARAM_CHECK(calculator->endIndex < calculator->dataNumber, return -1, "More data for calculator support");
PARAM_CHECK(sizeof(char) == calculator->dataUnit, return -1, "More data for calculator support");
calculator->data[calculator->endIndex++] = data;
return 0;
}
static int CalculatorPopChar(LogicCalculator *calculator, char *data)
{
PARAM_CHECK(calculator != NULL, return -1, "Invalid param");
PARAM_CHECK(calculator->endIndex < calculator->dataNumber, return -1, "More data for calculator support");
if (calculator->endIndex == 0) {
return -1;
}
*data = calculator->data[--calculator->endIndex];
return 0;
}
static int CalculatorPush(LogicCalculator *calculator, void *data)
{
PARAM_CHECK(calculator != NULL, return -1, "Invalid param");
PARAM_CHECK(calculator->endIndex < calculator->dataNumber, return -1, "More data for calculator support");
char *tmpData = (calculator->data + calculator->dataUnit * calculator->endIndex);
int ret = memcpy_s(tmpData, calculator->dataUnit, data, calculator->dataUnit);
PARAM_CHECK(ret == 0, return -1, "Failed to copy logic data");
calculator->endIndex++;
return 0;
}
static int CalculatorPop(LogicCalculator *calculator, void *data)
{
PARAM_CHECK(calculator != NULL || data == NULL, return -1, "Invalid param");
PARAM_CHECK(calculator->endIndex < calculator->dataNumber, return -1, "More data for calculator support");
if (calculator->endIndex == 0) {
return -1;
}
char *tmpData = calculator->data + calculator->dataUnit * (calculator->endIndex - 1);
int ret = memcpy_s(data, calculator->dataUnit, tmpData, calculator->dataUnit);
PARAM_CHECK(ret == 0, return -1, "Failed to copy logic data");
calculator->endIndex--;
return 0;
}
static int CalculatorLength(const LogicCalculator *calculator)
{
PARAM_CHECK(calculator != NULL, return 0, "Invalid param");
return calculator->endIndex;
}
static int PrefixAdd(char *prefix, u_int32_t *prefixIndex, u_int32_t prefixLen, char op)
{
if ((*prefixIndex + 3) >= prefixLen) {
return -1;
}
prefix[(*prefixIndex)++] = ' ';
prefix[(*prefixIndex)++] = op;
prefix[(*prefixIndex)++] = ' ';
return 0;
}
static int HandleOperationOr(LogicCalculator *calculator, char *prefix, u_int32_t *prefixIndex, u_int32_t prefixLen)
{
int ret = 0;
char e;
prefix[(*prefixIndex)++] = ' ';
if(CalculatorLength(calculator) == 0) {
CalculatorPushChar(calculator, '|');
} else {
do {
CalculatorPopChar(calculator, &e);
if (e == '(') {
CalculatorPushChar(calculator, e);
} else {
ret = PrefixAdd(prefix, prefixIndex, prefixLen, e);
PARAM_CHECK(ret == 0, return -1, "Invalid prefix");
}
} while (CalculatorLength(calculator) > 0 && e != '(');
CalculatorPushChar(calculator, '|');
}
return 0;
}
static int ComputeSubCondition(LogicCalculator *calculator, LogicData *data, const char *condition)
{
if (!LOGIC_DATA_TEST_FLAG(data, LOGIC_DATA_FLAGS_ORIGINAL)) {
return LOGIC_DATA_TEST_FLAG(data, LOGIC_DATA_FLAGS_TRUE);
}
// 解析条件
int ret = GetValueFromContent(condition + data->startIndex,
data->endIndex - data->startIndex, 0, calculator->conditionName, SUPPORT_DATA_BUFFER_MAX);
PARAM_CHECK(ret == 0, return -1, "Failed parse content name");
ret = GetValueFromContent(condition + data->startIndex, data->endIndex - data->startIndex,
strlen(calculator->conditionName) + 1, calculator->conditionContent, SUPPORT_DATA_BUFFER_MAX);
PARAM_CHECK(ret == 0, return -1, "Failed parse content value");
// check name
if (strcmp(calculator->conditionName, calculator->inputName) == 0) {
if (strcmp(calculator->conditionContent, "*") == 0) {
return 1;
}
if (strcmp(calculator->conditionContent, calculator->inputContent) == 0) {
return 1;
}
}/* else {
u_int32_t len = SUPPORT_DATA_BUFFER_MAX;
ret = SystemReadParam(calculator->conditionName, calculator->readContent, &len);
if (ret == 0 && strcmp(calculator->conditionContent, calculator->readContent) == 0) {
return 1;
}
}*/
return 0;
}
int GetValueFromContent(const char *content, u_int32_t contentSize, u_int32_t start, char *value, u_int32_t valueSize)
{
u_int32_t contentIndex = start;
u_int32_t currIndex = 0;
while (contentIndex < contentSize && currIndex < valueSize) {
if (isspace(content[contentIndex])) {
contentIndex++;
continue;
}
if (content[contentIndex] == '=') {
value[currIndex++] = '\0';
return 0;
}
value[currIndex++] = content[contentIndex++];
}
if (currIndex < valueSize) {
value[currIndex] = '\0';
return 0;
}
return -1;
}
int ComputeCondition(LogicCalculator *calculator, const char *condition)
{
u_int32_t currIndex = 0;
u_int32_t start = 0;
int noneOper = 1;
CalculatorClear(calculator);
LogicData data1 = {};
LogicData data2 = {};
while (currIndex < strlen(condition)) {
if (condition[currIndex] == '|' || condition[currIndex] == '&') {
noneOper = 0;
int ret = CalculatorPop(calculator, (void*)&data2);
ret |= CalculatorPop(calculator, (void*)&data1);
PARAM_CHECK(ret == 0, return -1, "Failed to pop data");
ret = ComputeSubCondition(calculator, &data1, condition);
data1.flags = 0;
if (condition[currIndex] == '|' && ret == 1) {
LOGIC_DATA_SET_FLAG(&data1, LOGIC_DATA_FLAGS_TRUE);
} else if (condition[currIndex] == '|' || ret == 1) {
if (ComputeSubCondition(calculator, &data2, condition) == 1) {
LOGIC_DATA_SET_FLAG(&data1, LOGIC_DATA_FLAGS_TRUE);
}
}
ret = CalculatorPush(calculator, (void*)&data1);
PARAM_CHECK(ret == 0, return -1, "Failed to push data");
start = currIndex + 1; // 跳过符号
} else if (isspace(condition[currIndex])) {
if (start == currIndex) {
start = ++currIndex;
continue;
}
data1.flags = LOGIC_DATA_FLAGS_ORIGINAL;
data1.startIndex = start;
data1.endIndex = currIndex;
int ret = CalculatorPush(calculator, (void*)&data1);
PARAM_CHECK(ret == 0, return -1, "Failed to push data");
start = currIndex + 1;
}
currIndex++;
}
if (noneOper) {
data1.flags = LOGIC_DATA_FLAGS_ORIGINAL;
data1.startIndex = start;
data1.endIndex = strlen(condition);
} else {
int ret = CalculatorPop(calculator, &data1);
PARAM_CHECK(ret == 0, return -1, "Invalid calculator");
}
return ComputeSubCondition(calculator, &data1, condition);
}
int ConvertInfixToPrefix(const char *condition, char *prefix, u_int32_t prefixLen)
{
char e;
int ret = 0;
u_int32_t curr = 0;
u_int32_t prefixIndex = 0;
LogicCalculator calculator;
CalculatorInit(&calculator, 100, 1, 0);
while (curr < strlen(condition)) {
if (condition[curr] == ')') {
CalculatorPopChar(&calculator, &e);
while (e != '(') {
ret = PrefixAdd(prefix, &prefixIndex, prefixLen, e);
PARAM_CHECK(ret == 0, CalculatorFree(&calculator); return -1, "Invalid prefix");
ret = CalculatorPopChar(&calculator, &e);
PARAM_CHECK(ret == 0, CalculatorFree(&calculator); return -1, "Invalid calculator");
}
} else if (condition[curr] == '|') {
PARAM_CHECK(condition[curr + 1] == '|', CalculatorFree(&calculator); return -1, "Invalid condition");
ret = HandleOperationOr(&calculator, prefix, &prefixIndex, prefixLen);
PARAM_CHECK(ret == 0, CalculatorFree(&calculator); return -1, "Invalid prefix");
curr++;
} else if (condition[curr] == '&') {
PARAM_CHECK(condition[curr + 1] == '&', CalculatorFree(&calculator); return -1, "Invalid condition");
prefix[prefixIndex++] = ' ';
CalculatorPushChar(&calculator, condition[curr]);
curr++;
} else if (condition[curr] == '(') {
CalculatorPushChar(&calculator, condition[curr]);
} else {
prefix[prefixIndex++] = condition[curr];
}
curr++;
PARAM_CHECK(prefixIndex < prefixLen, CalculatorFree(&calculator); return -1, "Invalid prefixIndex");
}
while (CalculatorLength(&calculator) > 0) {
CalculatorPopChar(&calculator, &e);
ret = PrefixAdd(prefix, &prefixIndex, prefixLen, e);
PARAM_CHECK(ret == 0, CalculatorFree(&calculator);
return -1, "Invalid prefix %u %u", prefixIndex, prefixLen);
}
prefix[prefixIndex] = '\0';
CalculatorFree(&calculator);
return 0;
}
\ 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.
*/
#include "trigger_manager.h"
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "init_cmds.h"
#include "init_utils.h"
#include "trigger_checker.h"
#define LABEL "Trigger"
#define TRIGGER_AREA_SPACE 1024*64
#define TRIGGER_EXECUTE_QUEUE 64
#define BUFFER_SIZE 256
#define CHECK_INDEX_VALID(workSpace, index) \
(u_int32_t)(index) < sizeof((workSpace)->header) / sizeof((workSpace)->header[0])
#ifdef STARTUP_LOCAL
#define TRIGGER_PATH "/media/sf_ubuntu/test/__trigger__/trigger"
#else
#define TRIGGER_PATH "/dev/__trigger__/trigger"
#endif
int InitTriggerWorkSpace(TriggerWorkSpace *workSpace)
{
PARAM_CHECK(workSpace != NULL, return -1, "Invalid parm");
if (workSpace->area != NULL) {
return 0;
}
CheckAndCreateDir(TRIGGER_PATH);
int fd = open(TRIGGER_PATH, O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC, 0444);
PARAM_CHECK(fd >= 0, return -1, "Open file fail error %s", strerror(errno));
lseek(fd, TRIGGER_AREA_SPACE, SEEK_SET);
write(fd, "", 1);
void *areaAddr = (void *)mmap(NULL, TRIGGER_AREA_SPACE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
PARAM_CHECK(areaAddr != MAP_FAILED, close(fd); return -1,
"Failed to map memory error %s", strerror(errno));
close(fd);
// 第一部分做执行队列
workSpace->executeQueue.executeQueue = (u_int32_t *)areaAddr;
workSpace->executeQueue.queueCount = TRIGGER_EXECUTE_QUEUE;
workSpace->executeQueue.startIndex = 0;
workSpace->executeQueue.endIndex = 0;
pthread_mutex_init(&workSpace->executeQueue.mutex, NULL);
// 动态数据保存
workSpace->area = (TriggerArea *)(areaAddr + TRIGGER_EXECUTE_QUEUE * sizeof(u_int32_t));
atomic_init(&workSpace->area->serial, ATOMIC_VAR_INIT(0));
workSpace->area->dataSize = TRIGGER_AREA_SPACE - sizeof(TriggerArea) - TRIGGER_EXECUTE_QUEUE * sizeof(u_int32_t);
workSpace->area->currOffset = sizeof(TriggerArea) + TRIGGER_EXECUTE_QUEUE * sizeof(u_int32_t);
for (size_t i = 0; i < sizeof(workSpace->header) / sizeof(workSpace->header[0]); i++) {
atomic_init(&workSpace->header[i].firstTrigger, ATOMIC_VAR_INIT(0));
atomic_init(&workSpace->header[i].lastTrigger, ATOMIC_VAR_INIT(0));
}
return 0;
}
static CommandNode *GetCmdByIndex(TriggerWorkSpace *workSpace, TriggerNode *trigger, u_int32_t index)
{
if (index == 0 || index == (u_int32_t)-1) {
return NULL;
}
u_int32_t size = sizeof(CommandNode) + 2;
PARAM_CHECK((index + size) < workSpace->area->dataSize,
return NULL, "Invalid index for cmd %u", index);
return (CommandNode *)(workSpace->area->data + index);
}
static u_int32_t AddCommand(TriggerWorkSpace *workSpace, TriggerNode *trigger, const char *cmdName, const char *content)
{
PARAM_CHECK(workSpace != NULL && trigger != NULL, return 0, "list is null");
u_int32_t size = sizeof(CommandNode) + strlen(cmdName) + 1;
size += (content == NULL) ? 1 : strlen(content) + 1;
PARAM_CHECK((workSpace->area->currOffset + size) < workSpace->area->dataSize,
return 0, "Not enough memory for cmd %u %u", size, workSpace->area->currOffset);
CommandNode *node = (CommandNode *)(workSpace->area->data + workSpace->area->currOffset);
PARAM_CHECK(node != NULL, return 0, "Failed to alloc memory for command");
int ret = memcpy_s(node->name, sizeof(node->name) - 1, cmdName, strlen(cmdName));
PARAM_CHECK(ret == 0, return 0, "Failed to copy command");
node->name[strlen(cmdName)] = '\0';
if (content != NULL) {
ret = memcpy_s(node->content, size, content, strlen(content));
node->content[strlen(content)] = '\0';
PARAM_CHECK(ret == 0, return 0, "Failed to copy command");
} else {
node->content[0] = '\0';
}
u_int32_t offset = workSpace->area->currOffset;
atomic_init(&node->next, ATOMIC_VAR_INIT(0));
// 插入队列
if (trigger->firstCmd == 0) {
atomic_store_explicit(&trigger->firstCmd, offset, memory_order_release);
atomic_store_explicit(&trigger->lastCmd, offset, memory_order_release);
} else {
CommandNode *lastNode = GetCmdByIndex(workSpace, trigger, trigger->lastCmd);
if (lastNode != NULL) {
atomic_store_explicit(&lastNode->next, offset, memory_order_release);
}
atomic_store_explicit(&trigger->lastCmd, offset, memory_order_release);
}
workSpace->area->currOffset += size;
return offset;
}
static TriggerNode *GetTriggerByIndex(TriggerWorkSpace *workSpace, u_int32_t index)
{
if (index == 0 || index == (u_int32_t)-1) {
return NULL;
}
u_int32_t size = sizeof(TriggerNode) + 1;
PARAM_CHECK((index + size) < workSpace->area->dataSize,
return NULL, "Invalid index for trigger %u", index);
return (TriggerNode *)(workSpace->area->data + index);
}
static u_int32_t AddTrigger(TriggerWorkSpace *workSpace, int type, const char *name, const char *condition)
{
PARAM_CHECK(workSpace != NULL && name != NULL, return 0, "list is null");
const char *tmpCond = condition;
if (type == TRIGGER_BOOT && condition == NULL) {
tmpCond = name;
}
u_int32_t conditionSize = (tmpCond == NULL) ? 1 : strlen(tmpCond) + 1 + CONDITION_EXTEND_LEN;
PARAM_CHECK((workSpace->area->currOffset + sizeof(TriggerNode) + conditionSize) < workSpace->area->dataSize,
return -1, "Not enough memory for cmd");
TriggerNode *node = (TriggerNode *)(workSpace->area->data + workSpace->area->currOffset);
PARAM_CHECK(node != NULL, return 0, "Failed to alloc memory for trigger");
node->type = type;
int ret = memcpy_s(node->name, sizeof(node->name) - 1, name, strlen(name));
PARAM_CHECK(ret == 0, return 0, "Failed to memcpy_s for trigger");
node->name[strlen(name)] = '\0';
if (tmpCond != NULL) {
if (type == TRIGGER_PROPERTY) {
ret = ConvertInfixToPrefix(tmpCond, node->condition, conditionSize);
PARAM_CHECK(ret == 0, return 0, "Failed to memcpy_s for trigger");
} else {
ret = memcpy_s(node->condition, strlen(tmpCond) + 1, tmpCond, strlen(tmpCond));
PARAM_CHECK(ret == 0, return 0, "Failed to memcpy_s for trigger");
node->condition[strlen(tmpCond)] = '\0';
}
} else {
node->condition[0] = '\0';
}
u_int32_t offset = workSpace->area->currOffset;
atomic_init(&node->serial, ATOMIC_VAR_INIT(0));
atomic_init(&node->next, ATOMIC_VAR_INIT(0));
atomic_init(&node->firstCmd, ATOMIC_VAR_INIT(0));
atomic_init(&node->lastCmd, ATOMIC_VAR_INIT(0));
// 插入到trigger队列中
if (workSpace->header[type].firstTrigger == 0) {
atomic_store_explicit(&workSpace->header[type].firstTrigger, offset, memory_order_release);
atomic_store_explicit(&workSpace->header[type].lastTrigger, offset, memory_order_release);
} else {
TriggerNode *lastNode = GetTriggerByIndex(workSpace, workSpace->header[type].lastTrigger);
if (lastNode != NULL) {
atomic_store_explicit(&lastNode->next, offset, memory_order_release);
}
atomic_store_explicit(&workSpace->header[type].lastTrigger, offset, memory_order_release);
}
workSpace->area->currOffset += conditionSize + sizeof(TriggerNode);
return offset;
}
static int GetTriggerIndex(const char *type)
{
if (strncmp("param", type, strlen("param")) == 0) {
return TRIGGER_PROPERTY;
}
static const char *triggerType[] = {
"pre-init", "boot", "early-init", "init", "early-init", "late-init", "post-init",
"early-fs", "post-fs", "late-fs", "post-fs-data",
"nonencrypted",
"firmware_mounts_complete",
"load_persist_params_action"
};
for (size_t i = 0; i < sizeof(triggerType) / sizeof(char*); i++) {
if (strncmp(triggerType[i], type, strlen(triggerType[i])) == 0) {
return TRIGGER_BOOT;
}
}
return TRIGGER_BOOT;
}
static int CheckBootTriggerMatch(TriggerNode *trigger, void *content, u_int32_t contentSize)
{
if (strncmp(trigger->name, (char *)content, contentSize) == 0) {
return 1;
}
return 0;
}
int ParseTrigger(TriggerWorkSpace *workSpace, cJSON *triggerItem)
{
PARAM_CHECK(triggerItem != NULL, return -1, "Invalid file");
PARAM_CHECK(workSpace != NULL, return -1, "Failed to create trigger list");
char *name = cJSON_GetStringValue(cJSON_GetObjectItem(triggerItem, "name"));
PARAM_CHECK(name != NULL, return -1, "Can not get name from cfg");
char *condition = cJSON_GetStringValue(cJSON_GetObjectItem(triggerItem, "condition"));
int index = GetTriggerIndex(name);
PARAM_CHECK(CHECK_INDEX_VALID(workSpace, index), return -1, "Failed to get trigger index");
u_int32_t offset = 0;
TriggerNode *trigger = GetTriggerByName(workSpace, name, &offset);
if (trigger == NULL) {
offset = AddTrigger(workSpace, index, name, condition);
PARAM_CHECK(offset > 0, return -1, "Failed to create trigger %s", name);
trigger = GetTriggerByIndex(workSpace, offset);
} else {
if (condition != NULL) {
PARAM_LOGE("Warning parseTrigger %s %s", name, condition);
}
}
PARAM_LOGE("ParseTrigger %s %u", name, offset);
// 添加命令行
cJSON* cmdItems = cJSON_GetObjectItem(triggerItem, CMDS_ARR_NAME_IN_JSON);
PARAM_CHECK(cJSON_IsArray(cmdItems), return -1, "Command item must be array");
int cmdLinesCnt = cJSON_GetArraySize(cmdItems);
PARAM_CHECK(cmdLinesCnt > 0, return -1, "Command array size must positive %s", name);
for (int i = 0; i < cmdLinesCnt; ++i) {
char *cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdItems, i));
PARAM_CHECK(cmdLinesCnt > 0, continue, "Command is null");
size_t cmdLineLen = strlen(cmdLineStr);
const char *matchCmd = GetMatchCmd(cmdLineStr);
if (matchCmd == NULL && strncmp(cmdLineStr, TRIGGER_CMD, strlen(TRIGGER_CMD)) == 0) {
matchCmd = TRIGGER_CMD;
}
PARAM_CHECK(matchCmd != NULL, continue, "Command not support %s", cmdLineStr);
size_t matchLen = strlen(matchCmd);
if (matchLen == cmdLineLen) {
offset = AddCommand(workSpace, trigger, matchCmd, NULL);
} else {
offset = AddCommand(workSpace, trigger, matchCmd, cmdLineStr + matchLen);
}
//PARAM_LOGE("AddCommand %u %s %u", offset, cmdLineStr, workSpace->area->currOffset);
PARAM_CHECK(offset > 0, continue, "Failed to add command %s", cmdLineStr);
}
return 0;
}
int ExecuteTrigger(TriggerWorkSpace *workSpace, TriggerNode *trigger, CMD_EXECUTE cmdExecuter)
{
PARAM_CHECK(workSpace != NULL && trigger != NULL && cmdExecuter != NULL, return -1, "Invalid param");
PARAM_LOGI("ExecuteCmds trigger %s", trigger->name);
CommandNode *cmd = GetCmdByIndex(workSpace, trigger, trigger->firstCmd);
while (cmd != NULL) {
cmdExecuter(trigger, cmd->name, cmd->content);
cmd = GetCmdByIndex(workSpace, trigger, cmd->next);
}
return 0;
}
int ExecuteQueuePush(TriggerWorkSpace *workSpace, TriggerNode *trigger, u_int32_t triggerIndex)
{
PARAM_CHECK(workSpace != NULL, return -1, "Invalid area");
pthread_mutex_lock(&workSpace->executeQueue.mutex);
u_int32_t index = workSpace->executeQueue.endIndex++ % workSpace->executeQueue.queueCount;
workSpace->executeQueue.executeQueue[index] = triggerIndex;
pthread_mutex_unlock(&workSpace->executeQueue.mutex);
return 0;
}
TriggerNode *ExecuteQueuePop(TriggerWorkSpace *workSpace)
{
if (workSpace->executeQueue.endIndex <= workSpace->executeQueue.startIndex) {
return NULL;
}
pthread_mutex_lock(&workSpace->executeQueue.mutex);
u_int32_t currIndex = workSpace->executeQueue.startIndex % workSpace->executeQueue.queueCount;
u_int32_t triggerIndex = workSpace->executeQueue.executeQueue[currIndex];
workSpace->executeQueue.executeQueue[currIndex] = 0;
workSpace->executeQueue.startIndex++;
pthread_mutex_unlock(&workSpace->executeQueue.mutex);
return GetTriggerByIndex(workSpace, triggerIndex);
}
int ExecuteQueueSize(TriggerWorkSpace *workSpace)
{
PARAM_CHECK(workSpace != NULL, return 0, "Invalid param");
return workSpace->executeQueue.endIndex - workSpace->executeQueue.startIndex;
}
int CheckTrigger(TriggerWorkSpace *workSpace,
int type, void *content, u_int32_t contentSize, PARAM_CHECK_DONE triggerExecuter)
{
static TRIGGER_MATCH triggerCheckMatch[TRIGGER_MAX] = {
CheckBootTriggerMatch, NULL, NULL
};
PARAM_LOGI("ExecuteTrigger check content %s", (char*)content);
PARAM_CHECK(workSpace != NULL, return -1, "Trigger not init");
PARAM_CHECK(CHECK_INDEX_VALID(workSpace, type), return -1, "Invalid type %d", type);
PARAM_CHECK((u_int32_t)type < sizeof(triggerCheckMatch) / sizeof(triggerCheckMatch[0]),
return -1, "Failed to get check function");
PARAM_CHECK(triggerCheckMatch[type] != NULL, return 0, "Failed to get check function");
u_int32_t index = workSpace->header[type].firstTrigger;
TriggerNode *trigger = GetTriggerByIndex(workSpace, workSpace->header[type].firstTrigger);
while (trigger != NULL) {
if (triggerCheckMatch[type](trigger, content, contentSize) == 1) { // 等于1 则认为匹配
triggerExecuter(trigger, index);
}
index = trigger->next;
trigger = GetTriggerByIndex(workSpace, trigger->next);
}
return 0;
}
int CheckParamTrigger(TriggerWorkSpace *workSpace,
const char *content, u_int32_t contentSize, PARAM_CHECK_DONE triggerExecuter)
{
PARAM_CHECK(workSpace != NULL && content != NULL && triggerExecuter != NULL,
return -1, "Failed arg for param trigger");
LogicCalculator calculator;
CalculatorInit(&calculator, 100, sizeof(LogicData), 1);
// 先解析content
int ret = GetValueFromContent(content, contentSize, 0, calculator.inputName, SUPPORT_DATA_BUFFER_MAX);
PARAM_CHECK(ret == 0, CalculatorFree(&calculator); return -1, "Failed parse content name");
ret = GetValueFromContent(content, contentSize,
strlen(calculator.inputName) + 1, calculator.inputContent, SUPPORT_DATA_BUFFER_MAX);
PARAM_CHECK(ret == 0, CalculatorFree(&calculator); return -1, "Failed parse content value");
PARAM_LOGI("CheckParamTrigger content %s ", content);
u_int32_t index = workSpace->header[TRIGGER_PROPERTY].firstTrigger;
TriggerNode *trigger = GetTriggerByIndex(workSpace, workSpace->header[TRIGGER_PROPERTY].firstTrigger);
while (trigger != NULL) {
ret = ComputeCondition(&calculator, trigger->condition);
if (ret == 1) {
triggerExecuter(trigger, index);
}
index = trigger->next;
trigger = GetTriggerByIndex(workSpace, trigger->next);
}
CalculatorFree(&calculator);
return 0;
}
TriggerNode *GetTriggerByName(TriggerWorkSpace *workSpace, const char *triggerName, u_int32_t *triggerIndex)
{
PARAM_CHECK(workSpace != NULL && triggerName != NULL, return NULL, "Invalid param");
for (size_t i = 0; i < sizeof(workSpace->header) / sizeof(workSpace->header[0]); i++) {
u_int32_t index = workSpace->header[i].firstTrigger;
TriggerNode *trigger = GetTriggerByIndex(workSpace, workSpace->header[i].firstTrigger);
while (trigger != NULL) {
if (strcmp(triggerName, trigger->name) == 0) {
*triggerIndex = index;
return trigger;
}
index = trigger->next;
trigger = GetTriggerByIndex(workSpace, trigger->next);
}
}
return NULL;
}
\ 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.
*/
#include "trigger_processor.h"
#include <pthread.h>
#include <unistd.h>
#include "init_cmds.h"
#include "param_manager.h"
#include "trigger_checker.h"
#include "uv.h"
#define LABEL "Trigger"
#define SYS_POWER_CTRL "sys.powerctrl."
static int g_triggerServiceStart = 0;
static TriggerWorkSpace g_triggerWorkSpace = {};
static int DoCmdExecute(TriggerNode *trigger, const char *cmdName, const char *command)
{
PARAM_CHECK(trigger != NULL && cmdName != NULL && command != NULL, return -1, "Invalid param");
if (strncmp(cmdName, TRIGGER_CMD, strlen(TRIGGER_CMD)) == 0) {
u_int32_t triggerIndex = 0;
TriggerNode *node = GetTriggerByName(&g_triggerWorkSpace, command, &triggerIndex);
if (node != NULL && !TRIGGER_NODE_IN_QUEUE(node)) { // 不在队列中
PARAM_LOGI("DoCmdExecute trigger %s", node->name);
TRIGGER_NODE_SET_QUEUE_FLAG(node);
ExecuteQueuePush(&g_triggerWorkSpace, node, triggerIndex);
}
return 0;
}
PARAM_LOGI("DoCmdExecute trigger %s cmd %s %s", trigger->name, cmdName, command);
DoCmdByName(cmdName, command);
return 0;
}
static int DoTiggerCheckResult(TriggerNode *trigger, u_int32_t triggerIndex)
{
// 已经在队列中了,则不执行 TODO
if (TRIGGER_NODE_IN_QUEUE(trigger)) {
PARAM_LOGI("DoTiggerExecute trigger %s has been waiting execute", trigger->name);
return 0;
}
TRIGGER_NODE_SET_QUEUE_FLAG(trigger);
PARAM_LOGI("Waiting to exec trigger %s", trigger->name);
ExecuteQueuePush(&g_triggerWorkSpace, trigger, triggerIndex);
return 0;
}
void ExecuteQueueWork(u_int32_t maxCount)
{
PARAM_LOGI("ExecuteQueueWork %d %d", getpid(), gettid());
u_int32_t executeCount = 0;
TriggerNode *trigger = ExecuteQueuePop(&g_triggerWorkSpace);
while (trigger != NULL) {
ExecuteTrigger(&g_triggerWorkSpace, trigger, DoCmdExecute);
TRIGGER_NODE_CLEAR_QUEUE_FLAG(trigger);
executeCount++;
if (executeCount > maxCount) {
break;
}
PARAM_LOGI("ExecuteQueueWork %u", executeCount);
trigger = ExecuteQueuePop(&g_triggerWorkSpace);
}
}
static void CheckTriggers(int type, void *content, u_int32_t contentLen)
{
switch (type) {
case EVENT_PROPERTY: {
CheckParamTrigger(&g_triggerWorkSpace, content, contentLen, DoTiggerCheckResult);
break;
}
case EVENT_BOOT: {
CheckTrigger(&g_triggerWorkSpace, TRIGGER_BOOT, content, contentLen, DoTiggerCheckResult);
break;
}
default:
PARAM_LOGI("CheckTriggers: %d", type);
break;
}
}
static void ProcessAfterEvent(uv_work_t *req, int status)
{
free(req);
ExecuteQueueWork(UINT32_MAX);
}
static void ProcessEvent(uv_work_t *req)
{
TriggerDataEvent *event = (TriggerDataEvent *)req;
CheckTriggers(event->type, event->content, event->contentSize);
}
static const char *GetCmdInfo(const char *content, u_int32_t contentSize, char **cmdParam)
{
char cmd[MAX_CMD_NAME_LEN + 1] = { 0 };
int ret = GetValueFromContent(content, contentSize, 0, cmd, sizeof(cmd));
PARAM_CHECK(ret == 0, return NULL, "Failed parse cmd");
u_int32_t cmdLen = strlen(cmd);
PARAM_CHECK(cmdLen < MAX_CMD_NAME_LEN, return NULL, "Failed parse cmd");
cmd[cmdLen] = ' ';
cmd[cmdLen + 1] = '\0';
*cmdParam = (char *)content + cmdLen + 1;
return GetMatchCmd(cmd);
}
static void SendTriggerEvent(TriggerDataEvent *event)
{
int ctrlSize = strlen(SYS_POWER_CTRL);
if (strncmp(event->content, SYS_POWER_CTRL, ctrlSize) == 0) {
char *cmdParam = NULL;
const char *matchCmd = GetCmdInfo(event->content + ctrlSize, event->contentSize - ctrlSize, &cmdParam);
if (matchCmd != NULL) {
DoCmdByName(matchCmd, cmdParam);
} else {
PARAM_LOGE("SendTriggerEvent cmd %s not found", event->content);
}
}
else if (event->type == EVENT_BOOT || g_triggerServiceStart == 0) {
CheckTriggers(event->type, event->content, event->contentSize);
ExecuteQueueWork(UINT32_MAX); // 需要立刻执行
} else {
uv_queue_work(uv_default_loop(), &event->request, ProcessEvent, ProcessAfterEvent);
event = NULL;
}
if (event != NULL) {
free(event);
}
}
void PostParamTrigger(const char *name, const char *value)
{
PARAM_CHECK(name != NULL && value != NULL, return, "Invalid param");
PARAM_LOGI("PostParamTrigger %s ", name);
int contentLen = strlen(name) + strlen(value) + 2;
TriggerDataEvent *event = (TriggerDataEvent *)malloc(sizeof(TriggerDataEvent) + contentLen);
PARAM_CHECK(event != NULL, return, "Failed to alloc memory");
event->type = EVENT_PROPERTY;
event->request.data = (char*)event + sizeof(uv_work_t);
event->contentSize = BuildParamContent(event->content, contentLen, name, value);
PARAM_CHECK(event->contentSize > 0, return, "Failed to copy porperty");
SendTriggerEvent(event);
PARAM_LOGI("PostParamTrigger %s success", name);
}
void PostTrigger(EventType type, void *content, u_int32_t contentLen)
{
PARAM_LOGI("PostTrigger %d", type);
PARAM_CHECK(content != NULL && contentLen > 0, return, "Invalid param");
TriggerDataEvent *event = (TriggerDataEvent *)malloc(sizeof(TriggerDataEvent) + contentLen + 1);
PARAM_CHECK(event != NULL, return, "Failed to alloc memory");
event->type = type;
event->request.data = (char*)event + sizeof(uv_work_t);
event->contentSize = contentLen;
memcpy_s(event->content, contentLen, content, contentLen);
event->content[contentLen] = '\0';
SendTriggerEvent(event);
PARAM_LOGI("PostTrigger %d success", type);
}
void StartTriggerService()
{
PARAM_LOGI("StartTriggerService ");
g_triggerServiceStart = 1;
}
int ParseTriggerConfig(cJSON *fileRoot)
{
PARAM_CHECK(fileRoot != NULL, return -1, "Invalid file");
int ret = InitTriggerWorkSpace(&g_triggerWorkSpace);
PARAM_CHECK(ret == 0, return -1, "Failed to init trigger");
cJSON *triggers = cJSON_GetObjectItemCaseSensitive(fileRoot, TRIGGER_ARR_NAME_IN_JSON);
PARAM_CHECK(cJSON_IsArray(triggers), return -1, "Trigger item must array");
int size = cJSON_GetArraySize(triggers);
PARAM_CHECK(size > 0, return -1, "Trigger array size must positive");
for (int i = 0; i < size; ++i) {
cJSON *item = cJSON_GetArrayItem(triggers, i);
ParseTrigger(&g_triggerWorkSpace, item);
}
return 0;
}
void DoTriggerExec(const char *content)
{
PARAM_CHECK(content != NULL, return, "Invalid trigger content");
u_int32_t triggerIndex = 0;
TriggerNode *trigger = GetTriggerByName(&g_triggerWorkSpace, content, &triggerIndex);
if (trigger != NULL && !TRIGGER_NODE_IN_QUEUE(trigger)) { // 不在队列中
PARAM_LOGI("DoTriggerExec trigger %s", trigger->name);
TRIGGER_NODE_SET_QUEUE_FLAG(trigger);
ExecuteQueuePush(&g_triggerWorkSpace, trigger, triggerIndex);
}
ExecuteQueueWork(UINT32_MAX); // 需要立刻执行
}
TriggerWorkSpace *GetTriggerWorkSpace()
{
return &g_triggerWorkSpace;
}
\ No newline at end of file
# Copyright (c) 2020 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.
import("//build/ohos.gni")
ohos_executable("reboot") {
sources = [
"init_cmd_reboot.c",
]
include_dirs = [
"//base/startup/init_lite/interfaces/innerkits/include",
"//base/startup/init_lite/services/include/param/",
"//third_party/bounds_checking_function/include",
]
deps = [
"//base/startup/init_lite/interfaces/innerkits/reboot:libreboot",
]
install_enable = true
part_name = "init"
}
/*
* 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 <stdio.h>
#include <string.h>
#include <unistd.h>
#include "init_reboot_api.h"
int main(int argc, char* argv[])
{
if (argc > 2) {
printf("usage: reboot shutdown\n reboot updater\n reboot updater[:options]\n reboot\n");
return 0;
}
if (argc == 2 && strcmp(argv[1], "shutdown") != 0 &&
strcmp(argv[1], "updater") != 0 &&
strncmp(argv[1], "updater:", strlen("updater:")) != 0 ) {
printf("usage: reboot shutdown\n reboot updater\n reboot updater[:options]\n reboot\n");
return 0;
}
int ret = 0;
if (argc == 2) {
ret = DoRebootApi(argv[1]);
} else {
ret = DoRebootApi("NoArgument");
}
if (ret != 0) {
printf("[reboot command] DoRebootApi return error\n");
} else {
printf("[reboot command] DoRebootApi return ok\n");
}
while (1) {
pause();
}
return 0;
}
......@@ -19,6 +19,8 @@
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <unistd.h>
#include "init_log.h"
#define DEFAULT_RW_MODE 0666
#define DEFAULT_NO_AUTHORITY_MODE 0600
......@@ -30,29 +32,50 @@
void MountBasicFs()
{
if (mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755") != 0) {
printf("Mount tmpfs failed. %s\n", strerror(errno));
INIT_LOGE("Mount tmpfs failed. %s\n", strerror(errno));
}
if (mount("proc", "/proc", "proc", 0, "hidepid=2") != 0) {
printf("Mount procfs failed. %s\n", strerror(errno));
INIT_LOGE("Mount procfs failed. %s\n", strerror(errno));
}
if (mount("sysfs", "/sys", "sysfs", 0, NULL) != 0) {
printf("Mount sysfs failed. %s\n", strerror(errno));
INIT_LOGE("Mount sysfs failed. %s\n", strerror(errno));
}
#ifndef __LITEOS__
if (mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL) != 0) {
INIT_LOGE("Mount selinuxfs failed. %s\n", strerror(errno));
}
#endif
}
void CreateDeviceNode()
{
if (mknod("/dev/kmsg", S_IFCHR | DEFAULT_NO_AUTHORITY_MODE, makedev(1, DEVICE_ID_ELEVNTH)) != 0) {
printf("Create /dev/kmsg device node failed. %s\n", strerror(errno));
INIT_LOGE("Create /dev/kmsg device node failed. %s\n", strerror(errno));
}
if (mknod("/dev/null", S_IFCHR | DEFAULT_RW_MODE, makedev(1, DEVICE_ID_THIRD)) != 0) {
printf("Create /dev/null device node failed. %s\n", strerror(errno));
INIT_LOGE("Create /dev/null device node failed. %s\n", strerror(errno));
}
if (mknod("/dev/random", S_IFCHR | DEFAULT_RW_MODE, makedev(1, DEVICE_ID_EIGHTH)) != 0) {
printf("Create /dev/random device node failed. %s\n", strerror(errno));
INIT_LOGE("Create /dev/random device node failed. %s\n", strerror(errno));
}
if (mknod("/dev/urandom", S_IFCHR | DEFAULT_RW_MODE, makedev(1, DEVICE_ID_NINTH)) != 0) {
printf("Create /dev/urandom device node failed. %s\n", strerror(errno));
INIT_LOGE("Create /dev/urandom device node failed. %s\n", strerror(errno));
}
}
int MakeSocketDir(const char *path, mode_t mode)
{
int rc = mkdir("/dev/unix/", mode);
if (rc < 0 && errno != EEXIST) {
INIT_LOGE("Create %s failed. %d\n", path, errno);
return -1;
}
rc = mkdir("/dev/unix/socket/", mode);
if (rc < 0 && errno != EEXIST) {
INIT_LOGE("Create %s failed. %d\n", path, errno);
return -1;
}
return rc;
}
......@@ -20,24 +20,27 @@
#include <unistd.h>
#include <sys/prctl.h>
#include <sys/reboot.h>
#ifdef __LINUX__
#if ((defined __LINUX__) || (!defined OHOS_LITE))
#include <linux/securebits.h>
#endif
#ifdef __LINUX__
#include "init_signal_handler.h"
#endif
#include "init_log.h"
void RebootSystem()
{
int ret = reboot(RB_AUTOBOOT);
if (ret != 0) {
printf("[Init] reboot failed! syscall ret %d, err %d.\n", ret, errno);
INIT_LOGE("reboot failed! syscall ret %d, err %d.\n", ret, errno);
}
}
int KeepCapability()
{
#ifdef __LINUX__
#if ((defined __LINUX__) || (!defined OHOS_LITE))
if (prctl(PR_SET_SECUREBITS, SECBIT_NO_SETUID_FIXUP | SECBIT_NO_SETUID_FIXUP_LOCKED)) {
printf("[Init] prctl failed\n");
INIT_LOGE("prctl PR_SET_SECUREBITS failed: %d\n", errno);
return -1;
}
#endif
......@@ -46,9 +49,9 @@ int KeepCapability()
int SetAmbientCapability(int cap)
{
#ifdef __LINUX__
#if ((defined __LINUX__) || (!defined OHOS_LITE))
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0)) {
printf("[Init] prctl PR_CAP_AMBIENT failed\n");
INIT_LOGE("prctl PR_CAP_AMBIENT failed: %d\n", errno);
return -1;
}
#endif
......@@ -60,15 +63,15 @@ void ExecuteRcs()
#if (defined __LINUX__) && (defined NEED_EXEC_RCS_LINUX)
pid_t retPid = fork();
if (retPid < 0) {
printf("[Init] ExecuteRcs, fork failed! err %d.\n", errno);
INIT_LOGE("ExecuteRcs, fork failed! err %d.\n", errno);
return;
}
// child process
if (retPid == 0) {
printf("[Init] ExecuteRcs, child process id %d.\n", getpid());
INIT_LOGI("ExecuteRcs, child process id %d.\n", getpid());
if (execle("/bin/sh", "sh", "/etc/init.d/rcS", NULL, NULL) != 0) {
printf("[Init] ExecuteRcs, execle failed! err %d.\n", errno);
INIT_LOGE("ExecuteRcs, execle failed! err %d.\n", errno);
}
_exit(0x7f); // 0x7f: user specified
}
......@@ -76,14 +79,14 @@ void ExecuteRcs()
// init process
sem_t sem;
if (sem_init(&sem, 0, 0) != 0) {
printf("[Init] ExecuteRcs, sem_init failed, err %d.\n", errno);
INIT_LOGE("ExecuteRcs, sem_init failed, err %d.\n", errno);
return;
}
SignalRegWaitSem(retPid, &sem);
// wait until rcs process exited
if (sem_wait(&sem) != 0) {
printf("[Init] ExecuteRcs, sem_wait failed, err %d.\n", errno);
INIT_LOGE("ExecuteRcs, sem_wait failed, err %d.\n", errno);
}
#endif
}
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
文件模式从 100755 更改为 100644
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册