提交 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);
return result;
}
static void OnConnection(uv_connect_t *connect, int status)
static int StartRequest(int *fd, ParamMessage *request, int timeout)
{
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");
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);
// read result
ret = uv_read_start((uv_stream_t*)&(request->handle), OnReceiveAlloc, OnReceiveResponse);
PARAM_CHECK(ret >= 0, return, "Failed to uv_read_start response");
if (ret == 0) { // check result
ret = ProcessRecvMsg(request);
}
return ret;
}
static int StartRequest(int cmd, RequestNode *request)
int SystemSetParameter(const char *name, const char *value)
{
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;
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 %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;
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);
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 result;
return ret;
}
int SystemSetParameter(const char *name, const char *value)
int SystemWaitParameter(const char *name, const char *value, int32_t timeout)
{
PARAM_CHECK(name != NULL && value != NULL, return -1, "Invalid param");
InitParamClient();
PARAM_CHECK(name != NULL, return -1, "Invalid name");
int ret = CheckParamName(name, 0);
PARAM_CHECK(ret == 0, return ret, "Illegal param name");
PARAM_LOGD("StartRequest %s", name);
u_int32_t msgSize = sizeof(RequestMsg) + strlen(name) + strlen(value) + 2;
RequestNode *request = (RequestNode *)malloc(sizeof(RequestNode) + msgSize);
PARAM_CHECK(request != NULL, return -1, "Failed to malloc for connect");
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);
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);
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,51 +16,24 @@
#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
}
......
/*
* 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,15 +15,37 @@
#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"
#ifndef __NR_futex
#define PARAM_NR_FUTEX 202 /* syscall number */
#else
#define PARAM_NR_FUTEX __NR_futex
#endif
#if defined FUTEX_WAIT || defined FUTEX_WAKE
#include <linux/futex.h>
#else
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#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 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
#ifdef __cplusplus
#if __cplusplus
......@@ -31,105 +53,71 @@ extern "C" {
#endif
#endif
#define PARAM_WORKSPACE_MAX 64*1024
#define TRIE_SERIAL_DIRTY_OFFSET 1
#define TRIE_SERIAL_KEY_LEN_OFFSET 24
#define TRIE_SERIAL_DATA_LEN_OFFSET 16
#define PARAM_WORKSPACE_MAX (80 * 1024)
#define FILENAME_LEN_MAX 255
#define TRIE_DATA_LEN_MAX 128
#define NODE_INDEX unsigned int
#define TRIE_NODE_HEADER \
atomic_uint_least32_t serial; \
NODE_INDEX left; \
NODE_INDEX right;
#define DATA_ENTRY_KEY_LEN(entry) (entry)->dataLength >> TRIE_SERIAL_KEY_LEN_OFFSET
#define DATA_ENTRY_DATA_LEN(entry) (((entry)->dataLength >> TRIE_SERIAL_DATA_LEN_OFFSET) & 0x00FF)
#define DATA_ENTRY_DIRTY(serial) ((serial) & 1)
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
#define __futex(ftx, op, value, timeout, bitset) \
syscall(__NR_futex, ftx, op, value, timeout, NULL, bitset)
#define futex_wake(ftx, count) __futex(ftx, FUTEX_WAKE, count, NULL, 0)
#define futex_wait(ftx, value, timeout) __futex(ftx, FUTEX_WAIT, value, timeout, 0)
typedef struct {
TRIE_NODE_HEADER;
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;
}
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;
}
return WriteParam(&g_persistWorkSpace.persistWorkSpace, name, value);
// 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
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
{
"jobs" : [{
"name" : "boot",
"cmds" : [
"start param_watcher"
]
}
],
"services" : [{
"name" : "param_watcher",
"path" : ["/system/bin/sa_main", "/system/profile/param_watcher.xml"],
"uid" : "system",
"gid" : ["system", "shell"]
}
]
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册