提交 017f716d 编写于 作者: S sun_fan

init : fix param .

Signed-off-by: Nsun_fan <sun_fan1@hoperun.com>
上级 aeb75007
......@@ -18,14 +18,13 @@
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "init_log.h"
static int SendCmd(int cmd, unsigned long arg)
{
int fd = open(QUICKSTART_NODE, O_RDONLY);
......
# 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_shared_library("dynamic_service") {
sources = [ "dynamic_service.c" ]
include_dirs = [
"//base/startup/syspara_lite/interfaces/innerkits/native/syspara/include",
"//base/startup/init_lite/interfaces/innerkits/include",
]
deps = [
"//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara",
]
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
install_images = [ "system" ]
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 "dynamic_service.h"
#include <stdio.h>
#include "hilog/log.h"
#include "parameter.h"
#undef LOG_TAG
#undef LOG_DOMAIN
#define LOG_TAG "Init"
#define LOG_DOMAIN 0xD000719
int32_t StartDynamicProcess(const char *name)
{
if (name == NULL) {
HILOG_ERROR(LOG_CORE, "Start dynamic service failed, service name is null.");
return -1;
}
if (SetParameter("ohos.ctl.start", name) != 0) {
HILOG_ERROR(LOG_CORE, "Set param for %{public}s failed.\n", name);
return -1;
}
return 0;
}
int32_t StopDynamicProcess(const char *name)
{
if (name == NULL) {
HILOG_ERROR(LOG_CORE, "Stop dynamic service failed, service is null.\n");
return -1;
}
if (SetParameter("ohos.ctl.stop", name) != 0) {
HILOG_ERROR(LOG_CORE, "Set param for %{public}s failed.\n", name);
return -1;
}
return 0;
}
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef DYNAMIC_SERVICE_API_H
#define DYNAMIC_SERVICE_API_H
#include <inttypes.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
int32_t StartDynamicProcess(const char *name);
int32_t StopDynamicProcess(const char *name);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // DYNAMIC_SERVICE_API_H
\ No newline at end of file
......@@ -25,7 +25,7 @@ ohos_static_library("libreboot") {
deps = [
"//base/startup/init_lite/services/log:init_log",
"//base/startup/init_lite/services/param:paramclient",
"//base/startup/init_lite/services/param:param_client",
"//third_party/bounds_checking_function:libsec_static",
]
}
......@@ -46,7 +46,7 @@ int DoReboot(const char *cmdContent)
}
return 0;
}
int length = strlen(cmdContent);
size_t length = strlen(cmdContent);
if (length > MAX_REBOOT_VAUE_SIZE) {
INIT_LOGE("DoReboot api error, cmdContent = %s, length = %d.", cmdContent, length);
return -1;
......
......@@ -18,11 +18,7 @@
#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>
......@@ -34,7 +30,7 @@
#define MAX_SOCKET_ENV_PREFIX_LEN 64
#define MAX_SOCKET_DIR_LEN 128
static int GetControlFromEnv(char *path, int length)
static int GetControlFromEnv(const char *path, int length)
{
if (path == NULL || length <= 0) {
return -1;
......
......@@ -112,7 +112,7 @@ if (defined(ohos_lite)) {
]
deps = [
"//base/startup/init_lite/services/log:init_log",
"//base/startup/init_lite/services/param:paramservice",
"//base/startup/init_lite/services/param:param_service",
"//third_party/bounds_checking_function:libsec_static",
"//third_party/cJSON:cjson_static",
]
......@@ -134,13 +134,17 @@ if (defined(ohos_lite)) {
deps = [
":init",
":init_etc",
"//base/startup/init_lite/interfaces/innerkits/dynamic_service:dynamic_service",
"//base/startup/init_lite/interfaces/innerkits/socket:libsocket",
"//base/startup/init_lite/services/cmds/reboot:reboot",
"//base/startup/init_lite/services/cmds/service_control:service_control",
"//base/startup/init_lite/services/param:getparam",
"//base/startup/init_lite/services/param:paramclient",
"//base/startup/init_lite/services/param:paramservice",
"//base/startup/init_lite/services/param:setparam",
"//base/startup/init_lite/services/param:param",
"//base/startup/init_lite/services/param:param_client",
"//base/startup/init_lite/services/param:param_service",
"//base/startup/init_lite/services/param:param_watcher",
"//base/startup/init_lite/services/param:param_watcher.rc",
"//base/startup/init_lite/services/param:param_watcheragent",
"//base/startup/init_lite/services/param/watcher/sa_profile:param_watcher_profile",
]
}
......@@ -179,8 +183,15 @@ if (defined(ohos_lite)) {
}
ohos_prebuilt_etc("ohos.para") {
source = "//base/startup/init_lite/services/etc/ohos.para"
source = "//base/startup/init_lite/services/etc/param/ohos.para"
part_name = "init"
module_install_dir = "etc/param"
}
ohos_prebuilt_etc("ohos.para.dac") {
source = "//base/startup/init_lite/services/etc/param/ohos.para.dac"
part_name = "init"
module_install_dir = "etc/param"
}
group("init_etc") {
......@@ -190,6 +201,7 @@ if (defined(ohos_lite)) {
":init.usb.cfg",
":init.usb.configfs.cfg",
":ohos.para",
":ohos.para.dac",
":passwd",
]
}
......
......@@ -19,17 +19,26 @@
#include "init_reboot.h"
#define REBOOT_CMD_NUMBER 2
#define USAGE_INFO "usage: reboot shutdown\n"\
" reboot updater\n"\
" reboot updater[:options]\n" \
" reboot flash\n" \
" reboot flash[:options]\n" \
" reboot\n"
int main(int argc, char* argv[])
{
if (argc > REBOOT_CMD_NUMBER) {
printf("usage: reboot shutdown\n reboot updater\n reboot updater[:options]\n reboot\n");
printf("%s", USAGE_INFO);
return 0;
}
if (argc == REBOOT_CMD_NUMBER && strcmp(argv[1], "shutdown") != 0 &&
strcmp(argv[1], "updater") != 0 &&
strncmp(argv[1], "updater:", strlen("updater:")) != 0) {
printf("usage: reboot shutdown\n reboot updater\n reboot updater[:options]\n reboot\n");
strcmp(argv[1], "flash") != 0 &&
strncmp(argv[1], "updater:", strlen("updater:")) != 0 &&
strncmp(argv[1], "flash:", strlen("flash:")) != 0) {
printf("%s", USAGE_INFO);
return 0;
}
int ret = 0;
......
......@@ -19,7 +19,7 @@ ohos_executable("service_control") {
"//base/startup/init_lite/services/include",
]
deps = [
"//base/startup/init_lite/services/param:paramclient",
"//base/startup/init_lite/services/param:param_client",
"//third_party/bounds_checking_function:libsec_static",
]
symlink_target_name = [
......
......@@ -63,27 +63,7 @@
"mount configfs none /config nodev noexec nosuid",
"chmod 0770 /config/sdcardfs",
"chown system package_info /config/sdcardfs",
"mkdir /mnt/secure 0700 root root",
"mkdir /mnt/secure/asec 0700 root root",
"mkdir /mnt/asec 0755 root system",
"mkdir /mnt/obb 0755 root system",
"mkdir /mnt/media_rw 0750 root media_rw",
"mkdir /mnt/user 0755 root root",
"mkdir /mnt/user/0 0755 root root",
"mkdir /mnt/expand 0771 system system",
"mkdir /mnt/appfuse 0711 root root",
"mkdir /mnt/runtime 0700 root root",
"mkdir /mnt/runtime/default 0755 root root",
"mkdir /mnt/runtime/default/self 0755 root root",
"mkdir /mnt/runtime/read 0755 root root",
"mkdir /mnt/runtime/read/self 0755 root root",
"mkdir /mnt/runtime/write 0755 root root",
"mkdir /mnt/runtime/write/self 0755 root root",
"mkdir /mnt/runtime/full 0755 root root",
"mkdir /mnt/runtime/full/self 0755 root root",
"symlink /storage/self/primary /sdcard",
"symlink /storage/self/primary /mnt/sdcard",
"symlink /mnt/user/0/primary /mnt/runtime/default/self/primary",
"write /proc/sys/kernel/panic_on_oops 1",
"write /proc/sys/kernel/hung_task_timeout_secs 0",
"write /proc/cpu/alignment 4",
......@@ -153,25 +133,12 @@
"chmod 0600 /dev/cg2_bpf",
"mount bpf bpf /sys/fs/bpf nodev noexec nosuid",
"mkdir /dev/fscklogs 0770 root system",
"mount pstore pstore /sys/fs/pstore nodev noexec nosuid",
"chown system log /sys/fs/pstore",
"chmod 0550 /sys/fs/pstore",
"chown system log /sys/fs/pstore/console-ramoops",
"chmod 0440 /sys/fs/pstore/console-ramoops",
"chown system log /sys/fs/pstore/console-ramoops-0",
"chmod 0440 /sys/fs/pstore/console-ramoops-0",
"chown system log /sys/fs/pstore/pmsg-ramoops-0",
"chmod 0440 /sys/fs/pstore/pmsg-ramoops-0",
"write /proc/sys/abi/swp 1",
"symlink /proc/self/fd /dev/fd",
"export DOWNLOAD_CACHE /data/cache",
"setrlimit RLIMIT_NICE 40 40",
"setrlimit RLIMIT_NOFILE 32768 32768",
"write /sys/class/leds/vibrator/trigger transient",
"write /dev/cpu_variant:${ro.bionic.arch} ${ro.bionic.cpu_variant}",
"chmod 0444 /dev/cpu_variant:${ro.bionic.arch}",
"write /dev/cpu_variant:${ro.bionic.2nd_arch} ${ro.bionic.2nd_cpu_variant}",
"chmod 0444 /dev/cpu_variant:${ro.bionic.2nd_arch}",
"chown system system /sys/power/state",
"chown system system /sys/power/wakeup_count",
"chmod 0660 /sys/power/state",
......@@ -182,6 +149,7 @@
}, {
"name" : "load_persist_props_action",
"cmds" : [
"mkdir /data/parameters 0770 root root",
"load_persist_params load_persist_params"
]
}, {
......@@ -205,27 +173,14 @@
}, {
"name" : "post-fs",
"cmds" : [
"exec - system system -- /system/bin/vdc checkpoint markBootAttempt",
"mount rootfs rootfs / remount bind ro nodev",
"mount none /mnt/runtime/default /storage bind rec",
"mount none none /storage slave rec",
"chown system cache /cache",
"chmod 0770 /cache",
"mkdir /cache/recovery 0770 system cache",
"mkdir /cache/backup_stage 0700 system system",
"mkdir /cache/backup 0700 system system",
"chown root log /proc/vmallocinfo",
"chmod 0440 /proc/vmallocinfo",
"chown root log /proc/slabinfo",
"chmod 0440 /proc/slabinfo",
"chown root system /proc/kmsg",
"chmod 0440 /proc/kmsg",
"chown root system /proc/sysrq-trigger",
"chmod 0220 /proc/sysrq-trigger",
"chown system log /proc/last_kmsg",
"chmod 0440 /proc/last_kmsg",
"chmod 0444 /sys/fs/selinux/policy",
"mkdir /cache/lost+found 0770 root root"
"chmod 0444 /sys/fs/selinux/policy"
]
}, {
"name" : "late-fs",
......@@ -325,6 +280,7 @@
"mkdir /data/cache/recovery 0770 system cache",
"mkdir /data/cache/backup_stage 0700 system system",
"mkdir /data/cache/backup 0700 system system",
"mkdir /data/init_agent 0776 shell shell",
"setparam sys.use_memfd false",
"chown root system /dev/fscklogs/log",
"chmod 0770 /dev/fscklogs/log"
......@@ -346,11 +302,6 @@
"write /proc/sys/vm/dirty_expire_centisecs 200",
"write /proc/sys/vm/dirty_background_ratio 5",
"write /sys/fs/f2fs/${dev.mnt.blk.data}/cp_interval 200",
"chown radio system /sys/android_power/state",
"chown radio system /sys/android_power/request_state",
"chown radio system /sys/android_power/acquire_full_wake_lock",
"chown radio system /sys/android_power/acquire_partial_wake_lock",
"chown radio system /sys/android_power/release_wake_lock",
"chown system system /sys/power/autosleep",
"chown radio wakelock /sys/power/wake_lock",
"chown radio wakelock /sys/power/wake_unlock",
......
# 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.
build_version = 2.0
# whether ohos is enabled.
hw_sc.build.os.enable=true
# ohos API version number.
hw_sc.build.os.apiversion=6
# ohos system version.
hw_sc.build.os.version=2.2.0
# ohos device type please use hw_sc.build.os.devicetype
# ohos release type
hw_sc.build.os.releasetype=Canary1
ro.actionable_compatible_property.enabled=false
ro.postinstall.fstab.prefix=/system
ro.secure=1
security.perf_harden=1
ro.allow.mock.location=0
ro.debuggable=1
ro.build.characteristics="default"
ro.product.model="ohos"
ro.product.name="OpenHarmony 2.0 Canary"
persist.sys.usb.config=hdc
# 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.
build_version root:root:0777
hw_sc.build.os.enable root:root:0777
hw_sc.build.os.apiversion root:root:0777
hw_sc.build.os.version root:root:0777
hw_sc.build.os.releasetype root:root:0777
const.actionable_compatible_property.enabled root:root:0777
const.postinstall.fstab.prefix root:root:0777
const.secure root:root:0777
security.perf_harden root:root:0777
const.allow.mock.location root:root:0777
const.debuggable root:root:0777
persist.sys.usb.config root:root:0777
# default forbit other user to start service
ohos.servicectrl. root:root:0777
test.permission. root:root:0770
test.permission.read. root:root:0774
test.permission.write. root:root:0772
test.permission.watcher. root:root:0771
\ No newline at end of file
......@@ -52,13 +52,15 @@ struct CmdArgs {
int GetParamValue(const char *symValue, char *paramValue, unsigned int paramLen);
struct CmdArgs* GetCmd(const char *cmdContent, const char *delim, int argsCount);
void FreeCmd(struct CmdArgs **cmd);
void FreeCmd(struct CmdArgs *cmd);
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);
const char *GetMatchCmd(const char *cmdStr, unsigned int *index);
const char *GetCmdKey(unsigned int index);
#ifdef __cplusplus
#if __cplusplus
}
......
......@@ -12,8 +12,10 @@
* 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
#ifndef BASE_STARTUP_INITLITE_IMPORT_H
#define BASE_STARTUP_INITLITE_IMPORT_H
#include "cJSON.h"
void ParseAllImports(const cJSON *root);
#endif
......@@ -36,8 +36,8 @@ typedef struct {
void ParseAllJobs(const cJSON* fileRoot);
void DoJob(const char* jobName);
void ReleaseAllJobs();
void DumpAllJobs();
void ReleaseAllJobs(void);
void DumpAllJobs(void);
#ifdef __cplusplus
#if __cplusplus
}
......
......@@ -39,6 +39,7 @@ extern "C" {
#define SERVICE_ATTR_CRITICAL 0x020 // critical, will reboot if it crash 4 times in 4 minutes
#define SERVICE_ATTR_DISABLED 0x040 // disabled
#define SERVICE_ATTR_CONSOLE 0x080 // console
#define SERVICE_ATTR_DYNAMIC 0x100 // dynamic service
#define MAX_SERVICE_NAME 32
#define MAX_WRITEPID_FILES 100
......
......@@ -36,15 +36,15 @@ extern "C" {
#define MAX_SERVICES_CNT_IN_FILE 100
void RegisterServices(Service* services, int servicesCnt);
void StartServiceByName(const char* serviceName);
void StopServiceByName(const char* serviceName);
void StopAllServices();
void StopAllServicesBeforeReboot();
void RegisterServices(Service *services, int servicesCnt);
void StartServiceByName(const char *serviceName, bool checkDynamic);
void StopServiceByName(const char *serviceName);
void StopAllServices(void);
void StopAllServicesBeforeReboot(void);
void ReapServiceByPID(int pid);
void ParseAllServices(const cJSON* fileRoot);
void ParseAllServices(const cJSON *fileRoot);
#ifdef OHOS_SERVICE_DUMP
void DumpAllServices();
void DumpAllServices(void);
#endif
#ifdef __cplusplus
#if __cplusplus
......
......@@ -23,8 +23,7 @@
#define MAX_SOCK_NAME_LEN 16
#define SOCK_OPT_NUMS 6
enum SockOptionTab
{
enum SockOptionTab {
SERVICE_SOCK_NAME = 0,
SERVICE_SOCK_TYPE,
SERVICE_SOCK_PERM,
......@@ -34,8 +33,7 @@ enum SockOptionTab
};
struct ServiceSocket;
struct ServiceSocket
{
struct ServiceSocket {
char *name; // service name
int type; // socket type
uid_t uid; // uid
......
......@@ -16,6 +16,8 @@
#ifndef INIT_UTILS_H
#define INIT_UTILS_H
#include <unistd.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
......@@ -26,12 +28,12 @@ extern "C" {
#define OCTAL_BASE 8
#define DECIMAL_BASE 10
int DecodeUid(const char *name);
void CheckAndCreateDir(const char *fileName);
#define ARRAY_LENGTH(array) (sizeof((array)) / sizeof((array)[0]))
uid_t DecodeUid(const char *name);
char* ReadFileToBuf(const char *configFile);
int SplitString(char *srcPtr, char **dstPtr, int maxNum);
void WaitForFile(const char *source, unsigned int maxCount);
size_t WriteAll(int fd, char *buffer, size_t size);
#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_LIST_H
#define BASE_STARTUP_INITLITE_LIST_H
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
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)))
#define ForEachListEntry(list, node) \
(for (node = (list)->next; node != (list); node = node->next))
void ListInit(struct ListNode *list);
void ListAddTail(struct ListNode *list, struct ListNode *item);
void ListRemove(struct ListNode *item);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // BASE_STARTUP_INITLITE_LIST_H
......@@ -15,62 +15,50 @@
#ifndef BASE_STARTUP_INIT_PARAM_H
#define BASE_STARTUP_INIT_PARAM_H
#include <stdint.h>
#include <stdio.h>
#include "cJSON.h"
#include "sys_param.h"
#include "cJSON.h"
#include "param.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef enum {
EVENT_PROPERTY, // 参数修改事件
EVENT_BOOT
} EventType;
/**
* Init 接口
* 初始化参数服务
*
*/
void InitParamService();
void InitParamService(void);
/**
* Init 接口
* 启动参数服务,在main启动的最后调用,阻赛当前线程
*
*/
int StartParamService();
int StartParamService(void);
/**
* Init 接口
* 停止参数服务
*
*/
void StopParamService();
void StopParamService(void);
/**
* Init 接口
* 加载默认的参数值
*
*/
int LoadDefaultParams(const char *fileName);
/**
* Init 接口
* 安全使用,加载参数的信息,包括selinux label 等
*
*/
int LoadParamInfos(const char *fileName);
int LoadDefaultParams(const char *fileName, int mode);
/**
* Init 接口
* 加载默认参数。
*
*/
int LoadPersistParams();
int LoadPersistParams(void);
/**
* Init 接口
......@@ -91,28 +79,21 @@ int SystemReadParam(const char *name, char *value, unsigned int *len);
* 触发一个trigger操作。
*
*/
void PostTrigger(EventType type, const char *content, u_int32_t contentLen);
/**
* 对Init接口
* 触发一个参数trigger操作。
*
*/
void PostParamTrigger(const char *name, const char *value);
void PostTrigger(EventType type, const char *content, uint32_t contentLen);
/**
* 对Init接口
* 解析trigger文件。
*
*/
int ParseTriggerConfig(cJSON *fileRoot);
int ParseTriggerConfig(const cJSON *fileRoot);
/**
* 对Init接口
* 按名字执行对应的trigger。
*
*/
void DoTriggerExec(const char *content);
void DoTriggerExec(const char *triggerName);
/**
* 对Init接口
......
/*
* Copyright (c) 2020 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef BASE_STARTUP_PARAM_H
#define BASE_STARTUP_PARAM_H
#include <stdint.h>
#include <stdio.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#define PARAM_CONST_VALUE_LEN_MAX 4096
#define PARAM_VALUE_LEN_MAX 96
#define PARAM_NAME_LEN_MAX 96
typedef uint32_t ParamHandle;
typedef enum {
PARAM_CODE_ERROR = -1,
PARAM_CODE_SUCCESS = 0,
PARAM_CODE_INVALID_PARAM = 100,
PARAM_CODE_INVALID_NAME,
PARAM_CODE_INVALID_VALUE,
PARAM_CODE_REACHED_MAX,
PARAM_CODE_NOT_SUPPORT,
PARAM_CODE_TIMEOUT,
PARAM_CODE_NOT_FOUND,
PARAM_CODE_READ_ONLY,
PARAM_CODE_FAIL_CONNECT,
PARAM_CODE_MAX
} PARAM_CODE;
typedef enum {
EVENT_TRIGGER_PARAM,
EVENT_TRIGGER_BOOT,
EVENT_TRIGGER_PARAM_WAIT,
EVENT_TRIGGER_PARAM_WATCH
} EventType;
#define LOAD_PARAM_NORMAL 0x00
#define LOAD_PARAM_ONLY_ADD 0x01
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif
\ No newline at end of file
......@@ -16,34 +16,18 @@
#ifndef BASE_STARTUP_SYS_PARAM_H
#define BASE_STARTUP_SYS_PARAM_H
#include <pthread.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include "param.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#define PARAM_VALUE_LEN_MAX 96
#define PARAM_NAME_LEN_MAX 96
typedef u_int32_t ParamHandle;
typedef struct {
u_int32_t serial;
ParamHandle handle;
char value[PARAM_VALUE_LEN_MAX];
} ParamCacheNode;
typedef const char *(*ParamEvaluatePtr)(u_int32_t cacheCount, ParamCacheNode *node);
typedef struct {
pthread_mutex_t lock;
u_int32_t serial;
u_int32_t cacheCount;
ParamEvaluatePtr evaluate;
ParamCacheNode *cacheNode;
} ParamCache;
#define DEFAULT_PARAM_WAIT_TIMEOUT 30 // 30s
#define DEFAULT_PARAM_SET_TIMEOUT 10 // 10s
/**
* 对外接口
......@@ -61,6 +45,21 @@ int SystemSetParameter(const char *name, const char *value);
*/
int SystemGetParameter(const char *name, char *value, unsigned int *len);
/**
* 对外接口
* 查询参数,主要用于其他进程使用,找到对应属性的handle。
*
*/
int SystemFindParameter(const char *name, ParamHandle *handle);
/**
* 对外接口
* 根据handle获取对应数据的修改标识。
* commitId 获取计数变化
*
*/
int SystemGetParameterCommitId(ParamHandle handle, uint32_t *commitId);
/**
* 外部接口
* 遍历参数。
......@@ -83,6 +82,19 @@ int SystemGetParameterName(ParamHandle handle, char *name, unsigned int len);
*
*/
int SystemGetParameterValue(ParamHandle handle, char *value, unsigned int *len);
/**
* 外部接口
* 等待某个参数值被修改,阻塞直到参数值被修改或超时
*
*/
int SystemWaitParameter(const char *name, const char *value, int32_t timeout);
typedef void (*ParameterChangePtr)(const char *key, const char *value, void *context);
int SystemWatchParameter(const char *keyprefix, ParameterChangePtr change, void *context);
void SystemDumpParameters(int verbose);
#ifdef __cplusplus
#if __cplusplus
}
......
......@@ -25,4 +25,13 @@ if (defined(ohos_lite)) {
part_name = "startup"
subsystem_name = "startup"
}
ohos_static_library("agent_log") {
sources = [ "init_log.c" ]
deps = [ "//third_party/bounds_checking_function:libsec_static" ]
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
defines = [ "INIT_AGENT" ]
part_name = "startup"
subsystem_name = "startup"
}
}
......@@ -65,6 +65,7 @@ void InitToHiLog(LogLevel logLevel, const char *fmt, ...)
}
#endif
#ifndef INIT_AGENT // for init
static int g_fd = -1;
void OpenLogDevice(void)
{
......@@ -126,3 +127,41 @@ void InitLog(InitLogLevel logLevel, const char *fileName, int line, const char *
}
return;
}
#else // for other process
static FILE *g_outfile = NULL;
void InitLog(InitLogLevel logLevel, const char *fileName, int line, const char *kLevel,
const char *fmt, ...)
{
if (logLevel < g_logLevel) {
return;
}
time_t second = time(0);
if (second < 0) {
return;
}
struct tm *t = localtime(&second);
if (t == NULL) {
return;
}
if (g_outfile == NULL) {
chmod(PARAM_AGENT_LOG_PATH, S_IRWXU | S_IRWXG | S_IRWXO);
g_outfile = fopen(PARAM_AGENT_LOG_PATH, "w+");
}
if (g_outfile == NULL) {
fprintf(stdout, "%s[%d-%d-%d %d:%d:%d][pid=%d][%s:%d][%s][%s] ", kLevel, (t->tm_year + BASE_YEAR),
(t->tm_mon + 1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, gettid(), fileName,
line, INIT_LOG_TAG, LOG_LEVEL_STR[logLevel]);
printf("output %s error: %s \n", fmt, strerror(errno));
return;
}
fprintf(g_outfile, "%s[%d-%d-%d %d:%d:%d][pid=%d][%s:%d][%s][%s] ", kLevel, (t->tm_year + BASE_YEAR),
(t->tm_mon + 1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, getpid(), fileName,
line, INIT_LOG_TAG, LOG_LEVEL_STR[logLevel]);
va_list list;
va_start(list, fmt);
vfprintf(g_outfile, fmt, list);
va_end(list);
fflush(g_outfile);
}
#endif
\ No newline at end of file
......@@ -69,10 +69,36 @@ void SetHiLogLevel(LogLevel logLevel);
#define INIT_LOGE(fmt, ...) InitLog(INIT_ERROR, (FILE_NAME), (__LINE__), "<3>", fmt"\n", ##__VA_ARGS__)
#define INIT_LOGF(fmt, ...) InitLog(INIT_FATAL, (FILE_NAME), (__LINE__), "<3>", fmt"\n", ##__VA_ARGS__)
#ifndef INIT_AGENT
#define STARTUP_LOGD(LABEL, fmt, ...) InitLog(INIT_DEBUG, (FILE_NAME), (__LINE__), "<7>", fmt "\n", ##__VA_ARGS__)
#define STARTUP_LOGI(LABEL, fmt, ...) InitLog(INIT_INFO, (FILE_NAME), (__LINE__), "<6>", fmt "\n", ##__VA_ARGS__)
#define STARTUP_LOGE(LABEL, fmt, ...) InitLog(INIT_ERROR, (FILE_NAME), (__LINE__), "<3>", fmt "\n", ##__VA_ARGS__)
#else
#include "hilog/log.h"
#define PARAM_AGENT_LOG_PATH "/data/init_agent/init_agent.log"
#define STARTUP_LOGD(LABEL, fmt, ...) \
do { \
InitLog(INIT_DEBUG, (FILE_NAME), (__LINE__), "", fmt "\n", ##__VA_ARGS__); \
(void)HiLogPrint(LOG_APP, LOG_DEBUG, LOG_DOMAIN, LABEL, "[%{public}s(%{public}d)] " fmt, \
(FILE_NAME), (__LINE__), ##__VA_ARGS__); \
} while (0)
#define STARTUP_LOGI(LABEL, fmt, ...) \
do { \
InitLog(INIT_INFO, (FILE_NAME), (__LINE__), "", fmt "\n", ##__VA_ARGS__); \
(void)HiLogPrint(LOG_APP, LOG_INFO, LOG_DOMAIN, LABEL, "[%{public}s(%{public}d)] " fmt, \
FILE_NAME, __LINE__, ##__VA_ARGS__); \
} while (0)
#define STARTUP_LOGE(LABEL, fmt, ...) \
do { \
InitLog(INIT_ERROR, (FILE_NAME), (__LINE__), "", fmt "\n", ##__VA_ARGS__); \
(void)HiLogPrint(LOG_APP, LOG_ERROR, LOG_DOMAIN, LABEL, "[%{public}s(%{public}d)] " fmt, \
FILE_NAME, __LINE__, ##__VA_ARGS__); \
} while (0)
#endif
void InitLog(InitLogLevel logLevel, const char *fileName, int line, const char *kLevel, const char *fmt, ...);
void SetLogLevel(InitLogLevel logLevel);
......@@ -117,6 +143,13 @@ void EnableDevKmsg(void);
} \
} while (0)
#define INIT_CHECK_ONLY_ELOG(ret, format, ...) \
do { \
if (!(ret)) { \
INIT_LOGE(format, ##__VA_ARGS__); \
} \
} while (0)
#ifdef __cplusplus
#if __cplusplus
}
......
......@@ -12,12 +12,29 @@
# limitations under the License.
import("//build/ohos.gni")
ohos_static_library("paramservice") {
declare_args() {
param_security = "dac"
}
ohos_prebuilt_etc("param_watcher.rc") {
if (use_musl) {
source = "watcher/etc/param_watcher.cfg"
} else {
source = "watcher/etc/param_watcher.rc"
}
relative_install_dir = "init"
part_name = "init"
}
ohos_static_library("param_service") {
sources = [
"//base/startup/init_lite/services/src/init_utils.c",
"manager/param_cache.c",
"//base/startup/init_lite/services/src/list.c",
"adapter/param_libuvadp.c",
"adapter/param_persistadp.c",
"manager/param_manager.c",
"manager/param_message.c",
"manager/param_trie.c",
"manager/param_utils.c",
"service/param_persist.c",
"service/param_service.c",
"trigger/trigger_checker.c",
......@@ -27,6 +44,7 @@ ohos_static_library("paramservice") {
include_dirs = [
"include",
"adapter",
"//base/startup/init_lite/services/include/param",
"//base/startup/init_lite/services/include",
"//base/startup/init_lite/services/log",
......@@ -34,6 +52,16 @@ ohos_static_library("paramservice") {
"//third_party/cJSON",
]
defines = [ "PARAM_SUPPORT_SAVE_PERSIST" ]
if (param_security == "selinux") {
sources += [ "adapter/param_selinux.c" ]
defines += [ "PARAM_SUPPORT_SELINUX" ]
} else {
sources += [ "adapter/param_dac.c" ]
defines += [ "PARAM_SUPPORT_DAC" ]
}
deps = [
"//third_party/bounds_checking_function:libsec_static",
"//third_party/libuv:uv_static",
......@@ -42,13 +70,13 @@ ohos_static_library("paramservice") {
subsystem_name = "startup"
}
ohos_static_library("paramclient") {
ohos_shared_library("param_client") {
sources = [
"//base/startup/init_lite/services/src/init_utils.c",
"client/param_request.c",
"manager/param_cache.c",
"manager/param_manager.c",
"manager/param_message.c",
"manager/param_trie.c",
"manager/param_utils.c",
]
include_dirs = [
......@@ -56,49 +84,132 @@ ohos_static_library("paramclient") {
"//base/startup/init_lite/services/include/param",
"//base/startup/init_lite/services/include",
"//base/startup/init_lite/services/log",
"//base/hiviewdfx/hilog/interfaces/native/innerkits/include",
"//third_party/libuv/include",
"//third_party/cJSON",
]
defines = [ "INIT_AGENT" ]
if (param_security == "selinux") {
sources += [ "adapter/param_selinux.c" ]
defines += [ "PARAM_SUPPORT_SELINUX" ]
} else {
sources += [ "adapter/param_dac.c" ]
defines += [ "PARAM_SUPPORT_DAC" ]
}
deps = [
"//base/startup/init_lite/services/log:init_log",
"//base/startup/init_lite/services/log:agent_log",
"//third_party/bounds_checking_function:libsec_static",
"//third_party/libuv:uv_static",
]
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
part_name = "init"
subsystem_name = "startup"
}
ohos_executable("getparam") {
sources = [ "cmd/param_get.c" ]
ohos_shared_library("param_watcheragent") {
sources = [
"watcher/agent/watcher.cpp",
"watcher/agent/watcher_manager_kits.cpp",
"watcher/agent/watcher_manager_proxy.cpp",
"watcher/agent/watcher_stub.cpp",
]
include_dirs = [
"include",
"//base/startup/init_lite/services/include/param",
"//base/startup/init_lite/services/param/watcher/include",
"//base/startup/init_lite/services/param/watcher/agent",
"//base/startup/init_lite/services/include",
"//base/startup/init_lite/services/log",
"//base/update/updateservice/interfaces/innerkits/include",
]
defines = [ "INIT_AGENT" ]
deps = [
"//base/startup/init_lite/services/param:paramclient",
"//base/startup/init_lite/services/log:agent_log",
"//base/startup/init_lite/services/param:param_client",
"//third_party/bounds_checking_function:libsec_static",
"//third_party/cJSON:cjson_static",
"//utils/native/base:utils",
]
install_enable = true
external_deps = [
"hiviewdfx_hilog_native:libhilog",
"ipc:ipc_core",
"safwk:system_ability_fwk",
"samgr_L2:samgr_proxy",
]
part_name = "init"
}
ohos_executable("setparam") {
sources = [ "cmd/param_set.c" ]
ohos_shared_library("param_watcher") {
sources = [
"watcher/proxy/watcher_manager.cpp",
"watcher/proxy/watcher_manager_stub.cpp",
"watcher/proxy/watcher_proxy.cpp",
]
include_dirs = [
"include",
"//base/startup/init_lite/services/include/param",
"//base/startup/init_lite/services/param/watcher/proxy",
"//base/startup/init_lite/services/param/watcher/include",
"//base/startup/init_lite/services/include",
"//base/startup/init_lite/services/log",
"//third_party/libuv/include",
"//third_party/cJSON",
"//utils/native/base/include",
"//utils/system/safwk/native/include",
"//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include",
"//foundation/distributedschedule/safwk/services/safwk/include",
"//foundation/distributedschedule/safwk/interfaces/innerkits/safwk",
"//foundation/distributedschedule/samgr/adapter/interfaces/innerkits/include",
"//foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include",
]
defines = [ "INIT_AGENT" ]
deps = [
"//base/startup/init_lite/services/log:agent_log",
"//base/startup/init_lite/services/param:param_client",
"//third_party/bounds_checking_function:libsec_static",
"//utils/native/base:utils",
]
external_deps = [
"hiviewdfx_hilog_native:libhilog",
"ipc:ipc_core",
"safwk:system_ability_fwk",
"samgr_L2:samgr_proxy",
]
install_images = [ "system" ]
part_name = "init"
}
ohos_executable("param") {
sources = [ "cmd/param_cmd.c" ]
include_dirs = [
"include",
"//base/startup/init_lite/services/include/param",
"//base/startup/init_lite/services/include",
"//base/startup/init_lite/services/log",
"//base/update/updateservice/interfaces/innerkits/include",
]
defines = [
"PARAM_TEST",
"INIT_AGENT",
]
deps = [
"//base/startup/init_lite/services/param:paramclient",
"//base/startup/init_lite/services/log:agent_log",
"//base/startup/init_lite/services/param:param_client",
"//base/startup/init_lite/services/param:param_watcheragent",
"//base/update/updateservice/interfaces/innerkits/engine:updateservicekits",
"//third_party/bounds_checking_function:libsec_static",
"//third_party/cJSON:cjson_static",
]
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
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 <grp.h>
#include <pwd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "param_security.h"
#include "param_utils.h"
#define OCT_BASE 8
#define LABEL "PARAM_DAC"
static ParamSecurityLabel g_localSecurityLabel = {};
static void GetUserIdByName(FILE *fp, uid_t *uid, const char *name, uint32_t nameLen)
{
*uid = -1;
(void)fseek(fp, 0, SEEK_SET);
struct passwd *data = NULL;
while ((data = fgetpwent(fp)) != NULL) {
if (strlen(data->pw_name) == nameLen && strncmp(data->pw_name, name, nameLen) == 0) {
*uid = data->pw_uid;
return;
}
}
}
static void GetGroupIdByName(FILE *fp, gid_t *gid, const char *name, uint32_t nameLen)
{
*gid = -1;
(void)fseek(fp, 0, SEEK_SET);
struct group *data = NULL;
while ((data = fgetgrent(fp)) != NULL) {
if (strlen(data->gr_name) == nameLen && strncmp(data->gr_name, name, nameLen) == 0) {
*gid = data->gr_gid;
break;
}
}
}
// user:group:r|w
static int GetParamDacData(FILE *fpForGroup, FILE *fpForUser, ParamDacData *dacData, const char *value)
{
char *groupName = strstr(value, ":");
if (groupName == NULL) {
return -1;
}
char *mode = strstr(groupName + 1, ":");
if (mode == NULL) {
return -1;
}
GetUserIdByName(fpForUser, &dacData->uid, value, groupName - value);
GetGroupIdByName(fpForGroup, &dacData->gid, groupName + 1, mode - groupName - 1);
dacData->mode = strtol(mode + 1, NULL, OCT_BASE);
return 0;
}
static int InitLocalSecurityLabel(ParamSecurityLabel **security, int isInit)
{
UNUSED(isInit);
PARAM_LOGD("InitLocalSecurityLabel uid:%d gid:%d euid: %d egid: %d ", getuid(), getgid(), geteuid(), getegid());
g_localSecurityLabel.cred.pid = getpid();
g_localSecurityLabel.cred.uid = geteuid();
g_localSecurityLabel.cred.gid = getegid();
*security = &g_localSecurityLabel;
// support check write permission in client
(*security)->flags |= LABEL_CHECK_FOR_ALL_PROCESS;
return 0;
}
static int FreeLocalSecurityLabel(ParamSecurityLabel *srcLabel)
{
return 0;
}
static int EncodeSecurityLabel(const ParamSecurityLabel *srcLabel, char *buffer, uint32_t *bufferSize)
{
PARAM_CHECK(bufferSize != NULL, return -1, "Invalid param");
if (buffer == NULL) {
*bufferSize = sizeof(ParamSecurityLabel);
return 0;
}
PARAM_CHECK(*bufferSize >= sizeof(ParamSecurityLabel), return -1, "Invalid buffersize %u", *bufferSize);
*bufferSize = sizeof(ParamSecurityLabel);
return memcpy_s(buffer, *bufferSize, srcLabel, sizeof(ParamSecurityLabel));
}
static int DecodeSecurityLabel(ParamSecurityLabel **srcLabel, char *buffer, uint32_t bufferSize)
{
PARAM_CHECK(bufferSize >= sizeof(ParamSecurityLabel), return -1, "Invalid buffersize %u", bufferSize);
PARAM_CHECK(srcLabel != NULL && buffer != NULL, return -1, "Invalid param");
*srcLabel = (ParamSecurityLabel *)buffer;
return 0;
}
static int LoadParamLabels(const char *fileName, SecurityLabelFunc label, void *context)
{
FILE *fpForGroup = fopen(GROUP_FILE_PATH, "r");
FILE *fpForUser = fopen(USER_FILE_PATH, "r");
FILE *fp = fopen(fileName, "r");
SubStringInfo *info = malloc(sizeof(SubStringInfo) * SUBSTR_INFO_DAC + 1);
PARAM_CHECK(fpForGroup != NULL && fpForUser != NULL && fp != NULL && info != NULL,
goto exit, "Can not open file for load param labels");
uint32_t infoCount = 0;
char buff[PARAM_BUFFER_SIZE];
ParamAuditData auditData = {};
while (fgets(buff, PARAM_BUFFER_SIZE, fp) != NULL) {
int subStrNumber = GetSubStringInfo(buff, strlen(buff), ' ', info, SUBSTR_INFO_DAC + 1);
if (subStrNumber <= SUBSTR_INFO_DAC) {
continue;
}
auditData.name = info[SUBSTR_INFO_NAME].value;
#ifdef STARTUP_INIT_TEST
auditData.label = info[SUBSTR_INFO_NAME].value;
#endif
int ret = GetParamDacData(fpForGroup, fpForUser, &auditData.dacData, info[SUBSTR_INFO_DAC].value);
PARAM_CHECK(ret == 0, continue, "Failed to get param info %d %s", ret, buff);
ret = label(&auditData, context);
PARAM_CHECK(ret == 0, continue, "Failed to write param info %d %s", ret, buff);
infoCount++;
}
PARAM_LOGI("Load parameter label total %u success %s", infoCount, fileName);
exit:
if (fp) {
(void)fclose(fp);
}
if (info) {
free(info);
}
if (fpForGroup) {
(void)fclose(fpForGroup);
}
if (fpForUser) {
(void)fclose(fpForUser);
}
return 0;
}
static int ProcessParamFile(const char *fileName, void *context)
{
LabelFuncContext *cxt = (LabelFuncContext *)context;
return LoadParamLabels(fileName, cxt->label, cxt->context);
}
static int GetParamSecurityLabel(SecurityLabelFunc label, const char *path, void *context)
{
PARAM_CHECK(label != NULL && path != NULL, return -1, "Invalid param");
struct stat st;
LabelFuncContext cxt = {label, context};
if ((stat(path, &st) == 0) && !S_ISDIR(st.st_mode)) {
return ProcessParamFile(path, &cxt);
}
return ReadFileInDir(path, ".para.dac", ProcessParamFile, &cxt);
}
static int CheckFilePermission(const ParamSecurityLabel *localLabel, const char *fileName, int flags)
{
UNUSED(flags);
PARAM_CHECK(localLabel != NULL && fileName != NULL, return -1, "Invalid param");
return 0;
}
static int CheckParamPermission(const ParamSecurityLabel *srcLabel, const ParamAuditData *auditData, int mode)
{
int ret = DAC_RESULT_FORBIDED;
PARAM_CHECK(srcLabel != NULL && auditData != NULL && auditData->name != NULL, return ret, "Invalid param");
PARAM_CHECK((mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) != 0, return ret, "Invalid mode %x", mode);
/**
* DAC group 实现的label的定义
* user:group:read|write|watch
*/
uint32_t localMode = 0;
if (srcLabel->cred.uid == auditData->dacData.uid) {
localMode = mode & (DAC_READ | DAC_WRITE | DAC_WATCH);
} else if (srcLabel->cred.gid == auditData->dacData.gid) {
localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_GROUP_START;
} else {
localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_OTHER_START;
}
if ((auditData->dacData.mode & localMode) != 0) {
ret = DAC_RESULT_PERMISSION;
}
PARAM_LOGD("Src label %d %d ", srcLabel->cred.gid, srcLabel->cred.uid);
PARAM_LOGD("auditData label %d %d mode %o lable %s",
auditData->dacData.gid, auditData->dacData.uid, auditData->dacData.mode, auditData->label);
PARAM_LOGD("%s check %o localMode %o ret %d", auditData->name, mode, localMode, ret);
return ret;
}
PARAM_STATIC int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit)
{
PARAM_CHECK(ops != NULL, return -1, "Invalid param");
PARAM_LOGI("RegisterSecurityDacOps %d", isInit);
ops->securityGetLabel = NULL;
ops->securityDecodeLabel = NULL;
ops->securityEncodeLabel = NULL;
ops->securityInitLabel = InitLocalSecurityLabel;
ops->securityCheckFilePermission = CheckFilePermission;
ops->securityCheckParamPermission = CheckParamPermission;
ops->securityFreeLabel = FreeLocalSecurityLabel;
if (isInit) {
ops->securityGetLabel = GetParamSecurityLabel;
ops->securityDecodeLabel = DecodeSecurityLabel;
} else {
ops->securityEncodeLabel = EncodeSecurityLabel;
}
return 0;
}
#ifdef PARAM_SUPPORT_DAC
int RegisterSecurityOps(ParamSecurityOps *ops, int isInit)
{
return RegisterSecurityDacOps(ops, isInit);
}
#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.
*/
#include "param_libuvadp.h"
#include <sys/wait.h>
#define LABEL "Libuvadp"
static LibuvWorkSpace libuv = { NULL };
static const uint32_t RECV_BUFFER_MAX = 5 * 1024;
static LibuvBaseTask *CreateLibuvTask(uint32_t size, uint32_t flags, uint16_t userDataSize, TaskClose close)
{
PARAM_CHECK(size <= RECV_BUFFER_MAX, return NULL, "Invaid size %u", size);
PARAM_CHECK(userDataSize <= RECV_BUFFER_MAX, return NULL, "Invaid user size %u", userDataSize);
LibuvBaseTask *worker = (LibuvBaseTask *)malloc(size + userDataSize);
PARAM_CHECK(worker != NULL, return NULL, "Failed to create param woker");
worker->worker.flags = flags;
worker->userDataSize = userDataSize;
worker->userDataOffset = size;
worker->close = close;
return worker;
}
static void OnClientClose(uv_handle_t *handle)
{
PARAM_LOGD("OnClientClose handle: %p", handle);
PARAM_CHECK(handle != NULL, return, "Invalid handle");
LibuvStreamTask *worker = PARAM_ENTRY(handle, LibuvStreamTask, stream);
if (worker->base.close != NULL) {
worker->base.close((ParamTaskPtr)worker);
}
free(worker);
}
static void OnServerClose(uv_handle_t *handle)
{
PARAM_LOGD("OnServerClose handle: %p", handle);
PARAM_CHECK(handle != NULL, return, "Invalid handle");
LibuvServerTask *worker = PARAM_ENTRY(handle, LibuvServerTask, server);
if (worker->base.close != NULL) {
worker->base.close((ParamTaskPtr)worker);
}
free(worker);
}
static void OnTimerClose(uv_handle_t *handle)
{
PARAM_CHECK(handle != NULL, return, "Invalid handle");
LibuvTimerTask *worker = PARAM_ENTRY(handle, LibuvTimerTask, timer);
if (worker->base.close != NULL) {
worker->base.close((ParamTaskPtr)worker);
}
free(worker);
}
static void OnReceiveAlloc(uv_handle_t *handle, size_t suggestedSize, uv_buf_t *buf)
{
UNUSED(suggestedSize);
PARAM_CHECK(handle != NULL, return, "Invalid handle");
buf->len = RECV_BUFFER_MAX;
buf->base = (char *)malloc(buf->len);
}
static void OnWriteResponse(uv_write_t *req, int status)
{
UNUSED(status);
PARAM_CHECK(req != NULL, return, "Invalid req");
PARAM_LOGD("OnWriteResponse handle: %p", req);
}
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, OnClientClose);
if (buf != NULL) {
free(buf->base);
}
return;
}
LibuvStreamTask *client = PARAM_ENTRY(handle, LibuvStreamTask, stream);
if (client->recvMessage != NULL) {
client->recvMessage(&client->base.worker, (const ParamMessage *)buf->base);
}
free(buf->base);
}
static void OnAsyncCloseCallback(uv_handle_t *handle)
{
PARAM_CHECK(handle != NULL, return, "Invalid handle");
free(handle);
}
static void OnAsyncCallback(uv_async_t *handle)
{
PARAM_CHECK(handle != NULL, return, "Invalid handle");
LibuvAsyncEvent *event = (LibuvAsyncEvent *)handle;
if (event->task != NULL && event->task->process != NULL) {
event->task->process(event->eventId, event->content, event->contentSize);
}
uv_close((uv_handle_t *)handle, OnAsyncCloseCallback);
}
static void OnConnection(uv_stream_t *server, int status)
{
PARAM_CHECK(status >= 0, return, "Error status %d", status);
PARAM_CHECK(server != NULL, return, "Error server");
LibuvServerTask *pipeServer = PARAM_ENTRY(server, LibuvServerTask, server);
PARAM_LOGD("OnConnection pipeServer: %p pip %p", pipeServer, server);
if (pipeServer->incomingConnect) {
pipeServer->incomingConnect((ParamTaskPtr)pipeServer, 0);
}
}
static void LibuvFreeMsg(const ParamTaskPtr stream, const ParamMessage *msg)
{
PARAM_CHECK(stream != NULL, return, "Invalid stream");
PARAM_CHECK(msg != NULL, return, "Invalid msg");
ParamMessage *message = (ParamMessage *)msg;
free(message);
}
static int InitPipeSocket(uv_pipe_t *pipeServer)
{
uv_fs_t req;
uv_fs_unlink(uv_default_loop(), &req, PIPE_NAME, NULL);
int ret = uv_pipe_init(uv_default_loop(), pipeServer, 0);
PARAM_CHECK(ret == 0, return ret, "Failed to uv_pipe_init %d", ret);
ret = uv_pipe_bind(pipeServer, PIPE_NAME);
PARAM_CHECK(ret == 0, return ret, "Failed to uv_pipe_bind %d %s", ret, uv_err_name(ret));
ret = uv_listen((uv_stream_t *)pipeServer, SOMAXCONN, OnConnection);
PARAM_CHECK(ret == 0, return ret, "Failed to uv_listen %d %s", ret, uv_err_name(ret));
PARAM_CHECK(chmod(PIPE_NAME, S_IRWXU | S_IRWXG | S_IRWXO) == 0,
return -1, "Open file %s error %s", PIPE_NAME, strerror(errno));
return 0;
}
static void LibuvTimerCallback(uv_timer_t *handle)
{
PARAM_CHECK(handle != NULL, return, "Invalid handle");
LibuvTimerTask *timer = PARAM_ENTRY(handle, LibuvTimerTask, timer);
timer->timerProcess(&timer->base.worker, timer->context);
}
int ParamServerCreate(ParamTaskPtr *stream, const ParamStreamInfo *info)
{
PARAM_CHECK(stream != NULL && info != NULL, return -1, "Invalid param");
PARAM_CHECK(info->incomingConnect != NULL, return -1, "Invalid incomingConnect");
LibuvServerTask *worker = (LibuvServerTask *)CreateLibuvTask(
sizeof(LibuvServerTask), WORKER_TYPE_SERVER | info->flags, 0, info->close);
PARAM_CHECK(worker != NULL, return -1, "Failed to add param woker");
InitPipeSocket(&worker->server.pipe);
PARAM_LOGD("OnConnection pipeServer: %p pipe %p", worker, &worker->server.pipe);
worker->incomingConnect = info->incomingConnect;
*stream = &worker->base.worker;
return 0;
}
int ParamStreamCreate(ParamTaskPtr *stream, ParamTaskPtr server, const ParamStreamInfo *info, uint16_t userDataSize)
{
PARAM_CHECK(stream != NULL && info != NULL, return -1, "Invalid stream");
PARAM_CHECK(info->recvMessage != NULL, return -1, "Invalid recvMessage");
PARAM_CHECK(info->close != NULL, return -1, "Invalid close");
LibuvServerTask *pipeServer = (LibuvServerTask *)server;
LibuvStreamTask *client = (LibuvStreamTask *)CreateLibuvTask(sizeof(LibuvStreamTask),
info->flags | WORKER_TYPE_MSG, userDataSize, info->close);
PARAM_CHECK(client != NULL, return -1, "Failed to add client");
if (server != NULL) {
uv_pipe_t *pipe = &client->stream.pipe;
int ret = uv_pipe_init(uv_default_loop(), (uv_pipe_t *)pipe, 1);
PARAM_CHECK(ret == 0, free(client);
return -1, "Failed to uv_pipe_init %d", ret);
pipe->data = &pipeServer->server;
PARAM_LOGD("OnConnection pipeServer: %p pipe %p", pipeServer, &pipeServer->server);
if ((info->flags & WORKER_TYPE_TEST) != WORKER_TYPE_TEST) {
ret = uv_accept((uv_stream_t *)&pipeServer->server.pipe, (uv_stream_t *)pipe);
PARAM_CHECK(ret == 0, uv_close((uv_handle_t *)pipe, NULL);
free(client);
return -1, "Failed to uv_accept %d", ret);
ret = uv_read_start((uv_stream_t *)pipe, OnReceiveAlloc, OnReceiveRequest);
PARAM_CHECK(ret == 0, uv_close((uv_handle_t *)pipe, NULL);
free(client);
return -1, "Failed to uv_read_start %d", ret);
}
}
client->recvMessage = info->recvMessage;
*stream = &client->base.worker;
return 0;
}
void *ParamGetTaskUserData(ParamTaskPtr stream)
{
PARAM_CHECK(stream != NULL, return NULL, "Invalid stream");
if ((stream->flags & WORKER_TYPE_CLIENT) != WORKER_TYPE_CLIENT) {
return NULL;
}
LibuvStreamTask *client = (LibuvStreamTask *)stream;
if (client->base.userDataSize == 0) {
return NULL;
}
return (void *)(((char *)stream) + client->base.userDataOffset);
}
int ParamTaskSendMsg(const ParamTaskPtr stream, const ParamMessage *msg)
{
PARAM_CHECK(stream != NULL && msg != NULL, LibuvFreeMsg(stream, msg);
return -1, "Invalid stream");
LibuvStreamTask *worker = (LibuvStreamTask *)stream;
if ((stream->flags & WORKER_TYPE_MSG) != WORKER_TYPE_MSG) {
LibuvFreeMsg(stream, msg);
return -1;
}
if ((stream->flags & WORKER_TYPE_TEST) != WORKER_TYPE_TEST) {
uv_buf_t buf = uv_buf_init((char *)msg, msg->msgSize);
int ret = uv_write(&worker->writer, (uv_stream_t *)&worker->stream.pipe, &buf, 1, OnWriteResponse);
PARAM_CHECK(ret >= 0, LibuvFreeMsg(stream, msg);
return -1, "Failed to uv_write2 ret %s", uv_strerror(ret));
}
LibuvFreeMsg(stream, msg);
return 0;
}
int ParamEventTaskCreate(ParamTaskPtr *stream, EventProcess eventProcess, EventProcess eventBeforeProcess)
{
PARAM_CHECK(stream != NULL && eventProcess != NULL, return -1, "Invalid info or stream");
LibuvEventTask *worker = (LibuvEventTask *)CreateLibuvTask(sizeof(LibuvEventTask),
WORKER_TYPE_EVENT | WORKER_TYPE_ASYNC, 0, NULL);
PARAM_CHECK(worker != NULL, return -1, "Failed to alloc worker");
worker->process = eventProcess;
worker->beforeProcess = eventBeforeProcess;
*stream = &worker->base.worker;
return 0;
}
int ParamEventSend(ParamTaskPtr stream, uint64_t eventId, const char *content, uint32_t size)
{
PARAM_CHECK(stream != NULL, return -1, "Invalid stream");
PARAM_CHECK((stream->flags & WORKER_TYPE_EVENT) == WORKER_TYPE_EVENT, return -1, "Invalid stream type");
int ret = PARAM_CODE_INVALID_PARAM;
if (stream->flags & WORKER_TYPE_ASYNC) {
LibuvEventTask *worker = (LibuvEventTask *)stream;
LibuvAsyncEvent *event = (LibuvAsyncEvent *)malloc(sizeof(LibuvAsyncEvent) + size + 1);
PARAM_CHECK(event != NULL, return -1, "Failed to alloc event");
event->eventId = eventId;
event->contentSize = size + 1;
event->task = worker;
if (content != NULL) {
ret = memcpy_s(event->content, event->contentSize, content, size);
PARAM_CHECK(ret == EOK, free(event);
return -1, "Failed to memcpy content ");
event->content[size] = '\0';
}
uv_async_init(uv_default_loop(), &event->async, OnAsyncCallback);
if (worker->beforeProcess != NULL) {
worker->beforeProcess(eventId, content, size);
}
uv_async_send(&event->async);
ret = 0;
}
return ret;
}
int ParamTaskClose(ParamTaskPtr stream)
{
PARAM_CHECK(stream != NULL, return -1, "Invalid param");
if (stream->flags & WORKER_TYPE_TIMER) {
LibuvTimerTask *worker = (LibuvTimerTask *)stream;
uv_timer_stop(&worker->timer);
uv_close((uv_handle_t *)(&worker->timer), OnTimerClose);
} else if (stream->flags & WORKER_TYPE_SERVER) {
LibuvServerTask *worker = (LibuvServerTask *)stream;
uv_close((uv_handle_t *)(&worker->server.pipe), OnServerClose);
} else if (stream->flags & WORKER_TYPE_MSG) {
LibuvStreamTask *worker = (LibuvStreamTask *)stream;
uv_close((uv_handle_t *)(&worker->stream.pipe), OnClientClose);
} else if (stream->flags & WORKER_TYPE_EVENT) {
LibuvAsyncEvent *event = (LibuvAsyncEvent *)stream;
uv_close((uv_handle_t *)&event->async, OnAsyncCloseCallback);
} else {
free(stream);
}
return 0;
}
int ParamTimerCreate(ParamTaskPtr *timer, TimerProcess process, void *context)
{
PARAM_CHECK(timer != NULL && process != NULL, return -1, "Invalid timer");
LibuvTimerTask *worker = (LibuvTimerTask *)CreateLibuvTask(sizeof(LibuvTimerTask), WORKER_TYPE_TIMER, 0, NULL);
PARAM_CHECK(worker != NULL, return -1, "Failed to alloc timer worker");
worker->base.worker.flags = WORKER_TYPE_TIMER;
worker->timerProcess = process;
worker->context = context;
uv_timer_init(uv_default_loop(), &worker->timer);
*timer = &worker->base.worker;
return 0;
}
int ParamTimerStart(ParamTaskPtr timer, uint64_t timeout, uint64_t repeat)
{
PARAM_CHECK(timer != NULL, return -1, "Invalid timer");
if (timer->flags & WORKER_TYPE_TIMER) {
LibuvTimerTask *worker = (LibuvTimerTask *)timer;
uv_timer_start(&worker->timer, LibuvTimerCallback, timeout, repeat);
return 0;
}
return -1;
}
static void SignalHandler(uv_signal_t *handle, int signum)
{
UNUSED(handle);
if (signum != SIGCHLD) {
return;
}
pid_t pid = 0;
int procStat = 0;
while (1) {
pid = waitpid(-1, &procStat, WNOHANG);
if (pid <= 0) {
break;
}
}
if (libuv.pidDeleteProcess != NULL) {
libuv.pidDeleteProcess(pid);
}
}
int ParamServiceStart(ProcessPidDelete pidDelete)
{
libuv.pidDeleteProcess = pidDelete;
uv_signal_t sigchldHandler;
int ret = uv_signal_init(uv_default_loop(), &sigchldHandler);
int ret1 = uv_signal_start(&sigchldHandler, SignalHandler, SIGCHLD);
PARAM_CHECK(ret == 0 && ret1 == 0, return -1, "Failed to process signal ");
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
return 0;
}
int ParamServiceStop(void)
{
uv_fs_t req;
uv_fs_unlink(uv_default_loop(), &req, PIPE_NAME, NULL);
uv_stop(uv_default_loop());
return 0;
}
\ No newline at end of file
/*
* Copyright (c) 2020 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef BASE_STARTUP_PARAM_LIBUVADP_H
#define BASE_STARTUP_PARAM_LIBUVADP_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "param_message.h"
#include "param_utils.h"
#include "uv.h"
typedef struct {
ProcessPidDelete pidDeleteProcess;
} LibuvWorkSpace;
typedef struct {
ParamTask worker;
TaskClose close;
uint16_t userDataSize;
uint16_t userDataOffset;
} LibuvBaseTask;
typedef struct {
LibuvBaseTask base;
RecvMessage recvMessage;
union {
uv_pipe_t pipe;
} stream;
uv_write_t writer;
} LibuvStreamTask;
typedef struct {
LibuvBaseTask base;
IncomingConnect incomingConnect;
union {
uv_pipe_t pipe;
} server;
} LibuvServerTask;
typedef struct {
LibuvBaseTask base;
EventProcess process;
EventProcess beforeProcess;
} LibuvEventTask;
typedef struct {
uv_async_t async;
LibuvEventTask *task;
uint64_t eventId;
uint32_t contentSize;
char content[0];
} LibuvAsyncEvent;
typedef struct {
LibuvBaseTask base;
uv_timer_t timer;
TimerProcess timerProcess;
void *context;
} LibuvTimerTask;
#endif // BASE_STARTUP_PARAM_LIBUVADP_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 <errno.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include "param_persist.h"
#include "param_utils.h"
#define LABEL "PERSIST_ADP"
typedef struct {
void *context;
PersistParamGetPtr persistParamGet;
} PersistAdpContext;
static int LoadPersistParam(PersistParamGetPtr persistParamGet, void *context)
{
CheckAndCreateDir(PARAM_PERSIST_SAVE_PATH);
FILE *fp = fopen(PARAM_PERSIST_SAVE_TMP_PATH, "r");
if (fp == NULL) {
fp = fopen(PARAM_PERSIST_SAVE_PATH, "r");
PARAM_LOGI("LoadPersistParam open file %s", PARAM_PERSIST_SAVE_PATH);
}
PARAM_CHECK(fp != NULL, return -1, "No valid persist parameter file %s", PARAM_PERSIST_SAVE_PATH);
char *buff = (char *)malloc(PARAM_BUFFER_SIZE);
SubStringInfo *info = malloc(sizeof(SubStringInfo) * (SUBSTR_INFO_VALUE + 1));
while (info != NULL && buff != NULL && fgets(buff, PARAM_BUFFER_SIZE, fp) != NULL) {
int subStrNumber = GetSubStringInfo(buff, strlen(buff), '=', info, SUBSTR_INFO_VALUE + 1);
if (subStrNumber <= SUBSTR_INFO_VALUE) {
continue;
}
int ret = persistParamGet(info[0].value, info[1].value, context);
PARAM_CHECK(ret == 0, continue, "Failed to set param %d %s", ret, buff);
}
free(info);
free(buff);
(void)fclose(fp);
return 0;
}
static int BatchSavePersistParamBegin(PERSIST_SAVE_HANDLE *handle)
{
FILE *fp = fopen(PARAM_PERSIST_SAVE_TMP_PATH, "w");
PARAM_CHECK(fp != NULL, return -1, "Open file %s fail error %s", PARAM_PERSIST_SAVE_TMP_PATH, strerror(errno));
*handle = (PERSIST_SAVE_HANDLE)fp;
return 0;
}
static int BatchSavePersistParam(PERSIST_SAVE_HANDLE handle, const char *name, const char *value)
{
FILE *fp = (FILE *)handle;
int ret = fprintf(fp, "%s=%s\n", name, value);
PARAM_CHECK(ret > 0, return -1, "Failed to write param");
PARAM_LOGD("BatchSavePersistParam %s=%s", name, value);
return 0;
}
static void BatchSavePersistParamEnd(PERSIST_SAVE_HANDLE handle)
{
FILE *fp = (FILE *)handle;
(void)fclose(fp);
unlink(PARAM_PERSIST_SAVE_PATH);
int ret = rename(PARAM_PERSIST_SAVE_TMP_PATH, PARAM_PERSIST_SAVE_PATH);
PARAM_CHECK(ret == 0, return, "BatchSavePersistParamEnd %s fail error %s",
PARAM_PERSIST_SAVE_TMP_PATH, strerror(errno));
}
int RegisterPersistParamOps(PersistParamOps *ops)
{
ops->save = NULL;
ops->load = LoadPersistParam;
ops->batchSaveBegin = BatchSavePersistParamBegin;
ops->batchSave = BatchSavePersistParam;
ops->batchSaveEnd = BatchSavePersistParamEnd;
return 0;
}
\ No newline at end of file
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sys/stat.h>
#include "init_utils.h"
#include "param_security.h"
#include "param_utils.h"
#define LABEL "PARAM_SELINUX"
#define SELINUX_LABEL_LEN 128
typedef struct SELinuxSecurityLabel {
ParamSecurityLabel securityLabel;
char label[SELINUX_LABEL_LEN];
} SELinuxSecurityLabel;
static SELinuxSecurityLabel g_localSecurityLabel = {};
static int InitLocalSecurityLabel(ParamSecurityLabel **security, int isInit)
{
UNUSED(isInit);
PARAM_LOGI("TestDacGetLabel uid:%d gid:%d euid: %d egid: %d ", getuid(), getgid(), geteuid(), getegid());
g_localSecurityLabel.securityLabel.cred.pid = getpid();
g_localSecurityLabel.securityLabel.cred.uid = geteuid();
g_localSecurityLabel.securityLabel.cred.gid = getegid();
*security = &g_localSecurityLabel.securityLabel;
return 0;
}
static int FreeLocalSecurityLabel(ParamSecurityLabel *srcLabel)
{
return 0;
}
static int EncodeSecurityLabel(const ParamSecurityLabel *srcLabel, char *buffer, uint32_t *bufferSize)
{
PARAM_CHECK(bufferSize != NULL, return -1, "Invalid param");
if (buffer == NULL) {
*bufferSize = sizeof(SELinuxSecurityLabel);
return 0;
}
PARAM_CHECK(*bufferSize >= sizeof(SELinuxSecurityLabel), return -1, "Invalid buffersize %u", *bufferSize);
*bufferSize = sizeof(SELinuxSecurityLabel);
return memcpy_s(buffer, *bufferSize, srcLabel, sizeof(SELinuxSecurityLabel));
}
static int DecodeSecurityLabel(ParamSecurityLabel **srcLabel, char *buffer, uint32_t bufferSize)
{
PARAM_CHECK(bufferSize >= sizeof(SELinuxSecurityLabel), return -1, "Invalid buffersize %u", bufferSize);
PARAM_CHECK(srcLabel != NULL && buffer != NULL, return -1, "Invalid param");
*srcLabel = &((SELinuxSecurityLabel *)buffer)->securityLabel;
return 0;
}
static int LoadParamLabels(const char *fileName, SecurityLabelFunc label, void *context)
{
int ret = 0;
FILE *fp = fopen(fileName, "r");
PARAM_CHECK(fp != NULL, return -1, "Open file %s fail", fileName);
SubStringInfo *info = malloc(sizeof(SubStringInfo) * SUBSTR_INFO_DAC + 1);
char buff[PARAM_BUFFER_SIZE];
int infoCount = 0;
ParamAuditData auditData = {};
while (fgets(buff, PARAM_BUFFER_SIZE, fp) != NULL) {
int subStrNumber = GetSubStringInfo(buff, strlen(buff), ' ', info, SUBSTR_INFO_DAC + 1);
if (subStrNumber <= SUBSTR_INFO_DAC) {
continue;
}
auditData.name = info[SUBSTR_INFO_NAME].value;
auditData.label = info[SUBSTR_INFO_LABEL].value;
ret = label(&auditData, context);
PARAM_CHECK(ret == 0, continue, "Failed to write param info %d %s", ret, buff);
infoCount++;
}
(void)fclose(fp);
free(info);
PARAM_LOGI("Load parameter info %d success %s", infoCount, fileName);
return 0;
}
static int ProcessParamFile(const char *fileName, void *context)
{
LabelFuncContext *cxt = (LabelFuncContext *)context;
return LoadParamLabels(fileName, cxt->label, cxt->context);
}
static int GetParamSecurityLabel(SecurityLabelFunc label, const char *path, void *context)
{
PARAM_CHECK(label != NULL, return -1, "Invalid param");
int ret = 0;
struct stat st;
LabelFuncContext cxt = { label, context };
if ((stat(path, &st) == 0) && !S_ISDIR(st.st_mode)) {
ret = ProcessParamFile(path, &cxt);
} else {
ret = ReadFileInDir(path, ".para.selinux", ProcessParamFile, &cxt);
}
return ret;
}
static int CheckFilePermission(const ParamSecurityLabel *localLabel, const char *fileName, int flags)
{
UNUSED(flags);
PARAM_CHECK(localLabel != NULL && fileName != NULL, return -1, "Invalid param");
return 0;
}
static int CheckParamPermission(const ParamSecurityLabel *srcLabel, const ParamAuditData *auditData, int mode)
{
PARAM_LOGI("CheckParamPermission ");
PARAM_CHECK(srcLabel != NULL && auditData != NULL && auditData->name != NULL, return -1, "Invalid param");
return 0;
}
PARAM_STATIC int RegisterSecuritySelinuxOps(ParamSecurityOps *ops, int isInit)
{
PARAM_CHECK(ops != NULL, return -1, "Invalid param");
ops->securityGetLabel = NULL;
ops->securityDecodeLabel = NULL;
ops->securityEncodeLabel = NULL;
ops->securityInitLabel = InitLocalSecurityLabel;
ops->securityCheckFilePermission = CheckFilePermission;
ops->securityCheckParamPermission = CheckParamPermission;
ops->securityFreeLabel = FreeLocalSecurityLabel;
if (isInit) {
ops->securityGetLabel = GetParamSecurityLabel;
ops->securityDecodeLabel = DecodeSecurityLabel;
} else {
ops->securityEncodeLabel = EncodeSecurityLabel;
}
return 0;
}
#ifdef PARAM_SUPPORT_SELINUX
int RegisterSecurityOps(ParamSecurityOps *ops, int isInit)
{
return RegisterSecuritySelinuxOps(ops, isInit);
}
#endif
\ No newline at end of file
......@@ -14,149 +14,298 @@
*/
#include "param_request.h"
#include <errno.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <time.h>
#include "param_manager.h"
#include "uv.h"
#include "param_message.h"
#define INVALID_SOCKET (-1)
#define LABEL "Client"
#define BUFFER_SIZE 200
#define ParamEntry(ptr, type, member) (type *)((char *)(ptr) - offsetof(type, member))
static const uint32_t RECV_BUFFER_MAX = 5 * 1024;
static atomic_uint g_requestId = ATOMIC_VAR_INIT(1);
static ClientWorkSpace g_clientSpace = { {}, -1, {} };
static ParamWorkSpace g_paramWorkSpaceReadOnly = {ATOMIC_VAR_INIT(0), {}, {}, {}};
__attribute__((constructor)) static void ClientInit(void);
__attribute__((destructor)) static void ClientDeinit(void);
static void OnWrite(uv_write_t *req, int status)
static int InitParamClient(void)
{
PARAM_LOGD("OnWrite status %d", status);
if (PARAM_TEST_FLAG(g_clientSpace.paramSpace.flags, WORKSPACE_FLAGS_INIT)) {
return 0;
}
PARAM_LOGI("InitParamClient");
pthread_mutex_init(&g_clientSpace.mutex, NULL);
g_clientSpace.clientFd = INVALID_SOCKET;
return InitParamWorkSpace(&g_clientSpace.paramSpace, 1);
}
static void OnReceiveAlloc(uv_handle_t* handle, size_t suggestedSize, uv_buf_t* buf)
void ClientInit(void)
{
// 这里需要按实际回复大小申请内存,不需要大内存
buf->base = (char *)malloc(sizeof(ResponseMsg));
PARAM_CHECK(buf->base != NULL, return, "OnReceiveAlloc malloc failed");
buf->len = sizeof(ResponseMsg);
PARAM_LOGD("OnReceiveAlloc handle %p %zu", handle, suggestedSize);
PARAM_LOGI("ClientInit");
(void)InitParamClient();
}
static void OnReceiveResponse(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
void ClientDeinit(void)
{
RequestNode *req = ParamEntry(handle, RequestNode, handle);
PARAM_LOGD("OnReceiveResponse %p", handle);
if (nread <= 0 || buf == NULL || handle == NULL || buf->base == NULL) {
if (buf != NULL && buf->base != NULL) {
free(buf->base);
}
if (handle != NULL) {
uv_close((uv_handle_t*)handle, NULL);
uv_stop(req->loop);
}
return;
CloseParamWorkSpace(&g_clientSpace.paramSpace);
}
static ParamSecurityOps *GetClientParamSecurityOps(void)
{
return &g_clientSpace.paramSpace.paramSecurityOps;
}
static int FillLabelContent(ParamMessage *request, uint32_t *start, uint32_t length)
{
uint32_t bufferSize = request->msgSize - sizeof(ParamMessage);
uint32_t offset = *start;
PARAM_CHECK((offset + sizeof(ParamMsgContent) + length) <= bufferSize,
return -1, "Invalid msgSize %u offset %u", request->msgSize, offset);
ParamMsgContent *content = (ParamMsgContent *)(request->data + offset);
content->type = PARAM_LABEL;
content->contentSize = 0;
ParamSecurityOps *ops = GetClientParamSecurityOps();
if (length != 0 && ops != NULL && ops->securityEncodeLabel != NULL) {
int ret = ops->securityEncodeLabel(g_clientSpace.paramSpace.securityLabel, content->content, &length);
PARAM_CHECK(ret == 0, return -1, "Failed to get label length");
content->contentSize = length;
}
ResponseMsg *response = (ResponseMsg *)(buf->base);
PARAM_CHECK(response != NULL, return, "The response is null");
PARAM_LOGD("OnReceiveResponse %p cmd %d result: %d", handle, response->type, response->result);
switch (response->type) {
case SET_PARAM:
req->result = response->result;
offset += sizeof(ParamMsgContent) + PARAM_ALIGN(content->contentSize);
*start = offset;
return 0;
}
static int ProcessRecvMsg(const ParamMessage *recvMsg)
{
PARAM_LOGD("ProcessRecvMsg type: %u msgId: %u name %s", recvMsg->type, recvMsg->id.msgId, recvMsg->key);
int result = PARAM_CODE_INVALID_PARAM;
switch (recvMsg->type) {
case MSG_SET_PARAM:
result = ((ParamResponseMessage *)recvMsg)->result;
break;
case MSG_NOTIFY_PARAM:
result = 0;
break;
default:
PARAM_LOGE("not supported the command: %d", response->type);
break;
}
PARAM_LOGD("Close handle %p", handle);
free(buf->base);
uv_close((uv_handle_t*)handle, NULL);
uv_stop(req->loop);
}
static void OnConnection(uv_connect_t *connect, int status)
{
PARAM_CHECK(status >= 0, return, "Failed to conntect status %s", uv_strerror(status));
RequestNode *request = ParamEntry(connect, RequestNode, connect);
PARAM_LOGD("Connect to server handle %p", &(request->handle));
uv_buf_t buf = uv_buf_init((char*)&request->msg, request->msg.contentSize + sizeof(request->msg));
int ret = uv_write2(&request->wr, (uv_stream_t*)&(request->handle), &buf, 1, (uv_stream_t*)&(request->handle), OnWrite);
PARAM_CHECK(ret >= 0, return, "Failed to uv_write2 porperty");
// read result
ret = uv_read_start((uv_stream_t*)&(request->handle), OnReceiveAlloc, OnReceiveResponse);
PARAM_CHECK(ret >= 0, return, "Failed to uv_read_start response");
}
static int StartRequest(int cmd, RequestNode *request)
{
PARAM_CHECK(request != NULL, return -1, "Invalid request");
request->result = -1;
request->msg.type = cmd;
request->loop = uv_loop_new();
PARAM_CHECK(request->loop != NULL, return -1, "StartRequest uv_loop_new failed");
uv_pipe_init(request->loop, &request->handle, 1);
uv_pipe_connect(&request->connect, &request->handle, PIPE_NAME, OnConnection);
uv_run(request->loop, UV_RUN_DEFAULT);
uv_loop_delete(request->loop);
int result = request->result;
free(request);
return result;
}
static int StartRequest(int *fd, ParamMessage *request, int timeout)
{
int ret = 0;
struct timeval time;
time.tv_sec = timeout;
time.tv_usec = 0;
do {
int clientFd = *fd;
if (clientFd == INVALID_SOCKET) {
clientFd = socket(AF_UNIX, SOCK_STREAM, 0);
PARAM_CHECK(clientFd >= 0, return PARAM_CODE_FAIL_CONNECT, "Failed to create socket");
ret = ConntectServer(clientFd, PIPE_NAME);
PARAM_CHECK(ret == 0, close(clientFd);
return PARAM_CODE_FAIL_CONNECT, "Failed to connect server");
setsockopt(clientFd, SOL_SOCKET, SO_SNDTIMEO, (char *)&time, sizeof(struct timeval));
setsockopt(clientFd, SOL_SOCKET, SO_RCVTIMEO, (char *)&time, sizeof(struct timeval));
*fd = clientFd;
}
ssize_t recvLen = 0;
ssize_t sendLen = send(clientFd, (char *)request, request->msgSize, 0);
if (sendLen > 0) {
recvLen = recv(clientFd, (char *)request, RECV_BUFFER_MAX, 0);
if (recvLen > 0) {
break;
}
}
ret = errno;
close(clientFd);
*fd = INVALID_SOCKET;
if (errno == EAGAIN || recvLen == 0) {
ret = PARAM_CODE_TIMEOUT;
break;
}
PARAM_LOGE("Send or recv msg fail errno %d %zd %zd", errno, sendLen, recvLen);
} while (1);
if (ret == 0) { // check result
ret = ProcessRecvMsg(request);
}
return ret;
}
int SystemSetParameter(const char *name, const char *value)
{
PARAM_CHECK(name != NULL && value != NULL, return -1, "Invalid param");
InitParamClient();
PARAM_CHECK(name != NULL && value != NULL, return -1, "Invalid name or value");
int ret = CheckParamName(name, 0);
PARAM_CHECK(ret == 0, return ret, "Illegal param name");
PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", name);
uint32_t msgSize = sizeof(ParamMessage) + sizeof(ParamMsgContent) + PARAM_ALIGN(strlen(value) + 1);
uint32_t labelLen = 0;
ParamSecurityOps *ops = GetClientParamSecurityOps();
if (LABEL_IS_CLIENT_CHECK_PERMITTED(g_clientSpace.paramSpace.securityLabel)) {
ret = CheckParamPermission(&g_clientSpace.paramSpace, g_clientSpace.paramSpace.securityLabel, name, DAC_WRITE);
PARAM_CHECK(ret == 0, return ret, "Forbit to set parameter %s", name);
} else if (!LABEL_IS_ALL_PERMITTED(g_clientSpace.paramSpace.securityLabel)) { // check local can check permissions
PARAM_CHECK(ops != NULL && ops->securityEncodeLabel != NULL, return -1, "Invalid securityEncodeLabel");
ret = ops->securityEncodeLabel(g_clientSpace.paramSpace.securityLabel, NULL, &labelLen);
PARAM_CHECK(ret == 0, return -1, "Failed to get label length");
}
msgSize += sizeof(ParamMsgContent) + labelLen;
msgSize = msgSize < RECV_BUFFER_MAX ? RECV_BUFFER_MAX : msgSize;
PARAM_LOGD("StartRequest %s", name);
u_int32_t msgSize = sizeof(RequestMsg) + strlen(name) + strlen(value) + 2;
RequestNode *request = (RequestNode *)malloc(sizeof(RequestNode) + msgSize);
ParamMessage *request = (ParamMessage *)CreateParamMessage(MSG_SET_PARAM, name, msgSize);
PARAM_CHECK(request != NULL, return -1, "Failed to malloc for connect");
uint32_t offset = 0;
ret = FillParamMsgContent(request, &offset, PARAM_VALUE, value, strlen(value));
PARAM_CHECK(ret == 0, free(request);
return -1, "Failed to fill value");
ret = FillLabelContent(request, &offset, labelLen);
PARAM_CHECK(ret == 0, free(request);
return -1, "Failed to fill label");
request->msgSize = offset + sizeof(ParamMessage);
request->id.msgId = atomic_fetch_add(&g_requestId, 1);
memset_s(request, sizeof(RequestNode), 0, sizeof(RequestNode));
// 带字符串结束符
int contentSize = BuildParamContent(request->msg.content, msgSize - sizeof(RequestMsg), name, value);
PARAM_CHECK(contentSize > 0, free(request); return -1, "Failed to copy porperty");
request->msg.contentSize = contentSize;
return StartRequest(SET_PARAM, request);
pthread_mutex_lock(&g_clientSpace.mutex);
ret = StartRequest(&g_clientSpace.clientFd, request, DEFAULT_PARAM_SET_TIMEOUT);
pthread_mutex_unlock(&g_clientSpace.mutex);
free(request);
return ret;
}
int SystemWaitParameter(const char *name, const char *value, int32_t timeout)
{
InitParamClient();
PARAM_CHECK(name != NULL, return -1, "Invalid name");
int ret = CheckParamName(name, 0);
PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", name);
ParamHandle handle = 0;
ret = ReadParamWithCheck(&g_clientSpace.paramSpace, name, DAC_READ, &handle);
if (ret != PARAM_CODE_NOT_FOUND && ret != 0) {
PARAM_CHECK(ret == 0, return ret, "Forbid to wait parameter %s", name);
}
if (timeout == 0) {
timeout = DEFAULT_PARAM_WAIT_TIMEOUT;
}
uint32_t msgSize = sizeof(ParamMessage) + sizeof(ParamMsgContent) + sizeof(ParamMsgContent) + sizeof(uint32_t);
msgSize = msgSize < RECV_BUFFER_MAX ? RECV_BUFFER_MAX : msgSize;
uint32_t offset = 0;
ParamMessage *request = NULL;
if (value != NULL) {
msgSize += PARAM_ALIGN(strlen(value) + 1);
request = (ParamMessage *)CreateParamMessage(MSG_WAIT_PARAM, name, msgSize);
PARAM_CHECK(request != NULL, return -1, "Failed to malloc for wait");
ret = FillParamMsgContent(request, &offset, PARAM_VALUE, value, strlen(value));
} else {
msgSize += PARAM_ALIGN(1);
request = (ParamMessage *)CreateParamMessage(MSG_WAIT_PARAM, name, msgSize);
PARAM_CHECK(request != NULL, return -1, "Failed to malloc for wait");
ret = FillParamMsgContent(request, &offset, PARAM_VALUE, "*", 1);
}
PARAM_CHECK(ret == 0, free(request);
return -1, "Failed to fill value");
ParamMsgContent *content = (ParamMsgContent *)(request->data + offset);
content->type = PARAM_WAIT_TIMEOUT;
content->contentSize = sizeof(uint32_t);
*((uint32_t *)(content->content)) = timeout;
offset += sizeof(ParamMsgContent) + sizeof(uint32_t);
request->msgSize = offset + sizeof(ParamMessage);
request->id.waitId = atomic_fetch_add(&g_requestId, 1);
int fd = INVALID_SOCKET;
ret = StartRequest(&fd, request, timeout);
if (fd != INVALID_SOCKET) {
close(fd);
}
free(request);
PARAM_LOGI("SystemWaitParameter %s value %s result %d ", name, value, ret);
return ret;
}
int SystemGetParameter(const char *name, char *value, unsigned int *len)
{
InitParamClient();
PARAM_CHECK(name != NULL && len != NULL, return -1, "The name or value is null");
InitParamWorkSpace(&g_paramWorkSpaceReadOnly, 1, NULL);
ParamHandle handle = 0;
int ret = ReadParamWithCheck(&g_paramWorkSpaceReadOnly, name, &handle);
PARAM_CHECK(ret == 0, return ret, "Can not get param for %s", name);
return ReadParamValue(&g_paramWorkSpaceReadOnly, handle, value, len);
int ret = ReadParamWithCheck(&g_clientSpace.paramSpace, name, DAC_READ, &handle);
if (ret != PARAM_CODE_NOT_FOUND && ret != 0) {
PARAM_CHECK(ret == 0, return ret, "Forbid to get parameter %s", name);
}
return ReadParamValue(&g_clientSpace.paramSpace, handle, value, len);
}
int SystemFindParameter(const char *name, ParamHandle *handle)
{
InitParamClient();
PARAM_CHECK(name != NULL && handle != NULL, return -1, "The name or handle is null");
int ret = ReadParamWithCheck(&g_clientSpace.paramSpace, name, DAC_READ, handle);
if (ret != PARAM_CODE_NOT_FOUND && ret != 0) {
PARAM_CHECK(ret == 0, return ret, "Forbid to access parameter %s", name);
}
return 0;
}
int SystemGetParameterCommitId(ParamHandle handle, uint32_t *commitId)
{
PARAM_CHECK(handle != 0 || commitId != NULL, return -1, "The handle is null");
return ReadParamCommitId(&g_clientSpace.paramSpace, handle, commitId);
}
int SystemGetParameterName(ParamHandle handle, char *name, unsigned int len)
{
PARAM_CHECK(name != NULL && handle != 0, return -1, "The name is null");
InitParamWorkSpace(&g_paramWorkSpaceReadOnly, 1, NULL);
return ReadParamName(&g_paramWorkSpaceReadOnly, handle, name, len);
return ReadParamName(&g_clientSpace.paramSpace, handle, name, len);
}
int SystemGetParameterValue(ParamHandle handle, char *value, unsigned int *len)
{
PARAM_CHECK(len != NULL && handle != 0, return -1, "The value is null");
InitParamWorkSpace(&g_paramWorkSpaceReadOnly, 1, NULL);
return ReadParamValue(&g_paramWorkSpaceReadOnly, handle, value, len);
return ReadParamValue(&g_clientSpace.paramSpace, handle, value, len);
}
int SystemTraversalParameter(void (*traversalParameter)(ParamHandle handle, void* cookie), void* cookie)
int SystemTraversalParameter(void (*traversalParameter)(ParamHandle handle, void *cookie), void *cookie)
{
InitParamClient();
PARAM_CHECK(traversalParameter != NULL, return -1, "The param is null");
InitParamWorkSpace(&g_paramWorkSpaceReadOnly, 1, NULL);
return TraversalParam(&g_paramWorkSpaceReadOnly, traversalParameter, cookie);
ParamHandle handle = 0;
// check default dac
int ret = ReadParamWithCheck(&g_clientSpace.paramSpace, "#", DAC_READ, &handle);
if (ret != PARAM_CODE_NOT_FOUND && ret != 0) {
PARAM_CHECK(ret == 0, return ret, "Forbid to traversal parameters");
}
return TraversalParam(&g_clientSpace.paramSpace, traversalParameter, cookie);
}
void SystemDumpParameters(int verbose)
{
InitParamClient();
DumpParameters(&g_clientSpace.paramSpace, verbose);
}
int WatchParamCheck(const char *keyprefix)
{
InitParamClient();
PARAM_CHECK(keyprefix != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid keyprefix");
int ret = CheckParamName(keyprefix, 0);
PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", keyprefix);
ParamHandle handle = 0;
ret = ReadParamWithCheck(&g_clientSpace.paramSpace, keyprefix, DAC_WATCH, &handle);
if (ret != PARAM_CODE_NOT_FOUND && ret != 0) {
PARAM_CHECK(ret == 0, return ret, "Forbid to watch parameter %s", keyprefix);
}
return 0;
}
const char *SystemDetectParamChange(ParamCache *cache,
ParamEvaluatePtr evaluate, u_int32_t count, const char *parameters[][2])
#ifdef STARTUP_INIT_TEST
ParamWorkSpace *GetClientParamWorkSpace(void)
{
PARAM_CHECK(cache != NULL && evaluate != NULL && parameters != NULL, return NULL, "The param is null");
return DetectParamChange(&g_paramWorkSpaceReadOnly, cache, evaluate, count, parameters);
return &g_clientSpace.paramSpace;
}
#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.
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "param_manager.h"
#include "param_utils.h"
#include "sys_param.h"
#define USAGE_INFO_PARAM_GET "param get [key]"
#define USAGE_INFO_PARAM_SET "param set key value"
#define USAGE_INFO_PARAM_WAIT "param wait key value"
#define USAGE_INFO_PARAM_DUMP "param dump [verbose]"
#define USAGE_INFO_PARAM_READ "param read key"
#define USAGE_INFO_PARAM_WATCH "param watch key"
#define READ_DURATION 100000
#define MIN_ARGC 2
#define WAIT_TIMEOUT_INDEX 2
struct CmdArgs {
char name[8];
int minArg;
void (*DoFuncion)(int argc, char *argv[], int start);
char help[128];
};
static void ShowParam(ParamHandle handle, void *cookie)
{
char *name = (char *)cookie;
char *value = ((char *)cookie) + PARAM_NAME_LEN_MAX;
SystemGetParameterName(handle, name, PARAM_NAME_LEN_MAX);
uint32_t size = PARAM_CONST_VALUE_LEN_MAX;
SystemGetParameterValue(handle, value, &size);
printf("\t%s = %s \n", name, value);
}
static void ExeuteCmdParamGet(int argc, char *argv[], int start)
{
uint32_t size = PARAM_CONST_VALUE_LEN_MAX + PARAM_NAME_LEN_MAX + 1 + 1;
char *buffer = (char *)malloc(size);
if (buffer == NULL) {
printf("Get parameterfail\n");
return;
}
memset_s(buffer, size, 0, size);
if (argc == start) {
SystemTraversalParameter(ShowParam, (void *)buffer);
} else {
int ret = SystemGetParameter(argv[start], buffer, &size);
if (ret == 0) {
printf("%s \n", buffer);
} else {
printf("Get parameter \"%s\" fail\n", argv[start]);
}
}
free(buffer);
}
static void ExeuteCmdParamSet(int argc, char *argv[], int start)
{
UNUSED(argc);
int ret = SystemSetParameter(argv[start], argv[start + 1]);
if (ret == 0) {
printf("Set parameter %s %s success\n", argv[start], argv[start + 1]);
} else {
printf("Set parameter %s %s fail\n", argv[start], argv[start + 1]);
}
return;
}
static void ExeuteCmdParamDump(int argc, char *argv[], int start)
{
int verbose = 0;
if (argc > start && strcmp(argv[start], "verbose") == 0) {
verbose = 1;
}
SystemDumpParameters(verbose);
}
static void ExeuteCmdParamWait(int argc, char *argv[], int start)
{
char *value = NULL;
uint32_t timeout = DEFAULT_PARAM_WAIT_TIMEOUT;
if (argc > (start + 1)) {
value = argv[start + 1];
}
if (argc > (start + WAIT_TIMEOUT_INDEX)) {
timeout = atol(argv[start + WAIT_TIMEOUT_INDEX]);
}
SystemWaitParameter(argv[start], value, timeout);
}
#ifdef PARAM_TEST
static void ExeuteCmdParamRead(int argc, char *argv[], int start)
{
srand((unsigned)time(NULL)); // srand()函数产生一个以当前时间开始的随机种子
while (1) {
ExeuteCmdParamGet(argc, argv, start);
int wait = rand() / READ_DURATION + READ_DURATION; // 100ms
usleep(wait);
}
}
static void HandleParamChange(const char *key, const char *value, void *context)
{
printf("Receive parameter change %s %s \n", key, value);
}
static void ExeuteCmdParamWatch(int argc, char *argv[], int start)
{
int ret = SystemWatchParameter(argv[start], HandleParamChange, NULL);
if (ret != 0) {
return;
}
while (1) {
(void)pause();
}
}
#endif
int RunParamCommand(int argc, char *argv[])
{
static struct CmdArgs paramCmds[] = {
{ "set", 4, ExeuteCmdParamSet, USAGE_INFO_PARAM_SET },
{ "get", 2, ExeuteCmdParamGet, USAGE_INFO_PARAM_GET },
{ "wait", 3, ExeuteCmdParamWait, USAGE_INFO_PARAM_WAIT },
{ "dump", 2, ExeuteCmdParamDump, USAGE_INFO_PARAM_DUMP },
#ifdef PARAM_TEST
{ "read", 2, ExeuteCmdParamRead, USAGE_INFO_PARAM_READ },
{ "watch", 2, ExeuteCmdParamWatch, USAGE_INFO_PARAM_WATCH },
#endif
};
if (argc < MIN_ARGC) {
printf("usage: \n");
for (size_t i = 0; i < sizeof(paramCmds) / sizeof(paramCmds[0]); i++) {
printf("\t %s\n", paramCmds[i].help);
}
return 0;
}
for (size_t i = 0; i < sizeof(paramCmds) / sizeof(paramCmds[0]); i++) {
if (strncmp(argv[1], paramCmds[i].name, strlen(paramCmds[i].name)) == 0) {
if (argc < paramCmds[i].minArg) {
printf("usage: %s\n", paramCmds[i].help);
return 0;
}
paramCmds[i].DoFuncion(argc, argv, MIN_ARGC);
return 0;
}
}
printf("usage: \n");
for (size_t i = 0; i < sizeof(paramCmds) / sizeof(paramCmds[0]); i++) {
printf("\t%s\n", paramCmds[i].help);
}
return 0;
}
#ifndef STARTUP_INIT_TEST
int main(int argc, char *argv[])
{
return RunParamCommand(argc, argv);
}
#endif
\ No newline at end of file
......@@ -18,140 +18,60 @@
#include <stdio.h>
#include <string.h>
#include "init_log.h"
#include "sys_param.h"
#include "param_message.h"
#include "param_persist.h"
#include "param_security.h"
#include "param_trie.h"
#include "securec.h"
#include "param_utils.h"
#include "sys_param.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef enum {
PARAM_CODE_INVALID_PARAM = 100,
PARAM_CODE_INVALID_NAME,
PARAM_CODE_INVALID_VALUE,
PARAM_CODE_REACHED_MAX,
PARAM_CODE_PERMISSION_DENIED,
PARAM_CODE_READ_ONLY_PROPERTY,
PARAM_CODE_NOT_SUPPORT,
PARAM_CODE_ERROR_MAP_FILE,
PARAM_CODE_NOT_FOUND_PROP,
PARAM_CODE_NOT_INIT
} PARAM_CODE;
#define IS_READY_ONLY(name) strncmp((name), "ro.", strlen("ro.")) == 0
#define LABEL_STRING_LEN 128
#ifdef STARTUP_LOCAL
#define PIPE_NAME "/tmp/paramservice"
#define PARAM_STORAGE_PATH "/media/sf_ubuntu/test/__parameters__/param_storage"
#define PARAM_PERSIST_PATH "/media/sf_ubuntu/test/param/persist_parameters"
#define PARAM_INFO_PATH "/media/sf_ubuntu/test/__parameters__/param_info"
#else
#define PIPE_NAME "/dev/unix/socket/paramservice"
#define PARAM_STORAGE_PATH "/dev/__parameters__/param_storage"
#define PARAM_PERSIST_PATH "/data/param/persist_parameters"
#define PARAM_INFO_PATH "/dev/__parameters__/param_info"
#endif
#define SUBSTR_INFO_NAME 0
#define SUBSTR_INFO_LABEL 1
#define SUBSTR_INFO_TYPE 2
#define SUBSTR_INFO_MAX 4
#define WORKSPACE_FLAGS_INIT 0x01
#define WORKSPACE_FLAGS_LOADED 0x02
#define PARAM_LOGI(fmt, ...) STARTUP_LOGI(LABEL, fmt, ##__VA_ARGS__)
#define PARAM_LOGE(fmt, ...) STARTUP_LOGE(LABEL, fmt, ##__VA_ARGS__)
#define PARAM_LOGD(fmt, ...) STARTUP_LOGD(LABEL, fmt, ##__VA_ARGS__)
#define PARAM_CHECK(retCode, exper, ...) \
if (!(retCode)) { \
PARAM_LOGE(__VA_ARGS__); \
exper; \
}
#define futex(addr1, op, val, rel, addr2, val3) \
syscall(SYS_futex, addr1, op, val, rel, addr2, val3)
#define futex_wait_always(addr1) \
syscall(SYS_futex, addr1, FUTEX_WAIT, *(int*)(addr1), 0, 0, 0)
#define futex_wake_single(addr1) \
syscall(SYS_futex, addr1, FUTEX_WAKE, 1, 0, 0, 0)
typedef struct UserCred {
pid_t pid;
uid_t uid;
gid_t gid;
} UserCred;
#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 {
char label[LABEL_STRING_LEN];
UserCred cred;
} ParamSecurityLabel;
typedef struct ParamAuditData {
const UserCred *cr;
const char *name;
} ParamAuditData;
typedef struct {
atomic_uint_least32_t flags;
WorkSpace paramLabelSpace;
uint32_t flags;
WorkSpace paramSpace;
ParamSecurityLabel label;
ParamSecurityLabel *securityLabel;
ParamSecurityOps paramSecurityOps;
ParamTaskPtr serverTask;
ParamTaskPtr timer;
} ParamWorkSpace;
typedef struct {
atomic_uint_least32_t flags;
WorkSpace persistWorkSpace;
uint32_t flags;
ParamTaskPtr saveTimer;
time_t lastSaveTimer;
PersistParamOps persistParamOps;
} ParamPersistWorkSpace;
typedef struct {
char value[128];
} SubStringInfo;
int InitParamWorkSpace(ParamWorkSpace *workSpace, int onlyRead, const char *context);
int InitParamWorkSpace(ParamWorkSpace *workSpace, int onlyRead);
void CloseParamWorkSpace(ParamWorkSpace *workSpace);
int ReadParamWithCheck(ParamWorkSpace *workSpace, const char *name, ParamHandle *handle);
int ReadParamValue(ParamWorkSpace *workSpace, ParamHandle handle, char *value, u_int32_t *len);
int ReadParamName(ParamWorkSpace *workSpace, ParamHandle handle, char *name, u_int32_t len);
u_int32_t ReadParamSerial(ParamWorkSpace *workSpace, ParamHandle handle);
int AddParam(WorkSpace *workSpace, const char *name, const char *value);
int WriteParam(WorkSpace *workSpace, const char *name, const char *value);
int WriteParamWithCheck(ParamWorkSpace *workSpace,
const ParamSecurityLabel *srcLabel, const char *name, const char *value);
int WriteParamInfo(ParamWorkSpace *workSpace, SubStringInfo *info, int subStrNumber);
int ReadParamWithCheck(ParamWorkSpace *workSpace, const char *name, int op, ParamHandle *handle);
int ReadParamValue(ParamWorkSpace *workSpace, ParamHandle handle, char *value, uint32_t *len);
int ReadParamName(ParamWorkSpace *workSpace, ParamHandle handle, char *name, uint32_t len);
int ReadParamCommitId(ParamWorkSpace *workSpace, ParamHandle handle, uint32_t *commitId);
int CheckParamValue(WorkSpace *workSpace, const TrieDataNode *node, const char *name, const char *value);
int CheckParamName(const char *name, int paramInfo);
int CanReadParam(ParamWorkSpace *workSpace, u_int32_t labelIndex, const char *name);
int CanWriteParam(ParamWorkSpace *workSpace,
const ParamSecurityLabel *srcLabel, const TrieDataNode *node, const char *name, const char *value);
int CheckMacPerms(ParamWorkSpace *workSpace,
const ParamSecurityLabel *srcLabel, const char *name, u_int32_t labelIndex);
int CheckControlParamPerms(ParamWorkSpace *workSpace,
const ParamSecurityLabel *srcLabel, const char *name, const char *value);
int CheckParamPermission(ParamWorkSpace *workSpace, const ParamSecurityLabel *srcLabel, const char *name, int mode);
int GetSubStringInfo(const char *buff, u_int32_t buffLen, char delimiter, SubStringInfo *info, int subStrNumber);
int BuildParamContent(char *content, u_int32_t contentSize, const char *name, const char *value);
ParamWorkSpace *GetParamWorkSpace();
typedef void (*TraversalParamPtr)(ParamHandle handle, void* context);
typedef void (*TraversalParamPtr)(ParamHandle handle, void *context);
typedef struct {
TraversalParamPtr traversalParamPtr;
void *context;
} ParamTraversalContext;
int TraversalParam(ParamWorkSpace *workSpace, TraversalParamPtr walkFunc, void *cookie);
const char *DetectParamChange(ParamWorkSpace *workSpace, ParamCache *cache,
ParamEvaluatePtr evaluate, u_int32_t count, const char *parameters[][2]);
ParamWorkSpace *GetParamWorkSpace(void);
ParamWorkSpace *GetClientParamWorkSpace(void);
void DumpParameters(ParamWorkSpace *workSpace, int verbose);
#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_PARAM_MESSAGE_H
#define BASE_STARTUP_PARAM_MESSAGE_H
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "param.h"
#include "param_utils.h"
#include "securec.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#ifndef PARAM_SUPPORT_LIBUV
#ifndef PARAM_SUPPORT_EVENT
#define PARAM_SUPPORT_LIBUV 1
#endif
#endif
#define WORKER_TYPE_MSG 0x01
#define WORKER_TYPE_EVENT 0x02
#define WORKER_TYPE_TIMER 0x08
#define WORKER_TYPE_ASYNC 0x10
#define WORKER_TYPE_SERVER 0x20
#define WORKER_TYPE_CLIENT 0x40
#define WORKER_TYPE_TEST 0x01000000
typedef enum {
MSG_SET_PARAM,
MSG_WAIT_PARAM,
MSG_ADD_WATCHER,
MSG_DEL_WATCHER,
MSG_NOTIFY_PARAM
} ParamMsgType;
typedef enum ContentType {
PARAM_NAME,
PARAM_VALUE,
PARAM_LABEL,
PARAM_WAIT_TIMEOUT,
PARAM_NAME_VALUE,
} ContentType;
typedef struct {
uint8_t type;
uint8_t rev;
uint16_t contentSize;
char content[0];
} ParamMsgContent;
typedef struct {
uint32_t type;
uint32_t msgSize;
union {
uint32_t msgId;
uint32_t watcherId;
uint32_t waitId;
} id;
char key[PARAM_NAME_LEN_MAX];
char data[0];
} ParamMessage;
typedef struct {
ParamMessage msg;
uint32_t result;
} ParamResponseMessage;
struct ParamTask_;
typedef struct ParamTask_ *ParamTaskPtr;
typedef int (*IncomingConnect)(const ParamTaskPtr stream, int flags);
typedef int (*RecvMessage)(const ParamTaskPtr stream, const ParamMessage *msg);
typedef void (*TimerProcess)(const ParamTaskPtr stream, void *context);
typedef void (*EventProcess)(uint64_t eventId, const char *context, uint32_t size);
typedef void (*TaskClose)(const ParamTaskPtr stream);
typedef void (*ProcessPidDelete)(pid_t pid);
typedef struct ParamTask_ {
int32_t flags;
} ParamTask;
typedef struct {
int flags;
char *server;
IncomingConnect incomingConnect;
RecvMessage recvMessage;
TaskClose close;
} ParamStreamInfo;
int ParamServiceStop(void);
int ParamServiceStart(ProcessPidDelete pidDelete);
int ParamTaskClose(ParamTaskPtr stream);
int ParamServerCreate(ParamTaskPtr *server, const ParamStreamInfo *info);
int ParamStreamCreate(ParamTaskPtr *client, ParamTaskPtr server, const ParamStreamInfo *info, uint16_t userDataSize);
int ParamTaskSendMsg(const ParamTaskPtr stream, const ParamMessage *msg);
int ParamEventTaskCreate(ParamTaskPtr *stream, EventProcess eventProcess, EventProcess eventBeforeProcess);
int ParamEventSend(ParamTaskPtr stream, uint64_t eventId, const char *content, uint32_t size);
int ParamTimerCreate(ParamTaskPtr *timer, TimerProcess process, void *context);
int ParamTimerStart(ParamTaskPtr timer, uint64_t timeout, uint64_t repeat);
void *ParamGetTaskUserData(ParamTaskPtr stream);
int FillParamMsgContent(ParamMessage *request, uint32_t *start, int type, const char *value, uint32_t length);
ParamMsgContent *GetNextContent(const ParamMessage *reqest, uint32_t *offset);
ParamMessage *CreateParamMessage(int type, const char *name, uint32_t msgSize);
int ConntectServer(int fd, const char *servername);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // BASE_STARTUP_PARAM_MESSAGE_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.
*/
#ifndef BASE_STARTUP_PARAM_PERSIST_H
#define BASE_STARTUP_PARAM_PERSIST_H
#include <stdint.h>
#include <sys/types.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef int (*PersistParamGetPtr)(const char *name, const char *value, void *context);
typedef void *PERSIST_SAVE_HANDLE;
typedef struct {
int (*load)(PersistParamGetPtr persistParamGet, void *context);
int (*save)(const char *name, const char *value);
int (*batchSaveBegin)(PERSIST_SAVE_HANDLE *handle);
int (*batchSave)(PERSIST_SAVE_HANDLE handle, const char *name, const char *value);
void (*batchSaveEnd)(PERSIST_SAVE_HANDLE handle);
} PersistParamOps;
#ifndef PARAM_SUPPORT_SAVE_PERSIST
#define PARAM_SUPPORT_SAVE_PERSIST 1 // default
#endif
#ifdef PARAM_SUPPORT_SAVE_PERSIST
int RegisterPersistParamOps(PersistParamOps *ops);
#define PARAM_MUST_SAVE_PARAM_DIFF 10 // 10s
#else
#define PARAM_MUST_SAVE_PARAM_DIFF UINT32_MAX
#endif
#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");
......@@ -15,54 +16,27 @@
#ifndef BASE_STARTUP_PARAM_REQUEST_H
#define BASE_STARTUP_PARAM_REQUEST_H
#include <pthread.h>
#include <stdatomic.h>
#include <stdio.h>
#include "sys_param.h"
#include "param_manager.h"
#include "uv.h"
#include "sys_param.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef enum RequestType {
SET_PARAM,
GET_PARAM,
} RequestType;
typedef struct {
ParamSecurityLabel securitylabel;
RequestType type;
int contentSize;
char content[0];
} RequestMsg;
typedef struct {
RequestType type;
int result;
int contentSize;
char content[0];
} ResponseMsg;
typedef struct {
uv_loop_t *loop;
uv_connect_t connect;
uv_pipe_t handle;
uv_write_t wr;
int result;
RequestMsg msg;
} RequestNode;
typedef struct {
uv_write_t writer;
ResponseMsg msg;
} ResponseNode;
ParamWorkSpace paramSpace;
int clientFd;
pthread_mutex_t mutex;
} ClientWorkSpace;
int WatchParamCheck(const char *keyprefix);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif
\ No newline at end of file
#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.
*/
#ifndef BASE_STARTUP_PARAM_SECURITY_H
#define BASE_STARTUP_PARAM_SECURITY_H
#include <stdint.h>
#include <sys/types.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#define DAC_GROUP_START 3
#define DAC_OTHER_START 6
#define DAC_READ 0x0100
#define DAC_WRITE 0x0080
#define DAC_WATCH 0x0040
#define DAC_ALL_PERMISSION 0777
#define LABEL_ALL_PERMISSION 0x04
#define LABEL_CHECK_FOR_ALL_PROCESS 0x02
#define LABEL_INIT_FOR_INIT 0x01
#define LABEL_IS_CLIENT_CHECK_PERMITTED(label) \
((label) != NULL) && ((((label)->flags & (LABEL_CHECK_FOR_ALL_PROCESS)) == (LABEL_CHECK_FOR_ALL_PROCESS)) && \
(((label)->flags & (LABEL_ALL_PERMISSION)) != (LABEL_ALL_PERMISSION)))
#define LABEL_IS_ALL_PERMITTED(label) \
(((label) == NULL) || ((label)->flags & LABEL_ALL_PERMISSION) == (LABEL_ALL_PERMISSION))
typedef enum {
DAC_RESULT_PERMISSION = 0,
DAC_RESULT_INVALID_PARAM = 1000,
DAC_RESULT_FORBIDED,
} DAC_RESULT;
typedef struct UserCred {
pid_t pid;
uid_t uid;
gid_t gid;
} UserCred;
typedef struct {
uint32_t flags;
UserCred cred;
} ParamSecurityLabel;
typedef struct {
pid_t pid;
uid_t uid;
gid_t gid;
uint32_t mode; // 访问权限
} ParamDacData;
typedef struct {
ParamDacData dacData;
const char *name;
const char *label;
} ParamAuditData;
typedef int (*SecurityLabelFunc)(const ParamAuditData *auditData, void *context);
typedef struct {
int (*securityInitLabel)(ParamSecurityLabel **label, int isInit);
int (*securityGetLabel)(SecurityLabelFunc label, const char *path, void *context);
int (*securityCheckFilePermission)(const ParamSecurityLabel *label, const char *fileName, int flags);
int (*securityCheckParamPermission)(const ParamSecurityLabel *srcLabel, const ParamAuditData *auditData, int mode);
int (*securityEncodeLabel)(const ParamSecurityLabel *srcLabel, char *buffer, uint32_t *bufferSize);
int (*securityDecodeLabel)(ParamSecurityLabel **srcLabel, char *buffer, uint32_t bufferSize);
int (*securityFreeLabel)(ParamSecurityLabel *srcLabel);
} ParamSecurityOps;
typedef int (*RegisterSecurityOpsPtr)(ParamSecurityOps *ops, int isInit);
int RegisterSecurityOps(ParamSecurityOps *ops, int isInit);
typedef struct {
SecurityLabelFunc label;
void *context;
} LabelFuncContext;
#ifdef PARAM_SUPPORT_SELINUX
#ifdef PARAM_SUPPORT_DAC
#error param security only support one.
#endif
#else
#define PARAM_SUPPORT_DAC 1 // default support dac
#endif
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // BASE_STARTUP_PARAM_SECURITY_H
\ No newline at end of file
......@@ -15,20 +15,38 @@
#ifndef BASE_STARTUP_PARAM_SERVICE_H
#define BASE_STARTUP_PARAM_SERVICE_H
#include <limits.h>
#include <stdio.h>
#include "sys_param.h"
#include "param_manager.h"
#include "sys_param.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
int InitPersistParamWorkSpace(const char *context);
int RefreshPersistParams(ParamWorkSpace *workSpace, const char *context);
void ClosePersistParamWorkSpace();
int WritePersistParam(const char *name, const char *value);
#define PARAM_WATCH_FLAGS_WAIT 0x01
struct CmdLineEntry {
char *key;
int set;
};
int WriteParam(WorkSpace *workSpace, const char *name, const char *value, uint32_t *dataIndex, int onlyAdd);
int InitPersistParamWorkSpace(ParamWorkSpace *workSpace);
void ClosePersistParamWorkSpace(void);
int LoadPersistParam(ParamWorkSpace *workSpace);
int WritePersistParam(ParamWorkSpace *workSpace, const char *name, const char *value);
#ifdef STARTUP_INIT_TEST
int ProcessMessage(const ParamTaskPtr worker, const ParamMessage *msg);
int AddSecurityLabel(const ParamAuditData *auditData, void *context);
#endif
int ProcessParamWaitAdd(ParamWorkSpace *worksapce, const ParamTaskPtr worker, const ParamMessage *msg);
int ProcessParamWatchAdd(ParamWorkSpace *worksapce, const ParamTaskPtr worker, const ParamMessage *msg);
#ifdef __cplusplus
#if __cplusplus
}
......
......@@ -15,121 +15,109 @@
#ifndef BASE_STARTUP_PARAM_TRIE_H
#define BASE_STARTUP_PARAM_TRIE_H
#include <linux/futex.h>
#include <stdatomic.h>
#include <stdio.h>
#include <string.h>
#include <sys/syscall.h>
#include "init_log.h"
#include "sys_param.h"
#include "param_security.h"
#include "securec.h"
#include "sys_param.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#ifndef __NR_futex
#define PARAM_NR_FUTEX 202 /* syscall number */
#else
#define PARAM_NR_FUTEX __NR_futex
#endif
#define PARAM_WORKSPACE_MAX 64*1024
#define TRIE_SERIAL_DIRTY_OFFSET 1
#define TRIE_SERIAL_KEY_LEN_OFFSET 24
#define TRIE_SERIAL_DATA_LEN_OFFSET 16
#define FILENAME_LEN_MAX 255
#define TRIE_DATA_LEN_MAX 128
#define NODE_INDEX unsigned int
#if defined FUTEX_WAIT || defined FUTEX_WAKE
#include <linux/futex.h>
#else
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#define TRIE_NODE_HEADER \
atomic_uint_least32_t serial; \
NODE_INDEX left; \
NODE_INDEX right;
#define PARAM_FUTEX(ftx, op, value, timeout, bitset) \
do { \
struct timespec d_timeout = { 0, 1000 * 1000 * (timeout) }; \
syscall(PARAM_NR_FUTEX, ftx, op, value, &d_timeout, NULL, bitset); \
} while (0)
#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_wake(ftx, count) PARAM_FUTEX(ftx, FUTEX_WAKE, count, 0, 0)
#define futex_wait(ftx, value) PARAM_FUTEX(ftx, FUTEX_WAIT, value, 100, 0)
#endif
#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)
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#define PARAM_WORKSPACE_MAX (80 * 1024)
#define FILENAME_LEN_MAX 255
typedef struct {
TRIE_NODE_HEADER;
uint32_t left;
uint32_t right;
uint32_t child;
uint32_t labelIndex;
uint32_t dataIndex;
uint16_t length;
char key[0];
} TrieNode;
} ParamTrieNode;
#define PARAM_FLAGS_MODIFY 0x80000000
#define PARAM_FLAGS_TRIGGED 0x40000000
#define PARAM_FLAGS_WAITED 0x20000000
#define PARAM_FLAGS_COMMITID 0x0000ffff
typedef struct {
TRIE_NODE_HEADER;
NODE_INDEX child;
NODE_INDEX labelIndex;
NODE_INDEX dataIndex;
char key[0];
} TrieDataNode;
atomic_uint commitId;
uint16_t keyLength;
uint16_t valueLength;
char data[0];
} ParamNode;
typedef struct {
atomic_uint_least32_t serial;
atomic_uint_least32_t dataLength;
uid_t uid;
gid_t gid;
uint16_t mode;
uint16_t length;
char data[0];
} DataEntry;
} ParamSecruityNode;
typedef struct {
atomic_uint_least32_t serial;
u_int32_t currOffset;
u_int32_t firstNode;
u_int32_t dataSize;
u_int32_t reserved_[28];
uint32_t trieNodeCount;
uint32_t paramNodeCount;
uint32_t securityNodeCount;
uint32_t currOffset;
uint32_t firstNode;
uint32_t dataSize;
uint32_t reserved_[28];
char data[0];
} WorkArea;
} ParamTrieHeader;
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;
uint32_t (*allocTrieNode)(struct WorkSpace_ *workSpace, const char *key, uint32_t keyLen);
int (*compareTrieNode)(ParamTrieNode *node, const char *key2, uint32_t key2Len);
ParamTrieHeader *area;
} 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);
ParamTrieNode *GetTrieNode(WorkSpace *workSpace, uint32_t offset);
void SaveIndex(uint32_t *index, uint32_t offset);
ParamTrieNode *AddTrieNode(WorkSpace *workSpace, const char *key, uint32_t keyLen);
ParamTrieNode *FindTrieNode(WorkSpace *workSpace, const char *key, uint32_t keyLen, uint32_t *matchLabel);
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);
typedef int (*TraversalTrieNodePtr)(WorkSpace *workSpace, ParamTrieNode *node, void *cookie);
int TraversalTrieNode(WorkSpace *workSpace, ParamTrieNode *subTrie, TraversalTrieNodePtr walkFunc, void *cookie);
uint32_t AddParamSecruityNode(WorkSpace *workSpace, const ParamAuditData *auditData);
uint32_t AddParamNode(WorkSpace *workSpace, const char *key, uint32_t keyLen, const char *value, uint32_t valueLen);
#ifdef __cplusplus
#if __cplusplus
}
......
/*
* Copyright (c) 2020 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef BASE_STARTUP_PARAM_UTILS_H
#define BASE_STARTUP_PARAM_UTILS_H
#include <stddef.h>
#include <stdint.h>
#include "init_log.h"
#include "securec.h"
#include "sys_param.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
typedef enum {
PARAM_CODE_NOT_INIT = PARAM_CODE_MAX + 1,
PARAM_CODE_ERROR_MAP_FILE,
} PARAM_INNER_CODE;
#define MS_UNIT 1000
#define UNUSED(x) (void)(x)
#define PARAM_ALIGN(len) (((len) + 0x03) & (~0x03))
#define PARAM_ENTRY(ptr, type, member) (type *)((char *)(ptr)-offsetof(type, member))
#define IS_READY_ONLY(name) \
((strncmp((name), "const.", strlen("const.")) == 0) || (strncmp((name), "ro.", strlen("ro.")) == 0))
#define PARAM_CONST_PREFIX "persist."
#define SYS_POWER_CTRL "sys.powerctrl="
#define OHOS_CTRL_START "ohos.ctl.start="
#define OHOS_CTRL_STOP "ohos.ctl.stop="
#define OHOS_SERVICE_CTRL_PREFIX "ohos.servicectrl."
#define OHOS_BOOT "ohos.boot."
#ifdef STARTUP_INIT_TEST
#define PARAM_STATIC
#define PARAM_DEFAULT_PATH ""
#define PIPE_NAME "/data/paramservice"
#define PARAM_STORAGE_PATH PARAM_DEFAULT_PATH"/__parameters__/param_storage"
#define PARAM_PERSIST_SAVE_PATH PARAM_DEFAULT_PATH"/param/persist_parameters"
#define PARAM_PERSIST_SAVE_TMP_PATH PARAM_DEFAULT_PATH"/param/tmp_persist_parameters"
#define PARAM_CMD_LINE PARAM_DEFAULT_PATH"/proc/cmdline"
#define GROUP_FILE_PATH PARAM_DEFAULT_PATH"/etc/group"
#define USER_FILE_PATH PARAM_DEFAULT_PATH"/etc/passwd"
#else
#define PARAM_DEFAULT_PATH ""
#define PARAM_STATIC static
#define PIPE_NAME "/dev/unix/socket/paramservice"
#define PARAM_STORAGE_PATH "/dev/__parameters__/param_storage"
#define PARAM_PERSIST_SAVE_PATH "/data/parameters/persist_parameters"
#define PARAM_PERSIST_SAVE_TMP_PATH "/data/parameters/tmp_persist_parameters"
#define PARAM_CMD_LINE "/proc/cmdline"
#define GROUP_FILE_PATH "/etc/group"
#define USER_FILE_PATH "/etc/passwd"
#endif
#define WORKSPACE_FLAGS_INIT 0x01
#define WORKSPACE_FLAGS_LOADED 0x02
#define WORKSPACE_FLAGS_UPDATE 0x04
#define WORKSPACE_FLAGS_LABEL_LOADED 0x08
#define PARAM_SET_FLAG(node, flag) ((node) |= (flag))
#define PARAM_CLEAR_FLAG(node, flag) ((node) &= ~(flag))
#define PARAM_TEST_FLAG(node, flag) (((node) & (flag)) == (flag))
#define PARAM_LOGI(fmt, ...) STARTUP_LOGI(LABEL, fmt, ##__VA_ARGS__)
#define PARAM_LOGE(fmt, ...) STARTUP_LOGE(LABEL, fmt, ##__VA_ARGS__)
#define PARAM_LOGD(fmt, ...) STARTUP_LOGD(LABEL, fmt, ##__VA_ARGS__)
#define PARAM_CHECK(retCode, exper, ...) \
if (!(retCode)) { \
PARAM_LOGE(__VA_ARGS__); \
exper; \
}
#define MAX_LABEL_LEN 256
#define PARAM_BUFFER_SIZE 256
#define SUBSTR_INFO_NAME 0
#define SUBSTR_INFO_VALUE 1
#ifdef PARAM_SUPPORT_SELINUX
#define SUBSTR_INFO_LABEL 1
#define SUBSTR_INFO_DAC 2
#else
#define SUBSTR_INFO_LABEL 1
#define SUBSTR_INFO_DAC 1
#endif
typedef struct {
int length;
char value[PARAM_BUFFER_SIZE];
} SubStringInfo;
#define MAX_DATA_BUFFER 2048
char *ReadFileData(const char *fileName);
void CheckAndCreateDir(const char *fileName);
int ReadFileInDir(const char *dirPath, const char *includeExt,
int (*processFile)(const char *fileName, void *context), void *context);
int GetSubStringInfo(const char *buff, uint32_t buffLen, char delimiter, SubStringInfo *info, int subStrNumber);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif
\ No newline at end of file
......@@ -15,8 +15,7 @@
#ifndef STARTUP_TRIGER_CHECKER_H
#define STARTUP_TRIGER_CHECKER_H
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>
......@@ -31,6 +30,7 @@ extern "C" {
#define MAX_TRIGGER_TYPE_LEN 16
#define SUPPORT_DATA_BUFFER_MAX 128
#define MAX_DATA_BUFFER_MAX (SUPPORT_DATA_BUFFER_MAX * 5)
#define CONDITION_EXTEND_LEN 32
#define LOGIC_DATA_FLAGS_ORIGINAL 0x1
......@@ -41,16 +41,16 @@ extern "C" {
#define LOGIC_DATA_CLEAR_FLAG(data, flag) (data)->flags &= ~(flag)
typedef struct {
u_int32_t flags;
u_int32_t startIndex;
u_int32_t endIndex;
uint32_t flags;
uint32_t startIndex;
uint32_t endIndex;
} LogicData;
struct tagTriggerNode;
struct tagTriggerNode_;
typedef int (*PARAM_CHECK_DONE)(struct tagTriggerNode_ *trigger, const char *content, uint32_t size);
typedef struct {
char triggerContent[MAX_TRIGGER_NAME_LEN];
int (*triggerExecuter)(struct tagTriggerNode *trigger, u_int32_t index);
PARAM_CHECK_DONE triggerExecuter;
int dataNumber;
int endIndex;
int dataUnit;
......@@ -64,10 +64,10 @@ typedef struct {
int CalculatorInit(LogicCalculator *calculator, int dataNumber, int dataUnit, int needCondition);
void CalculatorFree(LogicCalculator *calculator);
int ConvertInfixToPrefix(const char *condition, char *prefix, u_int32_t prefixLen);
int ConvertInfixToPrefix(const char *condition, char *prefix, uint32_t prefixLen);
int ComputeCondition(LogicCalculator *calculator, const char *condition);
int GetValueFromContent(const char *content, u_int32_t contentSize, u_int32_t start, char *value, u_int32_t valueSize);
char *GetMatchedSubCondition(const char *condition, const char *input, int length);
int GetValueFromContent(const char *content, uint32_t contentSize, uint32_t start, char *value, uint32_t valueSize);
int CheckMatchSubCondition(const char *condition, const char *input, int length);
#ifdef __cplusplus
#if __cplusplus
......
......@@ -15,16 +15,16 @@
#ifndef STARTUP_TRIGER_MANAGER_H
#define STARTUP_TRIGER_MANAGER_H
#include <pthread.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "cJSON.h"
#include "init_log.h"
#include "param_manager.h"
#include "trigger_checker.h"
#include "list.h"
#include "param_message.h"
#include "param_utils.h"
#include "securec.h"
#include "trigger_checker.h"
#ifdef __cplusplus
#if __cplusplus
......@@ -36,88 +36,132 @@ extern "C" {
#define TRIGGER_ARR_NAME_IN_JSON "jobs"
#define CMDS_ARR_NAME_IN_JSON "cmds"
#define TRIGGER_NODE_IN_QUEUE(trigger) \
(atomic_load_explicit(&(trigger)->serial, memory_order_relaxed) & 0x01)
#define TRIGGER_NODE_SET_QUEUE_FLAG(trigger) \
atomic_store_explicit(&(trigger)->serial, (trigger)->serial | 0x01, memory_order_relaxed)
#define TRIGGER_NODE_CLEAR_QUEUE_FLAG(trigger) \
atomic_store_explicit(&(trigger)->serial, (trigger)->serial & ~0x01, memory_order_relaxed)
#define TRIGGER_EXECUTE_QUEUE 64
#define MAX_CONDITION_NUMBER 64
#define TRIGGER_FLAGS_QUEUE 0x01
#define TRIGGER_FLAGS_RELATED 0x02
#define TRIGGER_FLAGS_ONCE 0x04 // 执行完成后释放
#define TRIGGER_FLAGS_SUBTRIGGER 0x08 // 对init执行后,需要执行的init:xxx=aaa的trigger
#define CMD_INDEX_FOR_PARA_WAIT 0xfffE
#define CMD_INDEX_FOR_PARA_WATCH 0xffff
#define TRIGGER_IN_QUEUE(trigger) (((trigger)->flags & TRIGGER_FLAGS_QUEUE) == TRIGGER_FLAGS_QUEUE)
#define TRIGGER_SET_FLAG(trigger, flag) ((trigger)->flags |= (flag))
#define TRIGGER_CLEAR_FLAG(trigger, flag) ((trigger)->flags &= ~(flag))
#define TRIGGER_TEST_FLAG(trigger, flag) (((trigger)->flags & (flag)) == (flag))
#define TRIGGER_GET_EXT_DATA(trigger, TYPE) \
(trigger)->extDataSize == 0 ? NULL : (TYPE *)(((char *)(trigger)) + (trigger)->extDataOffset)
typedef enum {
TRIGGER_BOOT = 0,
TRIGGER_PARAM,
TRIGGER_UNKNOW,
TRIGGER_MAX
}TriggerType;
TRIGGER_MAX,
TRIGGER_PARAM_WAIT,
TRIGGER_PARAM_WATCH
} TriggerType;
#define PARAM_TRIGGER_FOR_WAIT 0
#define PARAM_TRIGGER_FOR_WATCH 1
typedef struct {
ListNode triggerList;
uint32_t triggerCount;
uint32_t cmdNodeCount;
} TriggerHeader;
#define PARAM_TRIGGER_HEAD_INIT(head) \
do { \
ListInit(&(head).triggerList); \
(head).triggerCount = 0; \
(head).cmdNodeCount = 0; \
} while (0)
// Command对象列表,主要存储每个triger需要执行那些Command操作。
typedef struct CommandNode {
atomic_uint_least32_t next;
char name[MAX_TRIGGER_CMD_NAME_LEN];
typedef struct CommandNode_ {
struct CommandNode_ *next;
uint32_t cmdKeyIndex;
char content[0];
} CommandNode;
typedef struct tagTriggerNode {
atomic_uint_least32_t serial;
atomic_uint_least32_t next;
atomic_uint_least32_t firstCmd;
atomic_uint_least32_t lastCmd;
int type;
char name[MAX_TRIGGER_NAME_LEN];
char condition[0];
typedef struct tagTriggerNode_ {
ListNode node;
uint32_t flags : 24;
uint32_t type : 8;
TriggerHeader *triggerHead;
CommandNode *firstCmd;
CommandNode *lastCmd;
uint16_t extDataOffset;
uint16_t extDataSize;
char *condition;
char name[0];
} TriggerNode;
typedef struct {
atomic_uint_least32_t serial;
u_int32_t dataSize;
u_int32_t startSize;
u_int32_t currOffset;
char data[0];
} TriggerArea;
uint32_t queueCount;
uint32_t startIndex;
uint32_t endIndex;
TriggerNode **executeQueue;
} TriggerExecuteQueue;
typedef struct {
atomic_uint_least32_t firstTrigger;
atomic_uint_least32_t lastTrigger;
} TriggerHeader;
typedef struct {
u_int32_t *executeQueue;
u_int32_t queueCount;
u_int32_t startIndex;
u_int32_t endIndex;
pthread_mutex_t mutex;
} TriggerExecuteQueue;
TriggerHeader triggerHead;
ListNode node;
uint32_t timeout;
ParamTaskPtr stream;
} ParamWatcher;
typedef struct TriggerExtData_ {
int (*excuteCmd)(struct TriggerExtData_ *trigger, int cmd, const char *content);
uint32_t watcherId;
ParamWatcher *watcher;
} TriggerExtData;
typedef struct TriggerWorkSpace {
void (*cmdExec)(TriggerNode *trigger, CommandNode *cmd, const char *content, uint32_t size);
ParamTaskPtr eventHandle;
char buffer[PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX];
TriggerExecuteQueue executeQueue;
TriggerHeader header[TRIGGER_MAX];
TriggerArea *area;
TriggerHeader triggerHead[TRIGGER_MAX];
ParamWatcher watcher;
ListNode waitList;
} TriggerWorkSpace;
int InitTriggerWorkSpace(TriggerWorkSpace *workSpace);
int ParseTrigger(TriggerWorkSpace *workSpace, cJSON *triggerItem);
typedef int (*TRIGGER_MATCH)(LogicCalculator *calculator, TriggerNode *trigger, const char *content, u_int32_t contentSize);
typedef int (*PARAM_CHECK_DONE)(TriggerNode *trigger, u_int32_t index);
typedef int (*CMD_EXECUTE) (TriggerNode *trigger, const char *cmdName, const char *command);
int InitTriggerWorkSpace(void);
void CloseTriggerWorkSpace(void);
TriggerNode *GetTriggerByName(TriggerWorkSpace *workSpace, const char *triggerName, u_int32_t *triggerIndex);
int ExecuteTrigger(TriggerWorkSpace *workSpace, TriggerNode *trigger, CMD_EXECUTE cmdExecuter);
int CheckTrigger(const TriggerWorkSpace *workSpace,
int type, void *content, u_int32_t contentSize, PARAM_CHECK_DONE triggerExecuter);
int CheckParamTrigger(TriggerWorkSpace *workSpace,
const char *content, u_int32_t contentSize, PARAM_CHECK_DONE triggerExecuter);
int CheckAndExecuteTrigger(TriggerWorkSpace *workSpace, const char *content, PARAM_CHECK_DONE triggerExecuter);
typedef int (*TRIGGER_MATCH)(TriggerWorkSpace *workSpace, LogicCalculator *calculator,
TriggerNode *trigger, const char *content, uint32_t contentSize);
int CheckTrigger(TriggerWorkSpace *workSpace, int type,
const char *content, uint32_t contentSize, PARAM_CHECK_DONE triggerExecuter);
int MarkTriggerToParam(TriggerWorkSpace *workSpace, TriggerHeader *triggerHead, const char *name);
int CheckAndMarkTrigger(int type, const char *name);
TriggerNode *ExecuteQueuePop(TriggerWorkSpace *workSpace);
int ExecuteQueuePush(TriggerWorkSpace *workSpace, TriggerNode *trigger, u_int32_t index);
int ExecuteQueuePush(TriggerWorkSpace *workSpace, TriggerNode *trigger);
int ExecuteQueueSize(TriggerWorkSpace *workSpace);
u_int32_t AddTrigger(TriggerWorkSpace *workSpace, int type, const char *name, const char *condition);
u_int32_t AddCommand(TriggerWorkSpace *workSpace, TriggerNode *trigger, const char *cmdName, const char *content);
TriggerNode *AddTrigger(TriggerHeader *triggerHead, const char *name, const char *condition, uint16_t extDataSize);
TriggerNode *GetTriggerByName(TriggerWorkSpace *workSpace, const char *triggerName);
void FreeTrigger(TriggerNode *trigger);
void ClearTrigger(TriggerHeader *head);
int AddCommand(TriggerNode *trigger, uint32_t cmdIndex, const char *content);
CommandNode *GetNextCmdNode(TriggerNode *trigger, CommandNode *curr);
void DumpTrigger(TriggerWorkSpace *workSpace);
void PostParamTrigger(int type, const char *name, const char *value);
TriggerWorkSpace *GetTriggerWorkSpace();
ParamWatcher *GetParamWatcher(const ParamTaskPtr worker);
ParamWatcher *GetNextParamWatcher(TriggerWorkSpace *workSpace, ParamWatcher *curr);
TriggerNode *AddWatcherTrigger(ParamWatcher *watcher,
int triggerType, const char *name, const char *condition, const TriggerExtData *extData);
void DelWatcherTrigger(ParamWatcher *watcher, uint32_t watcherId);
void ClearWatcherTrigger(ParamWatcher *watcher);
TriggerWorkSpace *GetTriggerWorkSpace(void);
#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.
*/
#include "param_message.h"
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#define LABEL "PARAM_MSG"
int ConntectServer(int fd, const char *servername)
{
PARAM_CHECK(fd >= 0, return -1, "Invalid fd %d", fd);
PARAM_CHECK(servername != NULL, return -1, "Invalid servername");
struct sockaddr_un addr;
/* fill socket address structure with server's address */
int ret = memset_s(&addr, sizeof(addr), 0, sizeof(addr));
PARAM_CHECK(ret == 0, return -1, "Failed to memset server address");
addr.sun_family = AF_UNIX;
ret = sprintf_s(addr.sun_path, sizeof(addr.sun_path) - 1, "%s", servername);
PARAM_CHECK(ret > EOK, return -1, "Failed to sprintf_s server address");
int len = offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path);
ret = connect(fd, (struct sockaddr *)&addr, len);
PARAM_CHECK(ret != -1, return -1, "Failed to connect server %s %s", servername, strerror(errno));
return 0;
}
int FillParamMsgContent(ParamMessage *request, uint32_t *start, int type, const char *value, uint32_t length)
{
PARAM_CHECK(request != NULL && start != NULL, return -1, "Invalid param");
PARAM_CHECK(value != NULL && length > 0, return -1, "Invalid value");
uint32_t bufferSize = request->msgSize - sizeof(ParamMessage);
uint32_t offset = *start;
PARAM_CHECK((offset + sizeof(ParamMsgContent) + length) <= bufferSize,
return -1, "Invalid msgSize %u offset %u %d", request->msgSize, offset, type);
ParamMsgContent *content = (ParamMsgContent *)(request->data + offset);
content->type = type;
content->contentSize = length + 1;
int ret = memcpy_s(content->content, content->contentSize - 1, value, length);
PARAM_CHECK(ret == EOK, return -1, "Failed to copy value for %d", type);
content->content[length] = '\0';
offset += sizeof(ParamMsgContent) + PARAM_ALIGN(content->contentSize);
*start = offset;
return 0;
}
ParamMessage *CreateParamMessage(int type, const char *name, uint32_t msgSize)
{
if (msgSize < sizeof(ParamMessage)) {
msgSize = sizeof(ParamMessage);
}
ParamMessage *msg = (ParamMessage *)malloc(msgSize);
PARAM_CHECK(msg != NULL, return NULL, "Failed to malloc message");
msg->type = type;
msg->id.msgId = 0;
msg->msgSize = msgSize;
int ret = strcpy_s(msg->key, sizeof(msg->key) - 1, name);
PARAM_CHECK(ret == EOK, free(msg);
return NULL, "Failed to fill name");
return msg;
}
ParamMsgContent *GetNextContent(const ParamMessage *reqest, uint32_t *offset)
{
ParamMessage *msg = (ParamMessage *)reqest;
if ((msg == NULL) || ((*offset + sizeof(ParamMessage) + sizeof(ParamMsgContent)) >= msg->msgSize)) {
return NULL;
}
ParamMsgContent *content = (ParamMsgContent *)(msg->data + *offset);
*offset += sizeof(ParamMsgContent) + PARAM_ALIGN(content->contentSize);
return content;
}
此差异已折叠。
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "param_utils.h"
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#define LABEL "PARAM_UTILS"
void CheckAndCreateDir(const char *fileName)
{
if (fileName == NULL || *fileName == '\0') {
return;
}
char *path = strndup(fileName, strrchr(fileName, '/') - fileName);
if (path != NULL && access(path, F_OK) != 0) {
mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
}
free(path);
}
int ReadFileInDir(const char *dirPath, const char *includeExt,
int (*processFile)(const char *fileName, void *context), void *context)
{
DIR *pDir = opendir(dirPath);
PARAM_CHECK(pDir != NULL, return -1, "Read dir :%s failed.%d", dirPath, errno);
char *fileName = malloc(PARAM_BUFFER_SIZE);
PARAM_CHECK(fileName != NULL, closedir(pDir);
return -1, "Failed to malloc for %s", dirPath);
struct dirent *dp;
while ((dp = readdir(pDir)) != NULL) {
if (dp->d_type == DT_DIR) {
continue;
}
PARAM_LOGD("ReadFileInDir %s", dp->d_name);
if (includeExt != NULL) {
char *tmp = strstr(dp->d_name, includeExt);
if (tmp == NULL) {
continue;
}
if (strcmp(tmp, includeExt) != 0) {
continue;
}
}
int ret = snprintf_s(fileName, PARAM_BUFFER_SIZE, PARAM_BUFFER_SIZE - 1, "%s/%s", dirPath, dp->d_name);
PARAM_CHECK(ret > EOK, continue, "Failed to get file name for %s", dp->d_name);
struct stat st;
if (stat(fileName, &st) == 0) {
processFile(fileName, context);
}
}
closedir(pDir);
return 0;
}
char *ReadFileData(const char *fileName)
{
if (fileName == NULL) {
return NULL;
}
char *buffer = NULL;
int fd = -1;
do {
fd = open(fileName, O_RDONLY);
PARAM_CHECK(fd >= 0, break, "Failed to read file %s", fileName);
buffer = (char *)malloc(MAX_DATA_BUFFER);
PARAM_CHECK(buffer != NULL, break, "Failed to allocate memory for %s", fileName);
ssize_t readLen = read(fd, buffer, MAX_DATA_BUFFER - 1);
PARAM_CHECK(readLen > 0, break, "Failed to read data for %s", fileName);
buffer[readLen] = '\0';
} while (0);
if (fd != -1) {
close(fd);
}
return buffer;
}
static void TrimString(char *string, uint32_t currLen)
{
for (int i = currLen - 1; i >= 0; i--) {
if (string[i] == ' ' || string[i] == '\0') {
string[i] = '\0';
} else {
break;
}
}
}
int GetSubStringInfo(const char *buff, uint32_t buffLen, char delimiter, SubStringInfo *info, int subStrNumber)
{
size_t i = 0;
// 去掉开始的空格
for (; i < strlen(buff); i++) {
if (!isspace(buff[i])) {
break;
}
}
// 过滤掉注释
if (buff[i] == '#') {
return -1;
}
// 分割字符串
int spaceIsValid = 0;
int curr = 0;
int valueCurr = 0;
for (; i < buffLen; i++) {
if (buff[i] == '\n' || buff[i] == '\r' || buff[i] == '\0') {
break;
}
if (buff[i] == delimiter && valueCurr != 0) {
info[curr].value[valueCurr] = '\0';
TrimString(info[curr].value, valueCurr);
valueCurr = 0;
curr++;
spaceIsValid = 0;
} else {
if (!spaceIsValid && isspace(buff[i])) { // 过滤开始前的无效字符
continue;
}
spaceIsValid = 1;
if ((valueCurr + 1) >= (int)sizeof(info[curr].value)) {
continue;
}
info[curr].value[valueCurr++] = buff[i];
}
if (curr >= subStrNumber) {
break;
}
}
if (valueCurr > 0) {
info[curr].value[valueCurr] = '\0';
TrimString(info[curr].value, valueCurr);
valueCurr = 0;
curr++;
}
return curr;
}
\ No newline at end of file
......@@ -12,145 +12,167 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "sys_param.h"
#include <ctype.h>
#include "param_persist.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 <time.h>
#include <unistd.h>
#include "param_manager.h"
#include "param_service.h"
#include "param_trie.h"
#include "sys_param.h"
#define LABEL "Manager"
#define MAX_BUFF 256
typedef struct {
WorkSpace *workSpace;
WorkSpace *persistWorkSpace;
char *buffer;
} PersistContext;
static ParamPersistWorkSpace g_persistWorkSpace = { 0, NULL, 0, { NULL, NULL, NULL, NULL, NULL } };
static ParamPersistWorkSpace g_persistWorkSpace = {ATOMIC_VAR_INIT(0), };
static int AddPersistParam(const char *name, const char *value, void *context)
{
PARAM_CHECK(value != NULL && name != NULL && context != NULL,
return PARAM_CODE_INVALID_PARAM, "Invalid name or context");
WorkSpace *workSpace = (WorkSpace *)context;
uint32_t dataIndex = 0;
int ret = WriteParam(workSpace, name, value, &dataIndex, 0);
PARAM_CHECK(ret == 0, return ret, "Failed to write param %d name:%s %s", ret, name, value);
return 0;
}
static int ProcessParamTraversal(WorkSpace *workSpace, TrieNode *node, void *cookie)
static int SavePersistParam(WorkSpace *workSpace, ParamTrieNode *node, void *cookie)
{
PARAM_CHECK(workSpace != 0 && node != NULL && cookie != NULL, return -1, "Invalid param");
TrieDataNode *current = (TrieDataNode *)node;
ParamTrieNode *current = (ParamTrieNode *)node;
if (current == NULL || current->dataIndex == 0) {
return 0;
}
DataEntry *entry = (DataEntry *)GetTrieNode(workSpace, &current->dataIndex);
ParamNode *entry = (ParamNode *)GetTrieNode(workSpace, current->dataIndex);
if (entry == NULL) {
return -1;
}
PersistContext *persistContext = (PersistContext *)cookie;
int ret = GetDataName(entry, persistContext->buffer, MAX_BUFF);
PARAM_CHECK(ret == 0, return ret, "GetDataName failed");
if (strncmp(persistContext->buffer, "persist.", strlen("persist.")) != 0) {
return 0;
}
ret = GetDataValue(entry, persistContext->buffer + MAX_BUFF, MAX_BUFF);
if (ret == 0) { // 只支持新建
//PARAM_LOGI("Insert new persist param from normal param %s %s",
// persistContext->buffer, persistContext->buffer + MAX_BUFF);
ret = AddParam(persistContext->persistWorkSpace, persistContext->buffer, persistContext->buffer + MAX_BUFF);
PARAM_LOGD("SavePersistParam %s", entry->data);
if (strncmp(entry->data, PARAM_CONST_PREFIX, strlen(PARAM_CONST_PREFIX)) != 0) {
return 0;
}
PARAM_CHECK(ret == 0, return ret, "Failed to add persist param");
static char name[PARAM_NAME_LEN_MAX] = { 0 };
int ret = memcpy_s(name, PARAM_NAME_LEN_MAX - 1, entry->data, entry->keyLength);
PARAM_CHECK(ret == EOK, return -1, "Failed to read param name %s", entry->data);
name[entry->keyLength] = '\0';
ret = g_persistWorkSpace.persistParamOps.batchSave(cookie, name, entry->data + entry->keyLength + 1);
PARAM_CHECK(ret == 0, return -1, "Failed to write param %s", current->key);
return ret;
}
static int ProcessPersistPropertTraversal(WorkSpace *workSpace, TrieNode *node, void *cookie)
static int BatchSavePersistParam(WorkSpace *workSpace)
{
TrieDataNode *current = (TrieDataNode *)node;
if (current == NULL || current->dataIndex == 0) {
PARAM_LOGI("BatchSavePersistParam");
if (g_persistWorkSpace.persistParamOps.batchSaveBegin == NULL ||
g_persistWorkSpace.persistParamOps.batchSave == NULL ||
g_persistWorkSpace.persistParamOps.batchSaveEnd == NULL) {
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);
PARAM_CHECK(ret == 0, return ret, "GetDataName failed");
ret = GetDataValue(entry, persistContext->buffer + MAX_BUFF, MAX_BUFF);
if (ret == 0) {
//PARAM_LOGI("update normal param %s %s from persist param %u",
// persistContext->buffer, persistContext->buffer + MAX_BUFF, current->dataIndex);
ret = WriteParam(persistContext->workSpace, persistContext->buffer, persistContext->buffer + MAX_BUFF);
}
PARAM_CHECK(ret == 0, return ret, "Failed to add persist param");
PERSIST_SAVE_HANDLE handle;
int ret = g_persistWorkSpace.persistParamOps.batchSaveBegin(&handle);
PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "Failed to save persist");
ParamTrieNode *root = FindTrieNode(workSpace, PARAM_CONST_PREFIX, strlen(PARAM_CONST_PREFIX), NULL);
ret = TraversalTrieNode(workSpace, root, SavePersistParam, handle);
g_persistWorkSpace.persistParamOps.batchSaveEnd(handle);
PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "Save persist param fail");
PARAM_CLEAR_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_UPDATE);
(void)time(&g_persistWorkSpace.lastSaveTimer);
return ret;
}
int InitPersistParamWorkSpace(const char *context)
int InitPersistParamWorkSpace(ParamWorkSpace *workSpace)
{
u_int32_t flags = atomic_load_explicit(&g_persistWorkSpace.flags, memory_order_relaxed);
if ((flags & WORKSPACE_FLAGS_INIT) == WORKSPACE_FLAGS_INIT) {
if (PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_INIT)) {
return 0;
}
g_persistWorkSpace.persistWorkSpace.compareTrieNode = CompareTrieDataNode;
g_persistWorkSpace.persistWorkSpace.allocTrieNode = AllocateTrieDataNode;
int ret = InitPersistWorkSpace(PARAM_PERSIST_PATH, &g_persistWorkSpace.persistWorkSpace);
PARAM_CHECK(ret == 0, return ret, "Failed to init persist param");
atomic_store_explicit(&g_persistWorkSpace.flags, WORKSPACE_FLAGS_INIT, memory_order_release);
return ret;
(void)time(&g_persistWorkSpace.lastSaveTimer);
#ifdef PARAM_SUPPORT_SAVE_PERSIST
RegisterPersistParamOps(&g_persistWorkSpace.persistParamOps);
#endif
PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_INIT);
return 0;
}
void ClosePersistParamWorkSpace(void)
{
if (g_persistWorkSpace.saveTimer != NULL) {
ParamTaskClose(g_persistWorkSpace.saveTimer);
}
g_persistWorkSpace.flags = 0;
}
int RefreshPersistParams(ParamWorkSpace *workSpace, const char *context)
int LoadPersistParam(ParamWorkSpace *workSpace)
{
int ret = InitPersistParamWorkSpace(context);
int ret = InitPersistParamWorkSpace(workSpace);
PARAM_CHECK(ret == 0, return ret, "Failed to init persist param");
u_int32_t flags = atomic_load_explicit(&g_persistWorkSpace.flags, memory_order_relaxed);
if ((flags & WORKSPACE_FLAGS_LOADED) == WORKSPACE_FLAGS_LOADED) {
PARAM_LOGE("RefreshPersistParams has been loaded");
if (PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED)) {
PARAM_LOGE("Persist param has been loaded");
return 0;
}
// 申请临时的缓存,用于数据读取
char *buffer = (char *)malloc(MAX_BUFF + MAX_BUFF);
PARAM_CHECK(buffer != NULL, return -1, "Failed to malloc memory for param");
PersistContext persistContext = {
&workSpace->paramSpace, &g_persistWorkSpace.persistWorkSpace, buffer
};
// 遍历当前的参数,并把persist的写入
ret = TraversalTrieDataNode(&workSpace->paramSpace,
(TrieDataNode *)workSpace->paramSpace.rootNode, ProcessParamTraversal, &persistContext);
// 修改默认参数值
ret = TraversalTrieDataNode(&g_persistWorkSpace.persistWorkSpace,
(TrieDataNode *)g_persistWorkSpace.persistWorkSpace.rootNode, ProcessPersistPropertTraversal, &persistContext);
atomic_store_explicit(&g_persistWorkSpace.flags, flags | WORKSPACE_FLAGS_LOADED, memory_order_release);
free(buffer);
return ret;
ret = -1;
if (g_persistWorkSpace.persistParamOps.load != NULL) {
ret = g_persistWorkSpace.persistParamOps.load(AddPersistParam, &workSpace->paramSpace);
}
if (ret == 0) {
PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED);
} else {
PARAM_LOGE("Failed to load persist param ");
}
// 刷新新增的常量到persist
BatchSavePersistParam(&workSpace->paramSpace);
return 0;
}
void ClosePersistParamWorkSpace()
static void TimerCallbackForSave(ParamTaskPtr timer, void *context)
{
CloseWorkSpace(&g_persistWorkSpace.persistWorkSpace);
atomic_store_explicit(&g_persistWorkSpace.flags, 0, memory_order_release);
UNUSED(context);
ParamTaskClose(timer);
g_persistWorkSpace.saveTimer = NULL;
if (!PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_UPDATE)) {
return;
}
BatchSavePersistParam((WorkSpace *)context);
}
int WritePersistParam(const char *name, const char *value)
int WritePersistParam(ParamWorkSpace *workSpace, const char *name, const char *value)
{
PARAM_CHECK(value != NULL && name != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid param");
if (strncmp(name, "persist.", strlen("persist.")) != 0) {
if (strncmp(name, PARAM_CONST_PREFIX, strlen(PARAM_CONST_PREFIX)) != 0) {
return 0;
}
int ret = InitPersistParamWorkSpace("");
PARAM_CHECK(ret == 0, return ret, "Failed to init persist param");
u_int32_t flags = atomic_load_explicit(&g_persistWorkSpace.flags, memory_order_relaxed);
if ((flags & WORKSPACE_FLAGS_LOADED) != WORKSPACE_FLAGS_LOADED) {
if (!PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED)) {
PARAM_LOGE("Can not save persist param before load %s ", name);
return 0;
}
return WriteParam(&g_persistWorkSpace.persistWorkSpace, name, value);
PARAM_LOGD("WritePersistParam name %s ", name);
if (g_persistWorkSpace.persistParamOps.save != NULL) {
g_persistWorkSpace.persistParamOps.save(name, value);
}
// 不需要批量保存
if (g_persistWorkSpace.persistParamOps.batchSave == NULL) {
return 0;
}
// check timer for save all
time_t currTimer;
(void)time(&currTimer);
uint32_t diff = (uint32_t)difftime(currTimer, g_persistWorkSpace.lastSaveTimer);
if (diff > PARAM_MUST_SAVE_PARAM_DIFF) {
if (g_persistWorkSpace.saveTimer != NULL) {
ParamTaskClose(g_persistWorkSpace.saveTimer);
g_persistWorkSpace.saveTimer = NULL;
}
return BatchSavePersistParam(&workSpace->paramSpace);
}
PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_UPDATE);
if (g_persistWorkSpace.saveTimer == NULL) {
ParamTimerCreate(&g_persistWorkSpace.saveTimer, TimerCallbackForSave, &workSpace->paramSpace);
ParamTimerStart(g_persistWorkSpace.saveTimer, PARAM_MUST_SAVE_PARAM_DIFF * MS_UNIT, MS_UNIT);
}
return 0;
}
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "watcher.h"
#include "iservice_registry.h"
#include "securec.h"
#include "system_ability_definition.h"
#include "watcher_utils.h"
namespace OHOS {
namespace init_param {
void Watcher::OnParamerterChange(const std::string &name, const std::string &value)
{
UNUSED(name);
UNUSED(value);
}
} // namespace init_param
} // namespace OHOS
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册