提交 2b19a1cf 编写于 作者: Z zhong_ning

modify for l2 init

上级 2a43725c
/*
* 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("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;
}
printf("GetControlFromEnv path is %s \n", path);
const char *val = getenv(path);
if (val == NULL) {
printf("test GetControlFromEnv val is null %d\n", errno);
return -1;
}
errno = 0;
int fd = strtol(val, NULL, N_DEC);
if (errno) {
return -1;
}
printf("test GetControlFromEnv fd is %d \n", fd);
if (fcntl(fd, F_GETFD) < 0) {
printf("test 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);
printf("test GetControlSocket path is %s \n", path);
int fd = GetControlFromEnv(path);
if (fd < 0) {
printf("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) {
printf("test GetControlSocket errno %d \n", errno);
return -1;
}
char sockDir[MAX_SOCKET_DIR_LEN] = {0};
snprintf(sockDir, sizeof(sockDir), OHOS_SOCKET_DIR"/%s", name);
printf("test sockDir %s \n", sockDir);
printf("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"
]
}
}
}
......@@ -25,12 +25,17 @@ if (defined(ohos_lite)) {
"src/init_read_cfg.c",
"src/init_service.c",
"src/init_service_manager.c",
"src/init_import.c",
"src/init_signal_handler.c",
"src/init_utils.c",
"src/init_service_socket.c",
"src/main.c",
"src/init_capability.c",
]
include_dirs = [
"include",
"//base/startup/init_lite/services/include",
"//base/startup/init_lite/services/property/include",
"//third_party/cJSON",
"//third_party/bounds_checking_function/include",
"//base/startup/syspara_lite/interfaces/kits",
......@@ -74,7 +79,6 @@ if (defined(ohos_lite)) {
}
} else {
import("//build/ohos.gni")
ohos_executable("updaterueventd") {
sources = [
"src/list.c",
......@@ -86,37 +90,66 @@ if (defined(ohos_lite)) {
]
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_cmds.c",
"src/init_jobs.c",
"src/init_log.c",
"src/init_read_cfg.c",
"src/init_service.c",
"src/init_service_manager.c",
"src/init_import.c",
"src/init_signal_handler.c",
"src/init_utils.c",
"src/init_service_socket.c",
"src/main.c",
"src/init_capability.c",
]
include_dirs = [
"include",
"//base/startup/init_lite/services/include/property",
"//base/startup/init_lite/services/include/trigger",
"//base/startup/init_lite/services/include",
"//base/startup/init_lite/services/property/include",
"//third_party/cJSON",
"//third_party/bounds_checking_function/include",
]
deps = [
"//base/startup/init_lite/services/property:propertyserver",
"//base/startup/init_lite/services/property:propertyclient",
"//base/startup/init_lite/services/trigger:triggerservice",
"//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.cfg",
":init",
":updaterueventd",
"//base/startup/init_lite/services/trigger:triggerservice",
"//base/startup/init_lite/services/property:propertyserver",
"//base/startup/init_lite/services/property:propertyclient",
"//base/startup/init_lite/services/property:setparam",
"//base/startup/init_lite/services/property:getparam"
]
}
}
......@@ -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
#ifdef OHOS_LITE
#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
......@@ -23,9 +23,10 @@ extern "C" {
#endif
#define MAX_CMD_NAME_LEN 10
#define MAX_CMD_CONTENT_LEN 128
#define MAX_CMD_CNT_IN_ONE_JOB 30
#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
}
......
/*
* 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>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef enum StatupLogLevel {
STARTUP_DEBUG = 0,
STARTUP_INFO,
STARTUP_WARN,
STARTUP_ERROR,
STARTUP_FATAL
} StatupLogLevel;
#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_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__)
void InitLog(int logLevel, const char *fileName, int line, const char *fmt, ...);
void Logger(StatupLogLevel 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"};
StatupLogLevel level_;
int JudgeLevel(const StatupLogLevel level) { return return; }
#define STARTUP_LOG(LEVEL, LABEL, Level, fmt, ...) \
Logger(__FILE_NAME__, (__LINE__), fmt, ##__VA_ARGS__); \
if (JudgeLevel(StatupLogLevel::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][%s:%d] " fmt "\n", LABEL, __FILE_NAME__, __LINE__, ##__VA_ARGS__);
#endif
#define STARTUP_LOGI(LABEL, fmt, ...) STARTUP_LOG(STARTUP_INFO, LABEL, Info, fmt, ##__VA_ARGS__)
#define STARTUP_LOGE(LABEL, fmt, ...) STARTUP_LOG(STARTUP_ERROR, LABEL, Error, fmt, ##__VA_ARGS__)
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // INIT_LOG_H
......@@ -22,9 +22,12 @@ extern "C" {
#endif
#endif
#define INIT_CONFIGURATION_FILE "/etc/init.cfg"
#define INIT_CONFIGURATION_FILE "/init.cfg"
#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
......
......@@ -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,23 @@ 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 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_PROPERTY_H
#define BASE_STARTUP_PROPERTY_H
#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#define PROPERTY_VALUE_LEN_MAX 96
typedef u_int32_t PropertyHandle;
typedef struct {
u_int32_t serial;
PropertyHandle handle;
char value[PROPERTY_VALUE_LEN_MAX];
} PropertyCacheNode;
typedef const char *(*PropertyEvaluatePtr)(u_int32_t cacheCount, PropertyCacheNode *node);
typedef struct {
pthread_mutex_t lock;
u_int32_t serial;
u_int32_t cacheCount;
PropertyEvaluatePtr evaluate;
PropertyCacheNode *cacheNode;
} PropertyCache;
/**
* 对外接口
* 设置属性,主要用于其他进程使用,通过管道修改属性。
*
*/
int SystemSetParameter(const char *name, const char *value);
/**
* 对外接口
* 查询属性,主要用于其他进程使用,需要给定足够的内存保存属性。
* 如果 value == null,获取value的长度
* 否则value的大小认为是len
*
*/
int SystemGetParameter(const char *name, char *value, unsigned int *len);
/**
* 对外接口
* 查询属性,主要用于其他进程使用,需要给定足够的内存保存属性。
* 如果 value == null,获取value的长度
* 否则value的大小认为是len
*
*/
int SystemGetParameterName(PropertyHandle handle, char *name, unsigned int len);
/**
* 对外接口
* 遍历所有属性。
*
*/
int SystemTraversalParameter(void (*traversalParameter)(PropertyHandle handle, void* cookie), void* cookie);
/**
* 对外接口
* 获取属性值。
*
*/
int SystemGetParameterValue(PropertyHandle handle, char *value, unsigned int *len);
#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_TRIGER_H
#define BASE_STARTUP_TRIGER_H
#include <stdio.h>
#include "cJSON.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef enum {
EVENT_PROPERTY, // 属性修改事件
EVENT_BOOT
} EventType;
void PostTrigger(EventType type, void *content, u_int32_t contentLen);
void PostPropertyTrigger(const char *name, const char *value);
void StartTriggerService();
int ParseTriggerConfig(cJSON *fileRoot);
void DoTriggerExec(const char *content);
#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.
import("//build/ohos.gni")
ohos_static_library("propertyserver") {
sources = [
"manager/property_manager.c",
"manager/property_trie.c",
"manager/property_cache.c",
"service/property_service.c",
"service/property_persist.c",
"//base/startup/init_lite/services/src/init_utils.c",
]
include_dirs = [
"include",
"//base/startup/init_lite/services/include/property",
"//base/startup/init_lite/services/include/trigger",
"//base/startup/init_lite/services/include",
"//third_party/libuv/include",
"//third_party/cJSON",
]
deps = [
"//third_party/libuv:uv_static",
"//base/startup/init_lite/services/trigger:triggerservice",
"//third_party/bounds_checking_function:libsec_static",
]
part_name = "init"
subsystem_name = "startup"
}
ohos_static_library("propertyclient") {
sources = [
"manager/property_manager.c",
"client/property_request.c",
"manager/property_trie.c",
"manager/property_cache.c",
"//base/startup/init_lite/services/src/init_utils.c",
]
include_dirs = [
"include",
"//base/startup/init_lite/services/include/property",
"//base/startup/init_lite/services/include/trigger",
"//base/startup/init_lite/services/include",
"//third_party/libuv/include",
"//third_party/cJSON",
]
deps = [
"//third_party/libuv:uv_static",
"//third_party/bounds_checking_function:libsec_static",
]
part_name = "init"
subsystem_name = "startup"
}
ohos_executable("getparam") {
sources = [
"cmd/property_get.c",
]
include_dirs = [
"include",
"//base/startup/init_lite/services/include/property",
"//base/startup/init_lite/services/include/trigger",
"//base/startup/init_lite/services/include",
]
deps = [
"//base/startup/init_lite/services/property:propertyclient",
"//third_party/bounds_checking_function:libsec_static",
"//third_party/cJSON:cjson_static",
]
install_enable = true
part_name = "init"
}
ohos_executable("setparam") {
sources = [
"cmd/property_set.c",
]
include_dirs = [
"include",
"//base/startup/init_lite/services/include/property",
"//base/startup/init_lite/services/include/trigger",
"//base/startup/init_lite/services/include",
]
deps = [
"//base/startup/init_lite/services/property:propertyclient",
"//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 "property_request.h"
#include <string.h>
#include <unistd.h>
#include <time.h>
#include "property_manager.h"
#include "uv.h"
#define LABEL "Client"
#define BUFFER_SIZE 200
#define PropertyEntry(ptr, type, member) (type *)((char *)(ptr) - offsetof(type, member))
static PropertyWorkSpace g_propertyWorkSpaceReadOnly = {ATOMIC_VAR_INIT(0), {}, {}, {}};
static void OnWrite(uv_write_t* req, int status)
{
PROPERTY_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 = suggestedSize;
PROPERTY_LOGI("OnReceiveAlloc handle %p %zu", handle, suggestedSize);
}
static void OnReceiveResponse(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
{
RequestNode *req = PropertyEntry(handle, RequestNode, handle);
PROPERTY_LOGI("OnReceiveResponse %p", handle);
if (nread <= 0 || buf == NULL || buf->base == NULL) {
free(buf->base);
uv_close((uv_handle_t*)handle, NULL);
uv_stop(req->loop);
return;
}
ResponseMsg *response = (ResponseMsg *)(buf->base);
PROPERTY_CHECK(response != NULL, return, "The response is null");
PROPERTY_LOGI("OnReceiveResponse %p cmd %d result: %d", handle, response->type, response->result);
switch (response->type) {
case SET_PROPERTY:
req->result = response->result;
break;
default:
PROPERTY_LOGE("not supported the command: %d", response->type);
break;
}
PROPERTY_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)
{
PROPERTY_CHECK(status >= 0, return, "Failed to conntect status %s", uv_strerror(status));
uv_write_t wr;
RequestNode *request = PropertyEntry(connect, RequestNode, connect);
PROPERTY_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(&wr, (uv_stream_t*)&(request->handle), &buf, 1, (uv_stream_t*)&(request->handle), OnWrite);
PROPERTY_CHECK(ret >= 0, return, "Failed to uv_write2 porperty");
// read result
ret = uv_read_start((uv_stream_t*)&(request->handle), OnReceiveAlloc, OnReceiveResponse);
PROPERTY_CHECK(ret >= 0, return, "Failed to uv_read_start response");
}
static int StartRequest(int cmd, RequestNode *request)
{
PROPERTY_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);
int result = request->result;
free(request);
return result;
}
int SystemSetParameter(const char *name, const char *value)
{
PROPERTY_CHECK(name != NULL && value != NULL, return -1, "Invalid param");
int ret = CheckPropertyName(name, 0);
PROPERTY_CHECK(ret == 0, return ret, "Illegal property name");
PROPERTY_LOGI("StartRequest %s", name);
u_int32_t msgSize = sizeof(RequestMsg) + strlen(name) + strlen(value) + 2;
RequestNode *request = (RequestNode *)malloc(sizeof(RequestNode) + msgSize);
PROPERTY_CHECK(request != NULL, return -1, "Failed to malloc for connect");
// 带字符串结束符
int contentSize = BuildPropertyContent(request->msg.content, msgSize - sizeof(RequestMsg), name, value);
PROPERTY_CHECK(contentSize > 0, return -1, "Failed to copy porperty");
request->msg.contentSize = contentSize;
return StartRequest(SET_PROPERTY, request);
}
int SystemGetParameter(const char *name, char *value, unsigned int *len)
{
PROPERTY_CHECK(name != NULL && len != NULL, return -1, "The name or value is null");
InitPropertyWorkSpace(&g_propertyWorkSpaceReadOnly, 1, NULL);
PropertyHandle handle = 0;
int ret = ReadPropertyWithCheck(&g_propertyWorkSpaceReadOnly, name, &handle);
PROPERTY_CHECK(ret == 0, return ret, "Can not get param for %s", name);
return ReadPropertyValue(&g_propertyWorkSpaceReadOnly, handle, value, len);
}
int SystemGetParameterName(PropertyHandle handle, char *name, unsigned int len)
{
PROPERTY_CHECK(name != NULL && handle != 0, return -1, "The name is null");
InitPropertyWorkSpace(&g_propertyWorkSpaceReadOnly, 1, NULL);
return ReadPropertyName(&g_propertyWorkSpaceReadOnly, handle, name, len);
}
int SystemGetParameterValue(PropertyHandle handle, char *value, unsigned int *len)
{
PROPERTY_CHECK(len != NULL && handle != 0, return -1, "The value is null");
InitPropertyWorkSpace(&g_propertyWorkSpaceReadOnly, 1, NULL);
return ReadPropertyValue(&g_propertyWorkSpaceReadOnly, handle, value, len);
}
int SystemTraversalParameter(void (*traversalParameter)(PropertyHandle handle, void* cookie), void* cookie)
{
PROPERTY_CHECK(traversalParameter != NULL, return -1, "The param is null");
InitPropertyWorkSpace(&g_propertyWorkSpaceReadOnly, 1, NULL);
return TraversalProperty(&g_propertyWorkSpaceReadOnly, traversalParameter, cookie);
}
const char *SystemDetectPropertyChange(PropertyCache *cache,
PropertyEvaluatePtr evaluate, u_int32_t count, const char *properties[][2])
{
PROPERTY_CHECK(cache != NULL && evaluate != NULL && properties != NULL, return NULL, "The param is null");
return DetectPropertyChange(&g_propertyWorkSpaceReadOnly, cache, evaluate, count, properties);
}
/*
* 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 "property.h"
#define HELP_PARAM "--help"
#define BUFFER_SIZE 256
static void ProcessParam(PropertyHandle 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: getprop NAME VALUE\n");
return 0;
}
if (argc != 2) {
printf("usage: getprop 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("getparm %s %s \n", argv[1], value);
} else {
printf("getparm %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 "property.h"
#define HELP_PARAM "--help"
int main(int argc, char* argv[])
{
if (argc == 1 || argc > 3) {
printf("setparm: Need 2 arguments (see \"setparm --help\")\n");
return 0;
}
if (argc == 2 && strncmp(argv[1], HELP_PARAM, strlen(HELP_PARAM)) == 0) {
printf("usage: setprop NAME VALUE\n");
return 0;
}
int ret = SystemSetParameter(argv[1], argv[2]);
if (ret == 0) {
printf("setparm %s %s success\n", argv[1], argv[2]);
} else {
printf("setparm %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_PROPERTY_MANAGER_H
#define BASE_STARTUP_PROPERTY_MANAGER_H
#include <stdio.h>
#include <string.h>
#include "init_log.h"
#include "property.h"
#include "property_trie.h"
#include "securec.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef enum {
PROPERTY_CODE_INVALID_PARAM = 100,
PROPERTY_CODE_INVALID_NAME,
PROPERTY_CODE_INVALID_VALUE,
PROPERTY_CODE_REACHED_MAX,
PROPERTY_CODE_PERMISSION_DENIED,
PROPERTY_CODE_READ_ONLY_PROPERTY,
PROPERTY_CODE_NOT_SUPPORT,
PROPERTY_CODE_ERROR_MAP_FILE,
PROPERTY_CODE_NOT_FOUND_PROP,
PROPERTY_CODE_NOT_INIT
} PROPERTY_CODE;
#define IS_READY_ONLY(name) strncmp((name), "ro.", strlen("ro.")) == 0
#define LABEL_STRING_LEN 128
#ifdef STARTUP_LOCAL
#define PIPE_NAME "/tmp/propertyservice.sock"
#define PROPERTY_STORAGE_PATH "/media/sf_ubuntu/test/__properties__/property_storage"
#define PROPERTY_PERSIST_PATH "/media/sf_ubuntu/test/property/persist_properties.property"
#define PROPERTY_INFO_PATH "/media/sf_ubuntu/test/__properties__/property_info"
#else
#define PIPE_NAME "/dev/unix/socket/PropertyService"
#define PROPERTY_STORAGE_PATH "/dev/__properties__/property_storage"
#define PROPERTY_PERSIST_PATH "/data/property/persist_properties.property"
#define PROPERTY_INFO_PATH "/dev/__properties__/property_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 PROPERTY_LOGI(fmt, ...) STARTUP_LOGI(LABEL, fmt, ##__VA_ARGS__)
#define PROPERTY_LOGE(fmt, ...) STARTUP_LOGE(LABEL, fmt, ##__VA_ARGS__)
#define PROPERTY_CHECK(retCode, exper, ...) \
if (!(retCode)) { \
PROPERTY_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;
} PropertySecurityLabel;
typedef struct PropertyAuditData {
const UserCred *cr;
const char *name;
} PropertyAuditData;
typedef struct {
atomic_uint_least32_t flags;
WorkSpace propertyLabelSpace;
WorkSpace propertySpace;
PropertySecurityLabel label;
} PropertyWorkSpace;
typedef struct {
atomic_uint_least32_t flags;
WorkSpace persistWorkSpace;
} PropertyPersistWorkSpace;
typedef struct {
char value[128];
} SubStringInfo;
int InitPropertyWorkSpace(PropertyWorkSpace *workSpace, int onlyRead, const char *context);
void ClosePropertyWorkSpace(PropertyWorkSpace *workSpace);
int ReadPropertyWithCheck(PropertyWorkSpace *workSpace, const char *name, PropertyHandle *handle);
int ReadPropertyValue(PropertyWorkSpace *workSpace, PropertyHandle handle, char *value, u_int32_t *len);
int ReadPropertyName(PropertyWorkSpace *workSpace, PropertyHandle handle, char *name, u_int32_t len);
u_int32_t ReadPropertySerial(PropertyWorkSpace *workSpace, PropertyHandle handle);
int AddProperty(WorkSpace *workSpace, const char *name, const char *value);
int WriteProperty(WorkSpace *workSpace, const char *name, const char *value);
int WritePropertyWithCheck(PropertyWorkSpace *workSpace,
const PropertySecurityLabel *srcLabel, const char *name, const char *value);
int WritePropertyInfo(PropertyWorkSpace *workSpace, SubStringInfo *info, int subStrNumber);
int CheckPropertyValue(WorkSpace *workSpace, const TrieDataNode *node, const char *name, const char *value);
int CheckPropertyName(const char *name, int propInfo);
int CanReadProperty(PropertyWorkSpace *workSpace, u_int32_t labelIndex, const char *name);
int CanWriteProperty(PropertyWorkSpace *workSpace,
const PropertySecurityLabel *srcLabel, const TrieDataNode *node, const char *name, const char *value);
int CheckMacPerms(PropertyWorkSpace *workSpace,
const PropertySecurityLabel *srcLabel, const char *name, u_int32_t labelIndex);
int CheckControlPropertyPerms(PropertyWorkSpace *workSpace,
const PropertySecurityLabel *srcLabel, const char *name, const char *value);
int GetSubStringInfo(const char *buff, u_int32_t buffLen, char delimiter, SubStringInfo *info, int subStrNumber);
int BuildPropertyContent(char *content, u_int32_t contentSize, const char *name, const char *value);
PropertyWorkSpace *GetPropertyWorkSpace();
typedef void (*TraversalParamPtr)(PropertyHandle handle, void* context);
typedef struct {
TraversalParamPtr traversalParamPtr;
void *context;
} PropertyTraversalContext;
int TraversalProperty(PropertyWorkSpace *workSpace, TraversalParamPtr walkFunc, void *cookie);
int InitPersistPropertyWorkSpace(const char *context);
int RefreshPersistProperties(PropertyWorkSpace *workSpace, const char *context);
void ClosePersistPropertyWorkSpace();
int WritePersistProperty(const char *name, const char *value);
const char *DetectPropertyChange(PropertyWorkSpace *workSpace, PropertyCache *cache,
PropertyEvaluatePtr evaluate, u_int32_t count, const char *properties[][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_PROPERTY_REQUEST_H
#define BASE_STARTUP_PROPERTY_REQUEST_H
#include <stdio.h>
#include "property.h"
#include "property_manager.h"
#include "uv.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef enum RequestType {
SET_PROPERTY,
GET_PROPERTY,
} RequestType;
typedef struct {
PropertySecurityLabel 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;
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_PROPERTY_SERVICE_H
#define BASE_STARTUP_PROPERTY_SERVICE_H
#include <stdio.h>
#include "property.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
/**
* Init 接口
* 初始化属性服务
*
*/
void InitPropertyService();
/**
* Init 接口
* 加载默认的属性值
*
*/
int LoadDefaultProperty(const char *fileName);
/**
* Init 接口
* 安全使用,加载属性的信息,包括selinux label 等
*
*/
int LoadPropertyInfo(const char *fileName);
/**
* Init 接口
* 启动属性服务,在main启动的最后调用,阻赛当前线程
*
*/
int StartPropertyService();
/**
* Init 接口
* 设置属性,主要用于其他进程使用,通过管道修改属性
*
*/
int SystemWriteParameter(const char *name, const char *value);
/**
* Init 接口
* 查询属性。
*
*/
int SystemReadParameter(const char *name, char *value, unsigned int *len);
/**
* Init 接口
* 遍历属性。
*
*/
int SystemTraversalParameters(void (*traversalParameter)(PropertyHandle handle, void* cookie), void* cookie);
/**
* Init 接口
* 加载默认属性。
*
*/
int LoadPersistProperties();
#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_PROPERTY_TRIE_H
#define BASE_STARTUP_PROPERTY_TRIE_H
#include <linux/futex.h>
#include <stdatomic.h>
#include <stdio.h>
#include <string.h>
#include <sys/syscall.h>
#include "init_log.h"
#include "property.h"
#include "securec.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#define PROPERTY_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_PROPERTY_TRIE_H
\ 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 "property.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 "property_manager.h"
#define LABEL "Manager"
#define MAX_PROPERT_IN_WATCH 5
#define NORMAL_MEMORY_FOR_PROPERTY_CACHE 4 * 1024
static WorkSpace g_workSpace;
static pthread_mutex_t cacheLock = PTHREAD_MUTEX_INITIALIZER;
static int InitNormalMemory(WorkSpace *workSpace, u_int32_t spaceSize)
{
PROPERTY_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);
PROPERTY_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);
PROPERTY_LOGI("InitNormalMemory success, currOffset %u firstNode %u dataSize %u",
workSpace->area->currOffset, workSpace->area->firstNode, workSpace->area->dataSize);
return 0;
}
static PropertyCacheNode *AllocPropertyCacheNode(WorkSpace *workSpace, u_int32_t size)
{
PROPERTY_CHECK(workSpace != NULL, return 0, "Invalid param");
PROPERTY_CHECK((workSpace->area->currOffset + size) < workSpace->area->dataSize, return 0,
"Failed to allocate currOffset %d, dataSize %d", workSpace->area->currOffset, workSpace->area->dataSize);
PropertyCacheNode *cache = (PropertyCacheNode *)(workSpace->area->data + workSpace->area->currOffset);
workSpace->area->currOffset += size;
return cache;
}
static int CreatePropertyCache(PropertyCache *cache, PropertyWorkSpace *workSpace, PropertyEvaluatePtr evaluate)
{
PROPERTY_CHECK(cache != NULL && evaluate != NULL, return -1, "Invalid param");
if (cache->cacheNode != NULL) {
return 0;
}
int ret = InitNormalMemory(&g_workSpace, NORMAL_MEMORY_FOR_PROPERTY_CACHE);
PROPERTY_CHECK(ret == 0, return -1, "Failed to init normal memory");
pthread_mutex_init(&cache->lock, NULL);
cache->serial = GetWorkSpaceSerial(&workSpace->propertySpace);
cache->cacheCount = 0;
cache->evaluate = evaluate;
cache->cacheNode = (PropertyCacheNode *)AllocPropertyCacheNode(&g_workSpace,
sizeof(PropertyCache) * MAX_PROPERT_IN_WATCH);
PROPERTY_CHECK(cache->cacheNode != NULL, return -1, "Failed to malloc memory");
return 0;
}
static int AddPropertyNode(PropertyCache *cache, PropertyWorkSpace *workSpace, const char *name, const char *defValue)
{
PROPERTY_CHECK(cache != NULL && name != NULL, return -1, "Invalid param");
PROPERTY_CHECK(cache->cacheCount < MAX_PROPERT_IN_WATCH, return -1, "Full property in cache");
PropertyCacheNode *cacheNode = &cache->cacheNode[cache->cacheCount++];
int ret = memcpy_s(cacheNode->value, sizeof(cacheNode->value), defValue, strlen(defValue));
PROPERTY_CHECK(ret == 0, return -1, "Failed to copy default value");
ret = ReadPropertyWithCheck(workSpace, name, &cacheNode->handle);
PROPERTY_CHECK(ret == 0, return -1, "Failed to read property");
cacheNode->serial = ReadPropertySerial(workSpace, cacheNode->handle);
return ret;
}
static int CheckCacheNode(PropertyWorkSpace *workSpace, PropertyCacheNode *cacheNode)
{
return cacheNode && ReadPropertySerial(workSpace, cacheNode->handle) != cacheNode->serial;
}
static void RefreshCacheNode(PropertyWorkSpace *workSpace, PropertyCacheNode *cacheNode)
{
cacheNode->serial = ReadPropertySerial(workSpace, cacheNode->handle);
u_int32_t len = sizeof(cacheNode->value);
ReadPropertyValue(workSpace, cacheNode->handle, cacheNode->value, &len);
}
static const char *TestPropertyCache(PropertyCache *cache, PropertyWorkSpace *workSpace)
{
int changeDetected;
if (pthread_mutex_trylock(&cache->lock)) {
return cache->evaluate(cache->cacheCount, cache->cacheNode);
}
if (GetWorkSpaceSerial(&workSpace->propertySpace) != 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->propertySpace);
}
pthread_mutex_unlock(&cache->lock);
return cache->evaluate(cache->cacheCount, cache->cacheNode);
}
const char *DetectPropertyChange(PropertyWorkSpace *workSpace, PropertyCache *cache,
PropertyEvaluatePtr evaluate, u_int32_t count, const char *properties[][2])
{
pthread_mutex_lock(&cacheLock);
while (cache->cacheCount == 0) {
int ret = CreatePropertyCache(cache, workSpace, evaluate);
PROPERTY_CHECK(ret == 0, break, "Failed to create cache");
for (u_int32_t i = 0; i < count; i++) {
ret = AddPropertyNode(cache, workSpace, properties[i][0], properties[i][1]);
PROPERTY_CHECK(ret == 0, break, "Failed to add property cache");
}
PROPERTY_CHECK(ret == 0, break, "Failed to add property cache");
}
pthread_mutex_unlock(&cacheLock);
return TestPropertyCache(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 "property.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 "property_manager.h"
#include "property_trie.h"
#define LABEL "Manager"
#define MAX_BUFF 256
typedef struct {
WorkSpace *workSpace;
WorkSpace *persistWorkSpace;
char *buffer;
} PersistContext;
static PropertyPersistWorkSpace g_persistWorkSpace = {ATOMIC_VAR_INIT(0), };
static int ProcessPropertTraversal(WorkSpace *workSpace, TrieNode *node, void *cookie)
{
PROPERTY_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) { // 只支持新建
PROPERTY_LOGI("Insert new persist property from normal property %s", persistContext->buffer);
ret = AddProperty(persistContext->persistWorkSpace, persistContext->buffer, persistContext->buffer + MAX_BUFF);
}
PROPERTY_CHECK(ret == 0, return ret, "Failed to add persist property");
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) {
PROPERTY_LOGI("update normal property %s %s from persist property ",
persistContext->buffer, persistContext->buffer + MAX_BUFF);
ret = WriteProperty(persistContext->workSpace, persistContext->buffer, persistContext->buffer + MAX_BUFF);
}
PROPERTY_CHECK(ret == 0, return ret, "Failed to add persist property");
return ret;
}
int InitPersistPropertyWorkSpace(const char *context)
{
u_int32_t flags = atomic_load_explicit(&g_persistWorkSpace.flags, memory_order_relaxed);
PROPERTY_LOGI("InitPersistPropertyWorkSpace flags %x", flags);
if ((flags & WORKSPACE_FLAGS_INIT) == WORKSPACE_FLAGS_INIT) {
return 0;
}
g_persistWorkSpace.persistWorkSpace.compareTrieNode = CompareTrieDataNode;
g_persistWorkSpace.persistWorkSpace.allocTrieNode = AllocateTrieDataNode;
int ret = InitPersistWorkSpace(PROPERTY_PERSIST_PATH, &g_persistWorkSpace.persistWorkSpace);
atomic_store_explicit(&g_persistWorkSpace.flags, WORKSPACE_FLAGS_INIT, memory_order_release);
return ret;
}
int RefreshPersistProperties(PropertyWorkSpace *workSpace, const char *context)
{
u_int32_t flags = atomic_load_explicit(&g_persistWorkSpace.flags, memory_order_relaxed);
if ((flags & WORKSPACE_FLAGS_INIT) != WORKSPACE_FLAGS_INIT) {
int ret = InitPersistPropertyWorkSpace(context);
PROPERTY_CHECK(ret == 0, return ret, "Failed to init persist property");
flags = atomic_load_explicit(&g_persistWorkSpace.flags, memory_order_relaxed);
}
if ((flags & WORKSPACE_FLAGS_LOADED) == WORKSPACE_FLAGS_LOADED) {
return 0;
}
// 申请临时的缓存,用于数据读取
char *buffer = (char *)malloc(MAX_BUFF + MAX_BUFF);
PROPERTY_CHECK(buffer != NULL, return -1, "Failed to malloc memory for property");
PersistContext persistContext = {
&workSpace->propertySpace, &g_persistWorkSpace.persistWorkSpace, buffer
};
// 遍历当前的属性,并把persist的写入
int ret = TraversalTrieDataNode(&workSpace->propertySpace,
(TrieDataNode *)workSpace->propertySpace.rootNode, ProcessPropertTraversal, &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 ClosePersistPropertyWorkSpace()
{
CloseWorkSpace(&g_persistWorkSpace.persistWorkSpace);
atomic_store_explicit(&g_persistWorkSpace.flags, 0, memory_order_release);
}
int WritePersistProperty(const char *name, const char *value)
{
PROPERTY_CHECK(value != NULL && name != NULL, return PROPERTY_CODE_INVALID_PARAM, "Invalid param");
u_int32_t flags = atomic_load_explicit(&g_persistWorkSpace.flags, memory_order_relaxed);
if ((flags & WORKSPACE_FLAGS_LOADED) != WORKSPACE_FLAGS_LOADED) {
return 0;
}
if (strncmp(name, "persist.", strlen("persist.")) != 0) {
return 0;
}
return WriteProperty(&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 "property_service.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "property.h"
#include "property_manager.h"
#include "property_request.h"
#include "trigger.h"
#include "uv.h"
#define BUFFER_SIZE 256
#define LABEL "Server"
static char *g_initContext = "";
static PropertyWorkSpace g_propertyWorkSpace = {ATOMIC_VAR_INIT(0), {}, {}, {}};
void InitPropertyService()
{
int ret = InitPropertyWorkSpace(&g_propertyWorkSpace, 0, g_initContext);
PROPERTY_CHECK(ret == 0, return, "Init propert workspace fail");
}
int LoadDefaultProperty(const char *fileName)
{
u_int32_t flags = atomic_load_explicit(&g_propertyWorkSpace.flags, memory_order_relaxed);
if ((flags & WORKSPACE_FLAGS_INIT) != WORKSPACE_FLAGS_INIT) {
return PROPERTY_CODE_NOT_INIT;
}
FILE *fp = fopen(fileName, "r");
PROPERTY_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), '\n', info, SUBSTR_INFO_LABEL + 1);
if (subStrNumber <= SUBSTR_INFO_LABEL) {
continue;
}
if (strncmp(info[0].value, "ctl.", strlen("ctl.")) == 0) {
PROPERTY_LOGE("Do not set ctl. properties from init %s", info[0].value);
continue;
}
if (strcmp(info[0].value, "selinux.restorecon_recursive") == 0) {
PROPERTY_LOGE("Do not set selinux.restorecon_recursive from init %s", info[0].value);
continue;
}
int ret = CheckPropertyName(info[0].value, 0);
PROPERTY_CHECK(ret == 0, continue, "Illegal property name %s", info[0].value);
ret = WriteProperty(&g_propertyWorkSpace.propertySpace, info[0].value, info[1].value);
PROPERTY_CHECK(ret == 0, continue, "Failed to set property %d %s", ret, buff);
ret = WritePersistProperty(info[0].value, info[1].value);
PROPERTY_CHECK(ret == 0, continue, "Failed to set persist property %d %s", ret, buff);
}
fclose(fp);
free(info);
PROPERTY_LOGI("LoadDefaultProperty proterty success %s", fileName);
return 0;
}
int LoadPropertyInfo(const char *fileName)
{
u_int32_t flags = atomic_load_explicit(&g_propertyWorkSpace.flags, memory_order_relaxed);
if ((flags & WORKSPACE_FLAGS_INIT) != WORKSPACE_FLAGS_INIT) {
return PROPERTY_CODE_NOT_INIT;
}
FILE *fp = fopen(fileName, "r");
PROPERTY_CHECK(fp != NULL, return -1, "Open file %s fail", fileName);
SubStringInfo *info = malloc(sizeof(SubStringInfo) * SUBSTR_INFO_MAX);
char buff[BUFFER_SIZE];
int propInfoCount = 0;
while(fgets(buff, BUFFER_SIZE, fp) != NULL) {
int subStrNumber = GetSubStringInfo(buff, strlen(buff), ' ', info, SUBSTR_INFO_MAX);
if (subStrNumber <= 0) {
continue;
}
int ret = WritePropertyInfo(&g_propertyWorkSpace, info, subStrNumber);
PROPERTY_CHECK(ret == 0, continue, "Failed to write property info %d %s", ret, buff);
propInfoCount++;
}
fclose(fp);
free(info);
PROPERTY_LOGI("Load proterty info %d success %s", propInfoCount, fileName);
return 0;
}
static int ProcessPropertySet(RequestMsg *msg)
{
PROPERTY_CHECK(msg != NULL, return PROPERTY_CODE_INVALID_PARAM, "Failed to check param");
SubStringInfo info[3];
int ret = GetSubStringInfo(msg->content, msg->contentSize, '=', info, sizeof(info)/sizeof(info[0]));
PROPERTY_CHECK(ret >= 2, return ret, "Failed to get name from content %s", msg->content);
PROPERTY_LOGI("ProcessPropertySet name %s value: %s", info[0].value, info[1].value);
ret = WritePropertyWithCheck(&g_propertyWorkSpace, &msg->securitylabel, info[0].value, info[1].value);
PROPERTY_CHECK(ret == 0, return ret, "Failed to set property %d name %s %s", ret, info[0].value, info[1].value);
ret = WritePersistProperty(info[0].value, info[1].value);
PROPERTY_CHECK(ret == 0, return ret, "Failed to set property");
// 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->base = (char *)malloc(sizeof(RequestMsg) + BUFFER_SIZE * 2);
buf->len = suggestedSize;
}
static void OnWriteResponse(uv_write_t *req, int status)
{
// 发送成功,释放请求内存
PROPERTY_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);
PROPERTY_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);
PROPERTY_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);
PROPERTY_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_PROPERTY: {
freeHandle = 0;
int ret = ProcessPropertySet(msg);
SendResponse(handle, SET_PROPERTY, ret, NULL, 0);
break;
}
default:
PROPERTY_LOGE("not supported the command: %d", msg->type);
break;
}
free(buf->base);
uv_close((uv_handle_t*)handle, OnClose);
}
static void RemoveSocket(int sig)
{
uv_fs_t req;
uv_fs_unlink(uv_default_loop(), &req, PIPE_NAME, NULL);
ClosePropertyWorkSpace(&g_propertyWorkSpace);
ClosePersistPropertyWorkSpace();
uv_stop(uv_default_loop());
exit(0);
}
static void OnConnection(uv_stream_t *server, int status)
{
PROPERTY_CHECK(status >= 0, return, "Error status %d", status);
PROPERTY_CHECK(server != NULL, return, "Error server");
uv_pipe_t *stream = (uv_pipe_t*)malloc(sizeof(uv_pipe_t));
PROPERTY_CHECK(stream != NULL, return, "Failed to alloc stream");
int ret = uv_pipe_init(uv_default_loop(), (uv_pipe_t*)stream, 1);
PROPERTY_CHECK(ret == 0, free(stream); return, "Failed to uv_pipe_init %d", ret);
stream->data = server;
ret = uv_accept(server, (uv_stream_t *)stream);
PROPERTY_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);
PROPERTY_CHECK(ret == 0, uv_close((uv_handle_t*)stream, NULL); free(stream);
return, "Failed to uv_read_start %d", ret);
}
int StartPropertyService()
{
PROPERTY_LOGI("StartPropertyService.");
uv_fs_t req;
uv_fs_unlink(uv_default_loop(), &req, PIPE_NAME, NULL);
signal(SIGINT, RemoveSocket);
uv_pipe_t pipeServer;
int ret = uv_pipe_init(uv_default_loop(), &pipeServer, 0);
PROPERTY_CHECK(ret == 0, return ret, "Failed to uv_pipe_init %d", ret);
ret = uv_pipe_bind(&pipeServer, PIPE_NAME);
PROPERTY_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);
PROPERTY_CHECK(ret == 0, return ret, "Failed to uv_listen %d %s", ret, uv_err_name(ret));
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
PROPERTY_LOGI("Start service exit.");
return 0;
}
int SystemWriteParameter(const char *name, const char *value)
{
PROPERTY_CHECK(name != NULL && value != NULL, return -1, "The name is null");
PROPERTY_LOGI("SystemWriteParameter name %s value: %s", name, value);
int ret = WritePropertyWithCheck(&g_propertyWorkSpace, &g_propertyWorkSpace.label, name, value);
if (ret == 0) {
ret = WritePersistProperty(name, value);
PROPERTY_CHECK(ret == 0, return ret, "Failed to set property");
} else {
PROPERTY_LOGE("Failed to set property %d name %s %s", ret, name, value);
}
// notify event to process trigger
PostPropertyTrigger(name, value);
return 0;
}
int SystemReadParameter(const char *name, char *value, unsigned int *len)
{
PROPERTY_CHECK(name != NULL && len != NULL, return -1, "The name is null");
PropertyHandle handle = 0;
int ret = ReadPropertyWithCheck(&g_propertyWorkSpace, name, &handle);
if (ret == 0) {
ret = ReadPropertyValue(&g_propertyWorkSpace, handle, value, len);
}
return ret;
}
int SystemTraversalParameters(void (*traversalParameter)(PropertyHandle handle, void* cookie), void* cookie)
{
PROPERTY_CHECK(traversalParameter != NULL, return -1, "The param is null");
return TraversalProperty(&g_propertyWorkSpace, traversalParameter, cookie);
}
PropertyWorkSpace *GetPropertyWorkSpace()
{
return &g_propertyWorkSpace;
}
int LoadPersistProperties()
{
return RefreshPersistProperties(&g_propertyWorkSpace, g_initContext);
}
......@@ -38,6 +38,11 @@ void MountBasicFs()
if (mount("sysfs", "/sys", "sysfs", 0, NULL) != 0) {
printf("Mount sysfs failed. %s\n", strerror(errno));
}
#ifndef __LITEOS__
if (mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL) != 0) {
printf("Mount selinuxfs failed. %s\n", strerror(errno));
}
#endif
}
void CreateDeviceNode()
......@@ -56,3 +61,19 @@ void CreateDeviceNode()
printf("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) {
printf("Create %s failed. %d\n", path, errno);
return -1;
}
rc = mkdir("/dev/unix/socket/", mode);
if (rc < 0 && errno != EEXIST) {
printf("Create %s failed. %d\n", path, errno);
return -1;
}
return rc;
}
......@@ -20,8 +20,10 @@
#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
......@@ -35,9 +37,9 @@ void RebootSystem()
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");
printf("[Init] prctl PR_SET_SECUREBITS failed: %d\n", errno);
return -1;
}
#endif
......@@ -46,9 +48,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");
printf("[Init] prctl PR_CAP_AMBIENT failed: %d\n", errno);
return -1;
}
#endif
......
/*
* 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 "init_capability.h"
#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef OHOS_LITE
#include <sys/capability.h>
#else
#include <linux/capability.h>
#endif
#include <sys/types.h>
#include <unistd.h>
#include "init_log.h"
#include "init_perms.h"
#define MAX_CAPS_CNT_FOR_ONE_SERVICE 100
struct CapStrCapNum {
char *capStr;
int CapNum;
};
static struct CapStrCapNum g_capStrCapNum[] = {
{"CHOWN", CAP_CHOWN},
{"DAC_OVERRIDE", CAP_DAC_OVERRIDE},
{"DAC_READ_SEARCH", CAP_DAC_READ_SEARCH},
{"FOWNER", CAP_FOWNER},
{"FSETID", CAP_FSETID},
{"KILL", CAP_KILL},
{"SETGID", CAP_SETGID},
{"SETUID", CAP_SETUID},
{"SETPCAP", CAP_SETPCAP},
{"LINUX_IMMUTABLE", CAP_LINUX_IMMUTABLE},
{"NET_BIND_SERVICE", CAP_NET_BIND_SERVICE},
{"NET_BROADCAST", CAP_NET_BROADCAST},
{"NET_ADMIN", CAP_NET_ADMIN},
{"NET_RAW", CAP_NET_RAW},
{"IPC_LOCK", CAP_IPC_LOCK},
{"IPC_OWNER", CAP_IPC_OWNER},
{"SYS_MODULE", CAP_SYS_MODULE},
{"SYS_RAWIO", CAP_SYS_RAWIO},
{"SYS_CHROOT", CAP_SYS_CHROOT},
{"SYS_PTRACE", CAP_SYS_PTRACE},
{"SYS_PACCT", CAP_SYS_PACCT},
{"SYS_ADMIN", CAP_SYS_ADMIN},
{"SYS_BOOT", CAP_SYS_BOOT},
{"SYS_NICE", CAP_SYS_NICE},
{"SYS_RESOURCE", CAP_SYS_RESOURCE},
{"SYS_TIME", CAP_SYS_TIME},
{"SYS_TTY_CONFIG", CAP_SYS_TTY_CONFIG},
{"MKNOD", CAP_MKNOD},
{"LEASE", CAP_LEASE},
{"AUDIT_WRITE", CAP_AUDIT_WRITE},
{"AUDIT_CONTROL", CAP_AUDIT_CONTROL},
{"SETFCAP", CAP_SETFCAP},
{"MAC_OVERRIDE", CAP_MAC_OVERRIDE},
{"MAC_ADMIN", CAP_MAC_ADMIN},
{"SYSLOG", CAP_SYSLOG},
{"WAKE_ALARM", CAP_WAKE_ALARM},
{"BLOCK_SUSPEND", CAP_BLOCK_SUSPEND},
{"AUDIT_READ", CAP_AUDIT_READ},
};
static int GetServiceStringCaps(const cJSON* filedJ, Service* curServ) // string form
{
unsigned int i = 0;
for (; i < curServ->servPerm.capsCnt; ++i) {
if (cJSON_GetArrayItem(filedJ, i) == NULL || !cJSON_GetStringValue(cJSON_GetArrayItem(filedJ, i))
|| strlen(cJSON_GetStringValue(cJSON_GetArrayItem(filedJ, i))) <= 0) { // check all errors
INIT_LOGE("[Init] GetServiceStringCaps, parse item[%d] as string, error.\n", i);
break;
}
char* fieldStr = cJSON_GetStringValue(cJSON_GetArrayItem(filedJ, i));
int mapSize = sizeof(g_capStrCapNum) / sizeof(struct CapStrCapNum); // search
int j = 0;
for (; j < mapSize; j++) {
if (!strcmp(fieldStr, g_capStrCapNum[j].capStr)) {
break;
}
}
if (j < mapSize) {
curServ->servPerm.caps[i] = g_capStrCapNum[j].CapNum;
} else {
INIT_LOGE("[Init] GetServiceStringCaps, fieldStr = %s, error.\n", fieldStr);
break;
}
if (curServ->servPerm.caps[i] > CAP_LAST_CAP && curServ->servPerm.caps[i] != FULL_CAP) {
// resources will be released by function: ReleaseServiceMem
INIT_LOGE("[Init] GetServiceStringCaps, cap = %d, error.\n", curServ->servPerm.caps[i]);
return SERVICE_FAILURE;
}
}
int ret = i == curServ->servPerm.capsCnt ? SERVICE_SUCCESS : SERVICE_FAILURE;
return ret;
}
int GetServiceCaps(const cJSON* curArrItem, Service* curServ)
{
curServ->servPerm.capsCnt = 0;
curServ->servPerm.caps = NULL;
cJSON* filedJ = cJSON_GetObjectItem(curArrItem, "caps");
if (filedJ == NULL) {
INIT_LOGE("[Init] GetServiceCaps, caps is not found. but maybe ok.\n");
return SERVICE_SUCCESS;
}
if (!cJSON_IsArray(filedJ)) {
INIT_LOGE("[Init] GetServiceCaps, caps is not a list, error.\n");
return SERVICE_FAILURE;
}
// caps array does not exist, means do not need any capability
int capsCnt = cJSON_GetArraySize(filedJ);
if (capsCnt <= 0) {
return SERVICE_SUCCESS;
}
if (capsCnt > MAX_CAPS_CNT_FOR_ONE_SERVICE) {
INIT_LOGE("[Init] GetServiceCaps, too many caps[cnt %d] for one service, should not exceed %d.\n",
capsCnt, MAX_CAPS_CNT_FOR_ONE_SERVICE);
return SERVICE_FAILURE;
}
curServ->servPerm.caps = (unsigned int*)malloc(sizeof(unsigned int) * capsCnt);
if (curServ->servPerm.caps == NULL) {
INIT_LOGE("[Init] GetServiceCaps, malloc error.\n");
return SERVICE_FAILURE;
}
curServ->servPerm.capsCnt = capsCnt;
int i = 0;
for (; i < capsCnt; ++i) { // number form
cJSON* capJ = cJSON_GetArrayItem(filedJ, i);
if (!cJSON_IsNumber(capJ) || cJSON_GetNumberValue(capJ) < 0) {
// resources will be released by function: ReleaseServiceMem
INIT_LOGE("[Init] GetServiceCaps, capJ is not a number or capJ < 0, error.\n");
break;
}
curServ->servPerm.caps[i] = (unsigned int)cJSON_GetNumberValue(capJ);
if (curServ->servPerm.caps[i] > CAP_LAST_CAP && curServ->servPerm.caps[i] != FULL_CAP) { // CAP_LAST_CAP = 37
// resources will be released by function: ReleaseServiceMem
INIT_LOGE("[Init] GetServiceCaps, caps = %d, error.\n", curServ->servPerm.caps[i]);
return SERVICE_FAILURE;
}
}
if (i == capsCnt) {
return SERVICE_SUCCESS;
}
int ret = GetServiceStringCaps(filedJ, curServ);
return ret;
}
此差异已折叠。
/*
* 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_import.h"
#include <stdio.h>
#include "cJSON.h"
#include "init_read_cfg.h"
#define IMPORT_ARR_NAME_IN_JSON "import"
void ParseAllImports(cJSON *root)
{
cJSON *importAttr = cJSON_GetObjectItemCaseSensitive(root, IMPORT_ARR_NAME_IN_JSON);
if (!cJSON_IsArray(importAttr)) {
printf("[Init] ParseAllImports, import item is not array!\n");
return;
}
int importAttrSize = cJSON_GetArraySize(importAttr);
for (int i = 0; i < importAttrSize; i++) {
cJSON *importItem = cJSON_GetArrayItem(importAttr, i);
if (!cJSON_IsString(importItem)) {
printf("[Init] Invalid type of import item. should be string\n");
return;
}
char *importFile = cJSON_GetStringValue(importItem);
if (importFile == NULL) {
printf("[Init] cannot get import config file\n");
return;
}
printf("[Init] [Debug], ready to import %s...\n", importFile);
ParseInitCfg(importFile);
}
printf("[Init] [Debug], parse import file done\n");
return;
}
\ No newline at end of file
......@@ -24,17 +24,31 @@
#define JOBS_ARR_NAME_IN_JSON "jobs"
#define CMDS_ARR_NAME_IN_JSON "cmds"
#define MAX_JOBS_COUNT 10
#define MAX_JOBS_COUNT 100
static const char* g_supportedJobs[] = {
"pre-init",
"init",
"post-init",
};
// static const char* g_supportedJobs[] = {
// "pre-init",
// "init",
// "post-init",
// };
static Job* g_jobs = NULL;
static int g_jobCnt = 0;
void DumpAllJobs()
{
printf("[Init][Debug], Ready to dump all jobs:\n");
for (int i = 0; i < g_jobCnt; i++) {
printf("\t[Init], job name: %s\n", g_jobs[i].name);
printf("\t[Init], list all commands:\n");
for (int j = 0; j < g_jobs[i].cmdLinesCnt; j++) {
printf("\t\t[Init], command name : %s, command options: %s\n",
g_jobs[i].cmdLines[j].name, g_jobs[i].cmdLines[j].cmdContent);
}
}
printf("[Init][Debug], To dump all jobs finished\n");
}
static int GetJobName(const cJSON* jobItem, Job* resJob)
{
char* jobNameStr = cJSON_GetStringValue(cJSON_GetObjectItem(jobItem, "name"));
......@@ -42,37 +56,46 @@ static int GetJobName(const cJSON* jobItem, Job* resJob)
return 0;
}
size_t supportJobCnt = sizeof(g_supportedJobs) / sizeof(g_supportedJobs[0]);
for (size_t i = 0; i < supportJobCnt; ++i) {
if (strlen(g_supportedJobs[i]) == strlen(jobNameStr) &&
strncmp(g_supportedJobs[i], jobNameStr, strlen(g_supportedJobs[i])) == 0) {
if (memcpy_s(resJob->name, MAX_JOB_NAME_LEN, jobNameStr, strlen(jobNameStr)) != EOK) {
return 0;
}
resJob->name[strlen(jobNameStr)] = '\0';
return 1;
}
//size_t supportJobCnt = sizeof(g_supportedJobs) / sizeof(g_supportedJobs[0]);
//for (size_t i = 0; i < supportJobCnt; ++i) {
// if (strlen(g_supportedJobs[i]) == strlen(jobNameStr) &&
// strncmp(g_supportedJobs[i], jobNameStr, strlen(g_supportedJobs[i])) == 0) {
// if (memcpy_s(resJob->name, MAX_JOB_NAME_LEN, jobNameStr, strlen(jobNameStr)) != EOK) {
// return 0;
// }
// resJob->name[strlen(jobNameStr)] = '\0';
// return 1;
// }
//}
if (memcpy_s(resJob->name, MAX_JOB_NAME_LEN, jobNameStr, strlen(jobNameStr)) != EOK) {
printf("[Init], Get job name \"%s\" failed\n", jobNameStr);
return 0;
}
return 0;
resJob->name[strlen(jobNameStr)] = '\0';
return 1;
}
static void ParseJob(const cJSON* jobItem, Job* resJob)
{
if (!GetJobName(jobItem, resJob)) {
printf("[Init][Debug], get JobName failed\n");
(void)memset_s(resJob, sizeof(*resJob), 0, sizeof(*resJob));
return;
}
cJSON* cmdsItem = cJSON_GetObjectItem(jobItem, CMDS_ARR_NAME_IN_JSON);
if (!cJSON_IsArray(cmdsItem)) {
printf("[Init][Debug], job %s is not an arrary\n", resJob->name);
return;
}
int cmdLinesCnt = cJSON_GetArraySize(cmdsItem);
if (cmdLinesCnt <= 0) { // empty job, no cmd
printf("[Init][Debug], empty job \"%s\"\n", resJob->name);
return;
}
printf("[Init][Debug], job = %s, cmdLineCnt = %d\n", resJob->name, cmdLinesCnt);
if (cmdLinesCnt > MAX_CMD_CNT_IN_ONE_JOB) {
printf("[Init] ParseAllJobs, too many cmds[cnt %d] in one job, it should not exceed %d.\n",
cmdLinesCnt, MAX_CMD_CNT_IN_ONE_JOB);
......@@ -81,6 +104,7 @@ static void ParseJob(const cJSON* jobItem, Job* resJob)
resJob->cmdLines = (CmdLine*)malloc(cmdLinesCnt * sizeof(CmdLine));
if (resJob->cmdLines == NULL) {
printf("[Init][Debug], allocate memory for command line failed\n");
return;
}
......@@ -117,13 +141,14 @@ void ParseAllJobs(const cJSON* fileRoot)
return;
}
Job* retJobs = (Job*)malloc(sizeof(Job) * jobArrSize);
Job* retJobs = (Job*)realloc(g_jobs, sizeof(Job) * (g_jobCnt + jobArrSize));
if (retJobs == NULL) {
printf("[Init] ParseAllJobs, malloc failed! job arrSize %d.\n", jobArrSize);
return;
}
if (memset_s(retJobs, sizeof(Job) * jobArrSize, 0, sizeof(Job) * jobArrSize) != EOK) {
Job* tmp = retJobs + g_jobCnt;
if (memset_s(tmp, sizeof(Job) * jobArrSize, 0, sizeof(Job) * jobArrSize) != EOK) {
printf("[Init] ParseAllJobs, memset_s failed.\n");
free(retJobs);
retJobs = NULL;
......@@ -132,10 +157,10 @@ void ParseAllJobs(const cJSON* fileRoot)
for (int i = 0; i < jobArrSize; ++i) {
cJSON* jobItem = cJSON_GetArrayItem(jobArr, i);
ParseJob(jobItem, &(retJobs[i]));
ParseJob(jobItem, &(tmp[i]));
}
g_jobs = retJobs;
g_jobCnt = jobArrSize;
g_jobCnt += jobArrSize;
}
void DoJob(const char* jobName)
......@@ -145,13 +170,15 @@ void DoJob(const char* jobName)
return;
}
printf("[Init][Debug], Call job with name %s\n", jobName);
for (int i = 0; i < g_jobCnt; ++i) {
if (strncmp(jobName, g_jobs[i].name, strlen(g_jobs[i].name)) == 0) {
CmdLine* cmdLines = g_jobs[i].cmdLines;
for (int j = 0; j < g_jobs[i].cmdLinesCnt; ++j) {
DoCmd(&(cmdLines[j]));
}
break;
// Walk through all jobs
// break;
}
}
}
......
/*
* 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
void InitLog(int logLevel, const char *fileName, int line, const char *fmt, ...)
{
UNUSED(logLevel);
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, "%d-%d-%d %d:%d %s %d : %s", (t->tm_year + BASE_YEAR),
(t->tm_mon + 1), t->tm_mday, t->tm_hour, t->tm_min, fileName, line, tmpFmt) == -1) {
return;
}
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);
return;
}
va_end(vargs);
}
......@@ -16,6 +16,7 @@
#include "init_read_cfg.h"
#include <errno.h>
#include <dirent.h>
#include <linux/capability.h>
#include <stdio.h>
#include <stdlib.h>
......@@ -23,9 +24,16 @@
#include <sys/stat.h>
#include <unistd.h>
#include "init_import.h"
#include "init_jobs.h"
#include "init_log.h"
#include "init_perms.h"
#include "init_service_manager.h"
#include "init_utils.h"
#ifndef OHOS_LITE
#include "trigger.h"
#endif
#include "securec.h"
#ifndef __LINUX__
#ifdef OHOS_LITE
......@@ -33,368 +41,91 @@
#endif
#endif
static const long MAX_JSON_FILE_LEN = 102400; // max init.cfg size 100KB
static const int MAX_PATH_ARGS_CNT = 20; // max path and args count
static const int MAX_ONE_ARG_LEN = 64; // max length of one param/path
#define MAX_SERVICES_CNT_IN_FILE 100
#define MAX_CAPS_CNT_FOR_ONE_SERVICE 100
#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"
static char* ReadFileToBuf()
{
char* buffer = NULL;
FILE* fd = NULL;
struct stat fileStat = {0};
do {
if (stat(INIT_CONFIGURATION_FILE, &fileStat) != 0 ||
fileStat.st_size <= 0 || fileStat.st_size > MAX_JSON_FILE_LEN) {
break;
}
fd = fopen(INIT_CONFIGURATION_FILE, "r");
if (fd == NULL) {
break;
}
buffer = (char*)malloc(fileStat.st_size + 1);
if (buffer == NULL) {
break;
}
if (fread(buffer, fileStat.st_size, 1, fd) != 1) {
free(buffer);
buffer = NULL;
break;
}
buffer[fileStat.st_size] = '\0';
} while (0);
if (fd != NULL) {
fclose(fd);
fd = NULL;
}
return buffer;
}
static cJSON* GetArrItem(const cJSON* fileRoot, int* arrSize, const char* arrName)
#define FILE_NAME_MAX_SIZE 100
static void ParseInitCfgContents(cJSON *root)
{
cJSON* arrItem = cJSON_GetObjectItemCaseSensitive(fileRoot, arrName);
if (!cJSON_IsArray(arrItem)) {
printf("[Init] GetArrItem, item %s is not an array!\n", arrName);
return NULL;
}
*arrSize = cJSON_GetArraySize(arrItem);
if (*arrSize <= 0) {
return NULL;
}
return arrItem;
}
// parse services
ParseAllServices(root);
static int IsForbidden(const char* fieldStr)
{
size_t fieldLen = strlen(fieldStr);
size_t forbidStrLen = strlen(BIN_SH_NOT_ALLOWED);
if (fieldLen == forbidStrLen) {
if (strncmp(fieldStr, BIN_SH_NOT_ALLOWED, fieldLen) == 0) {
return 1;
}
return 0;
} else if (fieldLen > forbidStrLen) {
// "/bin/shxxxx" is valid but "/bin/sh xxxx" is invalid
if (strncmp(fieldStr, BIN_SH_NOT_ALLOWED, forbidStrLen) == 0) {
if (fieldStr[forbidStrLen] == ' ') {
return 1;
}
}
return 0;
} else {
return 0;
}
}
static void ReleaseServiceMem(Service* curServ)
{
if (curServ->pathArgs != NULL) {
for (int i = 0; i < curServ->pathArgsCnt; ++i) {
if (curServ->pathArgs[i] != NULL) {
free(curServ->pathArgs[i]);
curServ->pathArgs[i] = NULL;
}
}
free(curServ->pathArgs);
curServ->pathArgs = NULL;
}
curServ->pathArgsCnt = 0;
if (curServ->servPerm.caps != NULL) {
free(curServ->servPerm.caps);
curServ->servPerm.caps = NULL;
}
if (curServ->servPerm.gIDs != NULL) {
free(curServ->servPerm.gIDs);
curServ->servPerm.gIDs = NULL;
}
curServ->servPerm.capsCnt = 0;
curServ->servPerm.gidsCnt = 0;
}
static int GetServiceName(const cJSON* curArrItem, Service* curServ)
{
char* fieldStr = cJSON_GetStringValue(cJSON_GetObjectItem(curArrItem, "name"));
if (fieldStr == NULL) {
return SERVICE_FAILURE;
}
// parse jobs
ParseAllJobs(root);
size_t strLen = strlen(fieldStr);
if (strLen == 0 || strLen > MAX_SERVICE_NAME) {
return SERVICE_FAILURE;
}
#ifndef OHOS_LITE
ParseTriggerConfig(root);
#endif
if (memcpy_s(curServ->name, MAX_SERVICE_NAME, fieldStr, strLen) != EOK) {
return SERVICE_FAILURE;
}
curServ->name[strLen] = '\0';
return SERVICE_SUCCESS;
// parse imports
ParseAllImports(root);
}
static int GetServicePathAndArgs(const cJSON* curArrItem, Service* curServ)
void ParseInitCfg(const char *configFile)
{
cJSON* pathItem = cJSON_GetObjectItem(curArrItem, "path");
if (!cJSON_IsArray(pathItem)) {
return SERVICE_FAILURE;
}
int arrSize = cJSON_GetArraySize(pathItem);
if (arrSize <= 0 || arrSize > MAX_PATH_ARGS_CNT) { // array size invalid
return SERVICE_FAILURE;
}
curServ->pathArgs = (char**)malloc((arrSize + 1) * sizeof(char*));
if (curServ->pathArgs == NULL) {
return SERVICE_FAILURE;
}
for (int i = 0; i < arrSize + 1; ++i) {
curServ->pathArgs[i] = NULL;
}
curServ->pathArgsCnt = arrSize + 1;
for (int i = 0; i < arrSize; ++i) {
char* curParam = cJSON_GetStringValue(cJSON_GetArrayItem(pathItem, i));
if (curParam == NULL || strlen(curParam) > MAX_ONE_ARG_LEN) {
// resources will be released by function: ReleaseServiceMem
return SERVICE_FAILURE;
}
if (i == 0 && IsForbidden(curParam)) {
// resources will be released by function: ReleaseServiceMem
return SERVICE_FAILURE;
}
size_t paramLen = strlen(curParam);
curServ->pathArgs[i] = (char*)malloc(paramLen + 1);
if (curServ->pathArgs[i] == NULL) {
// resources will be released by function: ReleaseServiceMem
return SERVICE_FAILURE;
}
if (memcpy_s(curServ->pathArgs[i], paramLen + 1, curParam, paramLen) != EOK) {
// resources will be released by function: ReleaseServiceMem
return SERVICE_FAILURE;
}
curServ->pathArgs[i][paramLen] = '\0';
if (configFile == NULL || *configFile == '\0') {
printf("[Init] Invalid config file\n");
return;
}
return SERVICE_SUCCESS;
}
static int GetServiceNumber(const cJSON* curArrItem, Service* curServ, const char* targetField)
{
cJSON* filedJ = cJSON_GetObjectItem(curArrItem, targetField);
if (!cJSON_IsNumber(filedJ)) {
return SERVICE_FAILURE;
}
char *fileBuf = ReadFileToBuf(configFile);
//printf("[Init] start dump config file: \n");
//printf("%s", fileBuf);
//printf("[Init] end dump config file: \n");
int value = (int)cJSON_GetNumberValue(filedJ);
if (value < 0) {
return SERVICE_FAILURE;
}
cJSON* fileRoot = cJSON_Parse(fileBuf);
free(fileBuf);
fileBuf = NULL;
if (strncmp(targetField, UID_STR_IN_CFG, strlen(UID_STR_IN_CFG)) == 0) {
curServ->servPerm.uID = value;
} else if (strncmp(targetField, ONCE_STR_IN_CFG, strlen(ONCE_STR_IN_CFG)) == 0) {
if (value != 0) {
curServ->attribute |= SERVICE_ATTR_ONCE;
}
} else if (strncmp(targetField, IMPORTANT_STR_IN_CFG, strlen(IMPORTANT_STR_IN_CFG)) == 0) {
if (value != 0) {
curServ->attribute |= SERVICE_ATTR_IMPORTANT;
}
} else {
return SERVICE_FAILURE;
if (fileRoot == NULL) {
printf("[Init] InitReadCfg, parse failed! please check file %s format.\n", configFile);
return;
}
return SERVICE_SUCCESS;
ParseInitCfgContents(fileRoot);
// Release JSON object
cJSON_Delete(fileRoot);
return;
}
static int GetServiceCaps(const cJSON* curArrItem, Service* curServ)
static void ReadCfgs(const char *dirPath)
{
curServ->servPerm.capsCnt = 0;
curServ->servPerm.caps = NULL;
cJSON* filedJ = cJSON_GetObjectItem(curArrItem, "caps");
if (!cJSON_IsArray(filedJ)) {
return SERVICE_FAILURE;
}
// caps array does not exist, means do not need any capability
int capsCnt = cJSON_GetArraySize(filedJ);
if (capsCnt <= 0) {
return SERVICE_SUCCESS;
}
if (capsCnt > MAX_CAPS_CNT_FOR_ONE_SERVICE) {
printf("[Init] GetServiceCaps, too many caps[cnt %d] for one service, should not exceed %d.\n",
capsCnt, MAX_CAPS_CNT_FOR_ONE_SERVICE);
return SERVICE_FAILURE;
}
curServ->servPerm.caps = (unsigned int*)malloc(sizeof(unsigned int) * capsCnt);
if (curServ->servPerm.caps == NULL) {
return SERVICE_FAILURE;
DIR *pDir = opendir(dirPath);
if (pDir == NULL) {
INIT_LOGE("[Init], ParseCfgs open cfg dir :%s failed.%d\n", dirPath, errno);
return;
}
for (int i = 0; i < capsCnt; ++i) {
cJSON* capJ = cJSON_GetArrayItem(filedJ, i);
if (!cJSON_IsNumber(capJ) || cJSON_GetNumberValue(capJ) < 0) {
// resources will be released by function: ReleaseServiceMem
return SERVICE_FAILURE;
}
curServ->servPerm.caps[i] = (unsigned int)cJSON_GetNumberValue(capJ);
if (curServ->servPerm.caps[i] > CAP_LAST_CAP && curServ->servPerm.caps[i] != FULL_CAP) {
// resources will be released by function: ReleaseServiceMem
return SERVICE_FAILURE;
struct dirent *dp;
while ((dp = readdir(pDir)) != NULL) {
char fileName[FILE_NAME_MAX_SIZE];
if (snprintf_s(fileName, FILE_NAME_MAX_SIZE, FILE_NAME_MAX_SIZE - 1, "%s/%s", dirPath, dp->d_name) == -1) {
INIT_LOGE("[Init], ParseCfgs snprintf_s failed.\n");
closedir(pDir);
return;
}
struct stat st;
if (stat(fileName, &st) == 0) {
if (strstr(dp->d_name, ".cfg") == NULL) {
continue;
}
INIT_LOGE("[Init], fileName :%s.\n", fileName);
ParseInitCfg(fileName);
}
}
curServ->servPerm.capsCnt = capsCnt;
return SERVICE_SUCCESS;
closedir(pDir);
return;
}
static int GetServiceGids(const cJSON* curArrItem, Service* curServ)
static void ParseOtherCfgs()
{
curServ->servPerm.gidsCnt = 0;
curServ->servPerm.gIDs = NULL;
int gidsCnt;
cJSON* filedJ = cJSON_GetObjectItem(curArrItem, "gid");
if (cJSON_IsArray(filedJ)) {
gidsCnt = cJSON_GetArraySize(filedJ);
if (gidsCnt <= 0) {
// gids array does not exist, means do not need any group
return SERVICE_SUCCESS;
}
curServ->servPerm.gIDs = (unsigned int*)malloc(sizeof(unsigned int) * gidsCnt);
if (curServ->servPerm.gIDs == NULL) {
return SERVICE_FAILURE;
}
for (int i = 0; i < gidsCnt; ++i) {
cJSON* gidJ = cJSON_GetArrayItem(filedJ, i);
if (!cJSON_IsNumber(gidJ) || cJSON_GetNumberValue(gidJ) < 0) {
// resources will be released by function: ReleaseServiceMem
return SERVICE_FAILURE;
}
curServ->servPerm.gIDs[i] = (unsigned int)cJSON_GetNumberValue(gidJ);
}
} else {
int value = (int)cJSON_GetNumberValue(filedJ);
if (value < 0) {
return SERVICE_FAILURE;
}
gidsCnt = 1;
curServ->servPerm.gIDs = (unsigned int*)malloc(sizeof(unsigned int));
if (curServ->servPerm.gIDs == NULL) {
return SERVICE_FAILURE;
}
curServ->servPerm.gIDs[0] = (unsigned int)value;
}
curServ->servPerm.gidsCnt = gidsCnt;
return SERVICE_SUCCESS;
}
static void ParseAllServices(const cJSON* fileRoot)
{
int servArrSize = 0;
cJSON* serviceArr = GetArrItem(fileRoot, &servArrSize, SERVICES_ARR_NAME_IN_JSON);
if (serviceArr == NULL) {
printf("[Init] InitReadCfg, get array %s failed.\n", SERVICES_ARR_NAME_IN_JSON);
return;
}
if (servArrSize > MAX_SERVICES_CNT_IN_FILE) {
printf("[Init] InitReadCfg, too many services[cnt %d] detected, should not exceed %d.\n",
servArrSize, MAX_SERVICES_CNT_IN_FILE);
return;
}
Service* retServices = (Service*)malloc(sizeof(Service) * servArrSize);
if (retServices == NULL) {
printf("[Init] InitReadCfg, malloc for %s arr failed! %d.\n", SERVICES_ARR_NAME_IN_JSON, servArrSize);
return;
}
if (memset_s(retServices, sizeof(Service) * servArrSize, 0, sizeof(Service) * servArrSize) != EOK) {
free(retServices);
retServices = NULL;
return;
}
for (int i = 0; i < servArrSize; ++i) {
cJSON* curItem = cJSON_GetArrayItem(serviceArr, i);
if (GetServiceName(curItem, &retServices[i]) != SERVICE_SUCCESS ||
GetServicePathAndArgs(curItem, &retServices[i]) != SERVICE_SUCCESS ||
GetServiceNumber(curItem, &retServices[i], UID_STR_IN_CFG) != SERVICE_SUCCESS ||
GetServiceGids(curItem, &retServices[i]) != SERVICE_SUCCESS ||
GetServiceNumber(curItem, &retServices[i], ONCE_STR_IN_CFG) != SERVICE_SUCCESS ||
GetServiceNumber(curItem, &retServices[i], IMPORTANT_STR_IN_CFG) != SERVICE_SUCCESS ||
GetServiceCaps(curItem, &retServices[i]) != SERVICE_SUCCESS) {
// release resources if it fails
ReleaseServiceMem(&retServices[i]);
retServices[i].attribute |= SERVICE_ATTR_INVALID;
printf("[Init] InitReadCfg, parse information for service %d failed.\n", i);
continue;
}
}
RegisterServices(retServices, servArrSize);
ReadCfgs("/system/etc/init");
return;
}
void InitReadCfg()
{
// read configuration file in json format
char* fileBuf = ReadFileToBuf();
if (fileBuf == NULL) {
printf("[Init] InitReadCfg, read file %s failed! err %d.\n", INIT_CONFIGURATION_FILE, errno);
return;
}
cJSON* fileRoot = cJSON_Parse(fileBuf);
free(fileBuf);
fileBuf = NULL;
if (fileRoot == NULL) {
printf("[Init] InitReadCfg, parse failed! please check file %s format.\n", INIT_CONFIGURATION_FILE);
return;
}
// parse services
ParseAllServices(fileRoot);
// parse jobs
ParseAllJobs(fileRoot);
// release memory
cJSON_Delete(fileRoot);
ParseInitCfg(INIT_CONFIGURATION_FILE);
ParseOtherCfgs();
printf("[init], Parse init config file done.\n");
DumpAllServices();
// DumpAllJobs();
// do jobs
DoJob("pre-init");
#ifndef __LINUX__
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -33,6 +33,8 @@
#ifndef OHOS_LITE
#include "device.h"
#include "property.h"
#include "property_service.h"
#endif
static const pid_t INIT_PROCESS_PID = 1;
......@@ -82,6 +84,9 @@ int main(int argc, char * const argv[])
// 2. Mount basic filesystem and create common device node.
MountBasicFs();
CreateDeviceNode();
MakeSocketDir("/dev/unix/socket/", 0755);
InitPropertyService();
#endif
// 3. signal register
......@@ -107,6 +112,12 @@ int main(int argc, char * const argv[])
// 5. read configuration file and do jobs
InitReadCfg();
LoadDefaultProperty("/system/build.prop");
LoadDefaultProperty("/system/buildz.prop");
LoadDefaultProperty("/vendor/build.prop");
LoadDefaultProperty("/vendor/default.prop");
LoadDefaultProperty("/vendor/odm/etc/build.prop");
LoadDefaultProperty("/system/etc/prop.default");
#ifdef OHOS_DEBUG
struct timespec tmCfg;
if (clock_gettime(CLOCK_REALTIME, &tmCfg) != 0) {
......@@ -121,6 +132,9 @@ int main(int argc, char * const argv[])
#endif
printf("[Init] main, entering wait.\n");
#ifndef OHOS_LITE
StartPropertyService();
#endif
while (1) {
// pause only returns when a signal was caught and the signal-catching function returned.
// pause only returns -1, no need to process the return value.
......
......@@ -34,6 +34,7 @@ if (defined(ohos_lite)) {
"//base/startup/init_lite/services/src/init_cmds.c",
"//base/startup/init_lite/services/src/init_jobs.c",
"//base/startup/init_lite/services/src/init_service.c",
"//base/startup/init_lite/services/src/init_utils.c",
"//base/startup/init_lite/services/src/init_service_manager.c",
"//base/startup/init_lite/services/src/init_signal_handler.c",
"cmd_func_test.cpp",
......
......@@ -48,7 +48,7 @@ const uid_t CFG_FILE_UID = 0;
const gid_t CFG_FILE_GID = 0;
const mode_t CFG_FILE_MODE = S_IRUSR;
const int JOBS_IN_FILE_COUNT = 3; // pre-init, init, post-init
const int MAX_SERVICES_CNT_IN_FILE = 100;
const int MAX_SERVICES_COUNT_IN_FILE = 100;
const int MAX_CAPS_CNT_FOR_ONE_SERVICE = 100;
const unsigned int MAX_CAPABILITY_VALUE = 4294967295; // 0xFFFFFFFF
const unsigned int MAX_JSON_FILE_LEN = 102400; // max init.cfg size 100KB
......@@ -642,7 +642,7 @@ static void CheckServices(const cJSON* fileRoot)
int servArrSize = 0;
cJSON* serviceArr = GetArrItem(fileRoot, servArrSize, SERVICE_ARR_NAME_IN_JSON);
EXPECT_TRUE(serviceArr != nullptr);
EXPECT_TRUE(servArrSize <= MAX_SERVICES_CNT_IN_FILE);
EXPECT_TRUE(servArrSize <= MAX_SERVICES_COUNT_IN_FILE);
for (int i = 0; i < servArrSize; ++i) {
cJSON* curItem = cJSON_GetArrayItem(serviceArr, i);
......
# 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("triggerservice") {
sources = [
"trigger_manager.c",
"trigger_processor.c",
"trigger_checker.c",
"//base/startup/init_lite/services/src/init_utils.c",
]
include_dirs = [
".",
"//base/startup/init_lite/services/include/property",
"//base/startup/init_lite/services/include/trigger",
"//base/startup/init_lite/services/include",
"//base/startup/init_lite/services/property/include",
"//third_party/libuv/include",
"//third_party/cJSON",
]
deps = [
"//third_party/libuv:uv_static",
"//third_party/bounds_checking_function:libsec_static",
]
part_name = "startup"
subsystem_name = "startup"
}
\ 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 "property.h"
#include "trigger.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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册