mirror of
https://github.com/openharmony/startup_init_lite.git
synced 2026-07-01 22:44:01 -04:00
init: code Refactoring, watchdog, hdc_flashed, ramdisk
Signed-off-by: sun_fan <sun_fan1@hoperun.com>
This commit is contained in:
@@ -62,7 +62,8 @@
|
||||
<!--filteritem type="filename" name="*.uvwxyz" desc="Describe the reason for filtering scan results"/-->
|
||||
<!--filteritem type="filepath" name="abcdefg/.*.uvwxyz" desc="Describe the reason for filtering scan results"/-->
|
||||
<!--filteritem type="filepath" name="projectroot/[a-zA-Z0-9]{20,}.sh" desc="Temp files"/-->
|
||||
<filteritem type="filname" name="*.jpg|*.png|*.gif|*.pdf" desc="already checked"/>
|
||||
<filteritem type="filname" name="*.jpg|*.png|*.gif|*.pdf" desc="already checked"/>
|
||||
<filteritem type="filepath" name="services/test/unittest/test_data/proc/*" desc="启动功能UT测试的资源文件"/>
|
||||
</filefilter>
|
||||
|
||||
</filefilterlist>
|
||||
|
||||
@@ -31,7 +31,7 @@ int32_t StartDynamicProcess(const char *name)
|
||||
return -1;
|
||||
}
|
||||
if (SetParameter("ohos.ctl.start", name) != 0) {
|
||||
HILOG_ERROR(LOG_CORE, "Set param for {public}%s failed.\n", name);
|
||||
HILOG_ERROR(LOG_CORE, "Set param for %{public}s failed.\n", name);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -44,7 +44,7 @@ int32_t StopDynamicProcess(const char *name)
|
||||
return -1;
|
||||
}
|
||||
if (SetParameter("ohos.ctl.stop", name) != 0) {
|
||||
HILOG_ERROR(LOG_CORE, "Set param for {public}%s failed.\n", name);
|
||||
HILOG_ERROR(LOG_CORE, "Set param for %{public}s failed.\n", name);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
# 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")
|
||||
|
||||
fs_manager_sources = [
|
||||
"fstab.c",
|
||||
"fstab_mount.c",
|
||||
]
|
||||
|
||||
fs_manager_include_dirs = [
|
||||
"//base/startup/init_lite/interfaces/innerkits/include",
|
||||
"//third_party/bounds_checking_function/include",
|
||||
"//base/startup/init_lite/services/log",
|
||||
"//base/startup/init_lite/services/include",
|
||||
]
|
||||
|
||||
fs_manager_deps = [
|
||||
"//base/startup/init_lite/services/log:init_log",
|
||||
"//base/startup/init_lite/services/utils:libinit_utils",
|
||||
"//third_party/bounds_checking_function:libsec_static",
|
||||
]
|
||||
|
||||
ohos_shared_library("libfsmanager_shared") {
|
||||
sources = fs_manager_sources
|
||||
deps = fs_manager_deps
|
||||
include_dirs = fs_manager_include_dirs
|
||||
part_name = "init"
|
||||
install_images = [
|
||||
"system",
|
||||
]
|
||||
}
|
||||
|
||||
ohos_static_library("libfsmanager_static") {
|
||||
sources = fs_manager_sources
|
||||
deps = fs_manager_deps
|
||||
include_dirs = fs_manager_include_dirs
|
||||
part_name = "init"
|
||||
}
|
||||
|
||||
Executable
+391
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <libgen.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include "fs_manager/fs_manager.h"
|
||||
#include "init_utils.h"
|
||||
#include "securec.h"
|
||||
|
||||
struct FsManagerFlags {
|
||||
char *name;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
struct MountFlags {
|
||||
char *name;
|
||||
unsigned long flags;
|
||||
};
|
||||
|
||||
unsigned int ConvertFlags(char *flagBuffer)
|
||||
{
|
||||
static struct FsManagerFlags fsFlags[] = {
|
||||
{"check", FS_MANAGER_CHECK},
|
||||
{"wait", FS_MANAGER_WAIT},
|
||||
{"required", FS_MANAGER_REQUIRED},
|
||||
};
|
||||
|
||||
if (flagBuffer == NULL || *flagBuffer == '\0') {
|
||||
// No valid flags.
|
||||
return 0;
|
||||
}
|
||||
printf("[fs_manager][debug], fstab flags string: %s\n", flagBuffer);
|
||||
int flagCount = 0;
|
||||
unsigned int flags = 0;
|
||||
const int maxCount = 3;
|
||||
char **vector = SplitStringExt(flagBuffer, ",", &flagCount, maxCount);
|
||||
if (vector == NULL || flagCount == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < ARRAY_LENGTH(fsFlags); i++) {
|
||||
for (int j = 0; j < flagCount; j++) {
|
||||
printf("[fs_manager][debug], flag: %s\n", vector[j]);
|
||||
if (strcmp(fsFlags[i].name, vector[j]) == 0) {
|
||||
flags |= fsFlags[i].flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
FreeStringVector(vector, flagCount);
|
||||
return flags;
|
||||
}
|
||||
|
||||
static void AddToFstab(Fstab *fstab, FstabItem *item)
|
||||
{
|
||||
if (fstab == NULL || item == NULL) {
|
||||
return;
|
||||
}
|
||||
if (fstab->head != NULL) {
|
||||
item->next = fstab->head->next;
|
||||
fstab->head->next = item;
|
||||
} else {
|
||||
fstab->head = item;
|
||||
}
|
||||
}
|
||||
|
||||
void ReleaseFstabItem(FstabItem *item)
|
||||
{
|
||||
if (item != NULL) {
|
||||
if (item->deviceName != NULL) {
|
||||
free(item->deviceName);
|
||||
item->deviceName = NULL;
|
||||
}
|
||||
|
||||
if (item->mountPoint != NULL) {
|
||||
free(item->mountPoint);
|
||||
item->mountPoint = NULL;
|
||||
}
|
||||
|
||||
if (item->fsType != NULL) {
|
||||
free(item->fsType);
|
||||
item->fsType = NULL;
|
||||
}
|
||||
|
||||
if (item->mountOptions != NULL) {
|
||||
free(item->mountOptions);
|
||||
item->mountOptions = NULL;
|
||||
}
|
||||
free(item);
|
||||
item = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ReleaseFstab(Fstab *fstab)
|
||||
{
|
||||
if (fstab != NULL) {
|
||||
FstabItem *item = fstab->head;
|
||||
while (item != NULL) {
|
||||
FstabItem *tmp = item->next;
|
||||
ReleaseFstabItem(item);
|
||||
item = tmp;
|
||||
}
|
||||
free(fstab);
|
||||
fstab = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int ParseFstabPerLine(char *str, Fstab *fstab, bool procMounts)
|
||||
{
|
||||
if (str == NULL || fstab == NULL) {
|
||||
return -1;
|
||||
}
|
||||
const char *separator = " \t";
|
||||
char *rest = NULL;
|
||||
FstabItem *item = NULL;
|
||||
char *p = NULL;
|
||||
|
||||
if ((item = (FstabItem *)calloc(1, sizeof(FstabItem))) == NULL) {
|
||||
errno = ENOMEM;
|
||||
printf("[fs_manager] Allocate memory for FS table item failed, err = %d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
if ((p = strtok_r(str, separator, &rest)) == NULL) {
|
||||
fprintf(stderr, "Failed to parse block device.\n");
|
||||
break;
|
||||
}
|
||||
item->deviceName = strdup(p);
|
||||
|
||||
if ((p = strtok_r(NULL, separator, &rest)) == NULL) {
|
||||
fprintf(stderr, "Failed to parse mount point.\n");
|
||||
break;
|
||||
}
|
||||
item->mountPoint = strdup(p);
|
||||
|
||||
if ((p = strtok_r(NULL, separator, &rest)) == NULL) {
|
||||
fprintf(stderr, "Failed to parse fs type.\n");
|
||||
break;
|
||||
}
|
||||
item->fsType = strdup(p);
|
||||
|
||||
if ((p = strtok_r(NULL, separator, &rest)) == NULL) {
|
||||
fprintf(stderr, "Failed to parse mount options.\n");
|
||||
break;
|
||||
}
|
||||
item->mountOptions = strdup(p);
|
||||
|
||||
if ((p = strtok_r(NULL, separator, &rest)) == NULL) {
|
||||
fprintf(stderr, "Failed to parse fs manager flags.\n");
|
||||
break;
|
||||
}
|
||||
// @fsManagerFlags only for fstab
|
||||
// Ignore it if we read from /proc/mounts
|
||||
if (!procMounts) {
|
||||
item->fsManagerFlags = ConvertFlags(p);
|
||||
} else {
|
||||
item->fsManagerFlags = 0;
|
||||
}
|
||||
AddToFstab(fstab, item);
|
||||
return 0;
|
||||
} while (0);
|
||||
|
||||
free(item);
|
||||
item = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
Fstab *ReadFstabFromFile(const char *file, bool procMounts)
|
||||
{
|
||||
char *line = NULL;
|
||||
size_t allocn = 0;
|
||||
ssize_t readn = 0;
|
||||
Fstab *fstab = NULL;
|
||||
|
||||
if (file == NULL) {
|
||||
printf("[fs_manager], invalid file\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FILE *fp = fopen(file, "r");
|
||||
if (fp == NULL) {
|
||||
printf("[fs_manager] Open %s failed, err = %d", file, errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((fstab = (Fstab *)calloc(1, sizeof(Fstab))) == NULL) {
|
||||
printf("[fs_manager] Allocate memory for FS table failed, err = %d\n", errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Record line number of fstab file
|
||||
size_t ln = 0;
|
||||
while ((readn = getline(&line, &allocn, fp)) != -1) {
|
||||
char *p = NULL;
|
||||
ln++;
|
||||
if (line[readn - 1] == '\n') {
|
||||
line[readn - 1] = '\0';
|
||||
}
|
||||
p = line;
|
||||
while (isspace(*p)) {
|
||||
p++;
|
||||
}
|
||||
|
||||
if (*p == '\0' || *p == '#') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ParseFstabPerLine(p, fstab, procMounts) < 0) {
|
||||
if (errno == ENOMEM) {
|
||||
// Ran out of memory, there is no reason to continue.
|
||||
break;
|
||||
}
|
||||
// If one line in fstab file parsed with a failure. just give a warning
|
||||
// and skip it.
|
||||
printf("[fs_manager][warning] Cannot parse file \" %s \" at line %u. skip it\n", file, ln);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (line != NULL) {
|
||||
free(line);
|
||||
}
|
||||
return fstab;
|
||||
}
|
||||
|
||||
FstabItem *FindFstabItemForMountPoint(Fstab fstab, const char *mp)
|
||||
{
|
||||
FstabItem *item = NULL;
|
||||
if (mp != NULL) {
|
||||
for (item = fstab.head; item != NULL; item = item->next) {
|
||||
if (strcmp(item->mountPoint, mp) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
FstabItem *FindFstabItemForPath(Fstab fstab, const char *path)
|
||||
{
|
||||
FstabItem *item = NULL;
|
||||
|
||||
if (path == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char tmp[PATH_MAX] = {0};
|
||||
char *dir = NULL;
|
||||
if (strncpy_s(tmp, PATH_MAX -1, path, strlen(path)) != EOK) {
|
||||
printf("[fs_manager][error], Failed to copy path\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dir = tmp;
|
||||
while (true) {
|
||||
item = FindFstabItemForMountPoint(fstab, dir);
|
||||
if (item != NULL) {
|
||||
break;
|
||||
}
|
||||
dir = dirname(dir);
|
||||
// Reverse walk through path and met "/", just quit.
|
||||
if (dir == NULL || strcmp(dir, "/") == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
static const struct MountFlags mountFlags[] = {
|
||||
{ "noatime", MS_NOATIME },
|
||||
{ "noexec", MS_NOEXEC },
|
||||
{ "nosuid", MS_NOSUID },
|
||||
{ "nodev", MS_NODEV },
|
||||
{ "nodiratime", MS_NODIRATIME },
|
||||
{ "ro", MS_RDONLY },
|
||||
{ "rw", 0 },
|
||||
{ "sync", MS_SYNCHRONOUS },
|
||||
{ "remount", MS_REMOUNT },
|
||||
{ "bind", MS_BIND },
|
||||
{ "rec", MS_REC },
|
||||
{ "unbindable", MS_UNBINDABLE },
|
||||
{ "private", MS_PRIVATE },
|
||||
{ "slave", MS_SLAVE },
|
||||
{ "shared", MS_SHARED },
|
||||
{ "defaults", 0 },
|
||||
};
|
||||
|
||||
static bool IsDefaultMountFlags(const char *str) {
|
||||
bool isDefault = false;
|
||||
|
||||
if (str != NULL) {
|
||||
for (size_t i = 0; i < ARRAY_LENGTH(mountFlags); i++) {
|
||||
if (strcmp(str, mountFlags[i].name) == 0) {
|
||||
isDefault = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
static unsigned long ParseDefaultMountFlag(const char *str)
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
|
||||
if (str != NULL) {
|
||||
for (size_t i = 0; i < ARRAY_LENGTH(mountFlags); i++) {
|
||||
if (strcmp(str, mountFlags[i].name) == 0) {
|
||||
flags = mountFlags[i].flags;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
unsigned long GetMountFlags(char *mountFlags, char *fsSpecificData, size_t fsSpecificDataSize)
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
|
||||
if (mountFlags == NULL || fsSpecificData == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int flagCount = 0;
|
||||
// Why max count of mount flags is 15?
|
||||
// There are lots for mount flags defined in sys/mount.h
|
||||
// But we only support to parse 15 in @ParseDefaultMountFlags() function
|
||||
// So set default mount flag number to 15.
|
||||
// If the item configured in fstab contains flag over than 15,
|
||||
// @SplitStringExt can handle it and parse them all. but the parse function will drop it.
|
||||
const int maxCount = 15;
|
||||
char **flagsVector = SplitStringExt(mountFlags, ",", &flagCount, maxCount);
|
||||
|
||||
if (flagsVector == NULL || flagCount == 0) {
|
||||
// No flags or something wrong in SplitStringExt,just return.
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < flagCount; i++) {
|
||||
char *p = flagsVector[i];
|
||||
if (IsDefaultMountFlags(p)) {
|
||||
flags |= ParseDefaultMountFlag(p);
|
||||
} else {
|
||||
if (strncat_s(fsSpecificData, fsSpecificDataSize - 1, p, strlen(p)) != EOK) {
|
||||
printf("[fs_manager][warning], Failed to append mount flag \" %s \", ignore it\n", p);
|
||||
continue;
|
||||
}
|
||||
if (i == flagCount - 1) { // last flags, do not need to append ','
|
||||
break;
|
||||
}
|
||||
// Combined each mount flag with ','
|
||||
if (strncat_s(fsSpecificData, fsSpecificDataSize - 1, ",", 1) != EOK) {
|
||||
printf("[fs_manager][warning], Failed to append comma\n");
|
||||
break; // If cannot add ',' to the end of flags, there is not reason to continue.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FreeStringVector(flagsVector, flagCount);
|
||||
return flags;
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
+297
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include "fs_manager/fs_manager.h"
|
||||
#include "init_log.h"
|
||||
#include "init_utils.h"
|
||||
#include "securec.h"
|
||||
|
||||
#define FS_MANAGER_BUFFER_SIZE 512
|
||||
bool IsSupportedFilesystem(const char *fsType)
|
||||
{
|
||||
static const char *supportedFilesystem[] = {"ext4", "f2fs", NULL};
|
||||
|
||||
bool supported = false;
|
||||
int index = 0;
|
||||
if (fsType != NULL) {
|
||||
while (supportedFilesystem[index] != NULL) {
|
||||
if (strcmp(supportedFilesystem[index++], fsType) == 0) {
|
||||
supported = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return supported;
|
||||
}
|
||||
|
||||
static int ExecCommand(int argc, char **argv)
|
||||
{
|
||||
if (argc == 0 || argv == NULL || argv[0] == NULL) {
|
||||
return -1;
|
||||
}
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
INIT_LOGE("Fork new process to format failed: %d", errno);
|
||||
return -1;
|
||||
}
|
||||
if (pid == 0) {
|
||||
execv(argv[0], argv);
|
||||
exit(-1);
|
||||
}
|
||||
int status;
|
||||
waitpid(pid, &status, 0);
|
||||
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
|
||||
printf("Command %s failed with status %d", argv[0], WEXITSTATUS(status));
|
||||
}
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
int DoFormat(const char *devPath, const char *fsType)
|
||||
{
|
||||
if (devPath == NULL || fsType == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!IsSupportedFilesystem(fsType)) {
|
||||
printf("[fs_manager][error] Do not support filesystem \" %s \"\n", fsType);
|
||||
return -1;
|
||||
}
|
||||
int ret = 0;
|
||||
#define BLOCK_SIZE_BUFFER (64)
|
||||
char blockSizeBuffer[BLOCK_SIZE_BUFFER] = {0};
|
||||
if (strcmp(fsType, "ext4") == 0) {
|
||||
const unsigned int blockSize = 4096;
|
||||
if (snprintf_s(blockSizeBuffer, BLOCK_SIZE_BUFFER, BLOCK_SIZE_BUFFER - 1, "%u", blockSize) == -1) {
|
||||
printf("[fs_manager][error] Failed to build block size buffer\n");
|
||||
return -1;
|
||||
}
|
||||
char *formatCmds[] = {
|
||||
"/bin/mke2fs", "-F", "-t", (char *)fsType, "-b", blockSizeBuffer, (char *)devPath, NULL
|
||||
};
|
||||
int argc = ARRAY_LENGTH(formatCmds);
|
||||
char **argv = (char **)formatCmds;
|
||||
ret = ExecCommand(argc, argv);
|
||||
} else if (strcmp(fsType, "f2fs") == 0) {
|
||||
char *formatCmds[] = {
|
||||
"/bin/make_f2fs", (char *)devPath, NULL
|
||||
};
|
||||
int argc = ARRAY_LENGTH(formatCmds);
|
||||
char **argv = (char **)formatCmds;
|
||||
ret = ExecCommand(argc, argv);
|
||||
}
|
||||
#undef BLOCK_SIZE_BUFFER
|
||||
return ret;
|
||||
}
|
||||
|
||||
MountStatus GetMountStatusForMountPoint(const char *mp)
|
||||
{
|
||||
if (mp == NULL) {
|
||||
return MOUNT_ERROR;
|
||||
}
|
||||
char buffer[FS_MANAGER_BUFFER_SIZE] = {0};
|
||||
size_t n = 0;
|
||||
const int expectedItems = 6;
|
||||
int count = 0;
|
||||
char **mountItems = NULL;
|
||||
MountStatus status = MOUNT_ERROR;
|
||||
bool found = false;
|
||||
|
||||
FILE *fp = fopen("/proc/mounts", "r");
|
||||
if (fp == NULL) {
|
||||
return status;
|
||||
}
|
||||
while (fgets(buffer, sizeof(buffer) - 1, fp) != NULL) {
|
||||
n = strlen(buffer);
|
||||
if (buffer[n - 1] == '\n') {
|
||||
buffer[n - 1] = '\0';
|
||||
}
|
||||
mountItems = SplitStringExt(buffer, " ", &count, expectedItems);
|
||||
if (mountItems != NULL && count == expectedItems) {
|
||||
// Second item in /proc/mounts is mount point
|
||||
if (strcmp(mountItems[1], mp) == 0) {
|
||||
FreeStringVector(mountItems, count);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
FreeStringVector(mountItems, count);
|
||||
}
|
||||
}
|
||||
if (found == true) {
|
||||
status = MOUNT_MOUNTED;
|
||||
} else if (feof(fp) > 0) {
|
||||
status = MOUNT_UMOUNTED;
|
||||
}
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
static int Mount(const char *source, const char *target, const char *fsType,
|
||||
unsigned long flags, const char *data)
|
||||
{
|
||||
struct stat st = {};
|
||||
int rc = -1;
|
||||
|
||||
if (source == NULL || target == NULL || fsType == NULL) {
|
||||
printf("[fs_manager][error] Invalid argment for mount\n");
|
||||
return -1;
|
||||
}
|
||||
if (stat(target, &st) != 0 && errno != ENOENT) {
|
||||
printf("[fs_manager][error] Cannot get stat of \" %s \", err = %d\n", target, errno);
|
||||
return -1;
|
||||
}
|
||||
if ((st.st_mode & S_IFMT) == S_IFLNK) { // link, delete it.
|
||||
unlink(target);
|
||||
}
|
||||
if (mkdir(target, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) {
|
||||
if (errno != EEXIST) {
|
||||
printf("[fs_manager][error] Failed to create dir \" %s \", err = %d\n", target, errno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
errno = 0;
|
||||
while ((rc = mount(source, target, fsType, flags, data) != 0)) {
|
||||
if (errno == EAGAIN) {
|
||||
printf("[fs_manager][warning] Mount %s to %s failed. try again", source, target);
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int MountOneItem(FstabItem *item)
|
||||
{
|
||||
if (item == NULL) {
|
||||
return -1;
|
||||
}
|
||||
unsigned long mountFlags;
|
||||
char fsSpecificData[FS_MANAGER_BUFFER_SIZE] = {0};
|
||||
|
||||
mountFlags = GetMountFlags(item->mountOptions, fsSpecificData, sizeof(fsSpecificData));
|
||||
if (!IsSupportedFilesystem(item->fsType)) {
|
||||
printf("[fs_manager][error]Unsupported file system \" %s \"", item->fsType);
|
||||
return -1;
|
||||
}
|
||||
if (FM_MANAGER_WAIT_ENABLED(item->fsManagerFlags)) {
|
||||
WaitForFile(item->deviceName, WAIT_MAX_COUNT);
|
||||
}
|
||||
int rc = Mount(item->deviceName, item->mountPoint, item->fsType, mountFlags, fsSpecificData);
|
||||
if (rc != 0) {
|
||||
INIT_LOGE("Mount %s to %s failed %d", item->deviceName, item->mountPoint, errno);
|
||||
} else {
|
||||
INIT_LOGI("Mount %s to %s successful", item->deviceName, item->mountPoint);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int CheckRequiredAndMount(FstabItem *item, bool required)
|
||||
{
|
||||
int rc = -1;
|
||||
if (item == NULL) {
|
||||
return rc;
|
||||
}
|
||||
if (required) { // Mount partition during first startup.
|
||||
if (FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) {
|
||||
rc = MountOneItem(item);
|
||||
}
|
||||
} else { // Mount partition during second startup.
|
||||
if (!FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) {
|
||||
rc = MountOneItem(item);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int MountAllWithFstabFile(const char *fstabFile, bool required)
|
||||
{
|
||||
if (fstabFile == NULL || *fstabFile == '\0') {
|
||||
return -1;
|
||||
}
|
||||
Fstab *fstab = NULL;
|
||||
if ((fstab = ReadFstabFromFile(fstabFile, false)) == NULL) {
|
||||
printf("[fs_manager][error] Read fstab file \" %s \" failed\n", fstabFile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
FstabItem *item = NULL;
|
||||
int rc = -1;
|
||||
for (item = fstab->head; item != NULL; item = item->next) {
|
||||
rc = CheckRequiredAndMount(item, required);
|
||||
}
|
||||
ReleaseFstab(fstab);
|
||||
fstab = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int UmountAllWithFstabFile(const char *fstabFile)
|
||||
{
|
||||
if (fstabFile == NULL || *fstabFile == '\0') {
|
||||
return -1;
|
||||
}
|
||||
Fstab *fstab = NULL;
|
||||
if ((fstab = ReadFstabFromFile(fstabFile, false)) == NULL) {
|
||||
printf("[fs_manager][error] Read fstab file \" %s \" failed\n", fstabFile);
|
||||
return -1;;
|
||||
}
|
||||
|
||||
FstabItem *item = NULL;
|
||||
int rc = -1;
|
||||
for (item = fstab->head; item != NULL; item = item->next) {
|
||||
printf("[fs_manager][info]Umount %s\n", item->mountPoint);
|
||||
MountStatus status = GetMountStatusForMountPoint(item->mountPoint);
|
||||
if (status == MOUNT_ERROR) {
|
||||
printf("[fs_manager][warning] Cannot get mount status of mount point \" %s \"\n", item->mountPoint);
|
||||
continue; // Cannot get mount status, just ignore it and try next one.
|
||||
} else if (status == MOUNT_UMOUNTED) {
|
||||
printf("[fs_manager][info] Mount point \" %s \" already unmounted. device path: %s, fs type: %s\n",
|
||||
item->mountPoint, item->deviceName, item->fsType);
|
||||
continue;
|
||||
} else {
|
||||
rc = umount(item->mountPoint);
|
||||
if (rc == -1) {
|
||||
printf("[fs_manager][error] Umount %s failed, device path: %s, fs type: %s, err = %d",
|
||||
item->mountPoint, item->deviceName, item->fsType, errno);
|
||||
} else {
|
||||
printf("[fs_manager][info] Umount %s successfully\n",
|
||||
item->mountPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
ReleaseFstab(fstab);
|
||||
fstab = NULL;
|
||||
return rc;
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef STARTUP_FS_MANAGER_H
|
||||
#define STARTUP_FS_MANAGER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Fs manager flags definition */
|
||||
#define FS_MANAGER_CHECK 0x00000001
|
||||
#define FS_MANAGER_WAIT 0x00000002
|
||||
#define FS_MANAGER_REQUIRED 0x00000004
|
||||
|
||||
#define VALID_FS_MANAGER_FLAGS (FS_MANAGER_CHECK | FS_MANAGER_WAIT | FS_MANAGER_REQUIRED)
|
||||
#define FS_MANAGER_FLAGS_ENABLED(fsMgrFlags, flag) (((fsMgrFlags) & FS_MANAGER_##flag) != 0)
|
||||
|
||||
#define FM_MANAGER_CHECK_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), CHECK)
|
||||
#define FM_MANAGER_WAIT_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), WAIT)
|
||||
#define FM_MANAGER_REQUIRED_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), REQUIRED)
|
||||
|
||||
typedef enum MountStatus {
|
||||
MOUNT_ERROR = -1,
|
||||
MOUNT_UMOUNTED = 0,
|
||||
MOUNT_MOUNTED = 1,
|
||||
} MountStatus;
|
||||
|
||||
typedef struct FstabItem {
|
||||
char *deviceName; // Block device name
|
||||
char *mountPoint; // Mount point
|
||||
char *fsType; // File system type
|
||||
char * mountOptions; // File system mount options. readonly, rw, remount etc.
|
||||
unsigned int fsManagerFlags; // flags defined by fs manager.
|
||||
struct FstabItem *next;
|
||||
} FstabItem;
|
||||
|
||||
typedef struct {
|
||||
struct FstabItem *head;
|
||||
} Fstab;
|
||||
|
||||
void ReleaseFstab(Fstab *fstab);
|
||||
Fstab *ReadFstabFromFile(const char *file, bool procMounts);
|
||||
FstabItem *FindFstabItemForPath(Fstab fstab, const char *path);
|
||||
FstabItem* FindFstabItemForMountPoint(Fstab fstab, const char *mp);
|
||||
|
||||
bool IsSupportedFilesystem(const char *fsType);
|
||||
int DoFormat(const char *devPath, const char *fsType);
|
||||
int MountOneItem(FstabItem *item);
|
||||
MountStatus GetMountStatusForMountPoint(const char *mp);
|
||||
int MountAllWithFstabFile(const char *file, bool required);
|
||||
int UmountAllWithFstabFile(const char *file);
|
||||
unsigned long GetMountFlags(char *mountFlags, char *fsSpecificFlags, size_t fsSpecificFlagSize);
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // STARTUP_FS_MANAGER_H
|
||||
Regular → Executable
Regular → Executable
+2
-1
@@ -17,6 +17,7 @@
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "init_log.h"
|
||||
#include "param.h"
|
||||
#include "securec.h"
|
||||
@@ -45,7 +46,7 @@ int DoReboot(const char *option)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
size_t length = strlen(option);
|
||||
int length = strlen(option);
|
||||
if (length > MAX_REBOOT_OPTION_SIZE) {
|
||||
INIT_LOGE("Reboot option \" %s \" is too large, overflow", option);
|
||||
return -1;
|
||||
|
||||
Regular → Executable
@@ -14,7 +14,6 @@
|
||||
*/
|
||||
|
||||
#include "init_socket.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
Regular → Executable
+5
-1
@@ -5,7 +5,11 @@
|
||||
"module_list": [
|
||||
"//base/startup/init_lite/services:startup_init",
|
||||
"//base/startup/init_lite/ueventd:ueventd",
|
||||
"//base/startup/init_lite/ueventd:ueventd.config"
|
||||
"//base/startup/init_lite/ueventd:ueventd.config",
|
||||
"//base/startup/init_lite/watchdog:watchdog"
|
||||
],
|
||||
"test_list": [
|
||||
"//base/startup/init_lite/services/test/unittest:init_test"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Regular → Executable
+41
-31
@@ -10,6 +10,20 @@
|
||||
# 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.
|
||||
|
||||
init_common_sources = [
|
||||
"init/init_capability.c",
|
||||
"init/init_common_cmds.c",
|
||||
"init/init_config.c",
|
||||
"init/init_common_service.c",
|
||||
"init/init_service_manager.c",
|
||||
"init/init_service_socket.c",
|
||||
"init/main.c",
|
||||
"log/init_log.c",
|
||||
"utils/init_utils.c",
|
||||
"utils/list.c",
|
||||
]
|
||||
|
||||
if (defined(ohos_lite)) {
|
||||
# feature: init
|
||||
executable("init_lite") {
|
||||
@@ -19,27 +33,21 @@ if (defined(ohos_lite)) {
|
||||
"OHOS_LITE",
|
||||
]
|
||||
sources = [
|
||||
"log/init_log.c",
|
||||
"src/init_adapter.c",
|
||||
"src/init_capability.c",
|
||||
"src/init_cmds.c",
|
||||
"src/init_import.c",
|
||||
"src/init_jobs.c",
|
||||
"src/init_read_cfg.c",
|
||||
"src/init_reboot.c",
|
||||
"src/init_service.c",
|
||||
"src/init_service_manager.c",
|
||||
"src/init_service_socket.c",
|
||||
"src/init_signal_handler.c",
|
||||
"src/main.c",
|
||||
"utils/init_utils.c",
|
||||
"init/adapter/init_adapter.c",
|
||||
"init/lite/init.c",
|
||||
"init/lite/init_cmds.c",
|
||||
"init/lite/init_jobs.c",
|
||||
"init/lite/init_reboot.c",
|
||||
"init/lite/init_service.c",
|
||||
"init/lite/init_signal_handler.c",
|
||||
]
|
||||
|
||||
sources += init_common_sources
|
||||
|
||||
include_dirs = [
|
||||
"//base/startup/init_lite/services/include",
|
||||
"//base/startup/init_lite/services/param/include",
|
||||
"//base/startup/init_lite/services/init/include",
|
||||
"//base/startup/init_lite/services/log",
|
||||
"//base/startup/init_lite/services/utils",
|
||||
"//third_party/cJSON",
|
||||
"//third_party/bounds_checking_function/include",
|
||||
"//base/startup/syspara_lite/interfaces/kits",
|
||||
@@ -88,33 +96,34 @@ if (defined(ohos_lite)) {
|
||||
|
||||
ohos_executable("init") {
|
||||
sources = [
|
||||
"src/device.c",
|
||||
"src/init_adapter.c",
|
||||
"src/init_capability.c",
|
||||
"src/init_cmds.c",
|
||||
"src/init_import.c",
|
||||
"src/init_jobs.c",
|
||||
"src/init_read_cfg.c",
|
||||
"src/init_reboot.c",
|
||||
"src/init_service.c",
|
||||
"src/init_service_manager.c",
|
||||
"src/init_service_socket.c",
|
||||
"src/init_signal_handler.c",
|
||||
"src/main.c",
|
||||
"init/adapter/init_adapter.c",
|
||||
"init/standard/device.c",
|
||||
"init/standard/init.c",
|
||||
"init/standard/init_cmds.c",
|
||||
"init/standard/init_jobs.c",
|
||||
"init/standard/init_reboot.c",
|
||||
"init/standard/init_service.c",
|
||||
"init/standard/init_signal_handler.c",
|
||||
"init/standard/switch_root.c",
|
||||
"init/standard/init_mount.c",
|
||||
]
|
||||
|
||||
sources += init_common_sources
|
||||
|
||||
include_dirs = [
|
||||
"//base/startup/init_lite/services/include/param",
|
||||
"//base/startup/init_lite/services/include",
|
||||
"//base/startup/init_lite/services/init/include",
|
||||
"//base/startup/init_lite/services/log",
|
||||
"//base/startup/init_lite/services/utils",
|
||||
"//base/startup/init_lite/interfaces/innerkits/include",
|
||||
"//third_party/cJSON",
|
||||
"//third_party/bounds_checking_function/include",
|
||||
"//third_party/libuv/include",
|
||||
]
|
||||
deps = [
|
||||
"//base/startup/init_lite/interfaces/innerkits/fs_manager:libfsmanager_static",
|
||||
"//base/startup/init_lite/services/log:init_log",
|
||||
"//base/startup/init_lite/services/param:param_service",
|
||||
"//base/startup/init_lite/services/utils:libinit_utils",
|
||||
"//third_party/bounds_checking_function:libsec_static",
|
||||
"//third_party/cJSON:cjson_static",
|
||||
]
|
||||
@@ -138,6 +147,7 @@ if (defined(ohos_lite)) {
|
||||
":init_etc",
|
||||
"//base/startup/init_lite/interfaces/innerkits/dynamic_service:dynamic_service",
|
||||
"//base/startup/init_lite/interfaces/innerkits/socket:libsocket",
|
||||
"//base/startup/init_lite/interfaces/innerkits/fs_manager:libfsmanager_shared",
|
||||
"//base/startup/init_lite/services/cmds/reboot:reboot",
|
||||
"//base/startup/init_lite/services/cmds/service_control:service_control",
|
||||
"//base/startup/init_lite/services/param:param",
|
||||
|
||||
Regular → Executable
+2
-4
@@ -32,9 +32,7 @@ int main(int argc, char* argv[])
|
||||
printf("%s", USAGE_INFO);
|
||||
return 0;
|
||||
}
|
||||
if (argv[1] == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc == REBOOT_CMD_NUMBER && strcmp(argv[1], "shutdown") != 0 &&
|
||||
strcmp(argv[1], "updater") != 0 &&
|
||||
strcmp(argv[1], "flash") != 0 &&
|
||||
@@ -43,7 +41,7 @@ int main(int argc, char* argv[])
|
||||
printf("%s", USAGE_INFO);
|
||||
return 0;
|
||||
}
|
||||
int ret;
|
||||
int ret = 0;
|
||||
if (argc == REBOOT_CMD_NUMBER) {
|
||||
ret = DoReboot(argv[1]);
|
||||
} else {
|
||||
|
||||
@@ -67,9 +67,7 @@ int main(int argc, char** argv)
|
||||
ServiceControlUsage();
|
||||
return -1;
|
||||
}
|
||||
if (argv[0] == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char serviceCtl[SERVICE_CONTROL_MAX_SIZE];
|
||||
if (strcmp(argv[0], "start_service") == 0) {
|
||||
if (strncpy_s(serviceCtl, sizeof(serviceCtl), "ohos.ctl.start", sizeof(serviceCtl) - 1) != EOK) {
|
||||
|
||||
+12
-7
@@ -3,8 +3,7 @@
|
||||
"/etc/init.usb.cfg",
|
||||
"/etc/init.usb.configfs.cfg",
|
||||
"/etc/init.usb.cfg",
|
||||
"/etc/init.Hi3516DV300.usb.cfg",
|
||||
"/etc/init.Hi3516DV300.cfg"
|
||||
"/vendor/etc/init.${ohos.boot.hardware}.cfg"
|
||||
],
|
||||
"jobs" : [{
|
||||
"name" : "pre-init",
|
||||
@@ -16,10 +15,9 @@
|
||||
"mkdir /dev/memcg/apps/ 0755 system system",
|
||||
"mkdir /dev/memcg/system 0550 system system",
|
||||
"start ueventd",
|
||||
"mkdir /vendor",
|
||||
"start watchdog_service",
|
||||
"mkdir /data",
|
||||
"mount ext4 /dev/block/platform/soc/10100000.himci.eMMC/by-name/vendor /vendor wait rdonly barrier=1",
|
||||
"mount ext4 /dev/block/platform/soc/10100000.himci.eMMC/by-name/userdata /data wait nosuid nodev noatime barrier=1,data=ordered,noauto_da_alloc"
|
||||
"mount_fstab /vendor/etc/fstab.${ohos.boot.hardware}"
|
||||
]
|
||||
}, {
|
||||
"name" : "init",
|
||||
@@ -386,8 +384,8 @@
|
||||
"write /proc/sys/kernel/perf_event_paranoid 3"
|
||||
]
|
||||
}, {
|
||||
"name" : "boot && param:ro.debuggable=1",
|
||||
"condition" : "boot && ro.debuggable=1",
|
||||
"name" : "boot && param:const.debuggable=1",
|
||||
"condition" : "boot && const.debuggable=1",
|
||||
"cmds" : [
|
||||
"chmod 0773 /data/misc/trace",
|
||||
"chmod 0775 /data/misc/wmtrace",
|
||||
@@ -406,6 +404,13 @@
|
||||
"console" : 1,
|
||||
"uid" : "root",
|
||||
"gid" : ["shell", "log", "readproc"]
|
||||
}, {
|
||||
"name" : "watchdog_service",
|
||||
"path" : ["/system/bin/watchdog_service", "10", "2"],
|
||||
"disabled" : 1,
|
||||
"uid" : "root",
|
||||
"gid" : ["shell", "log", "readproc"]
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
{
|
||||
"import" : [
|
||||
"/vendor/etc/init.${ohos.boot.hardware}.usb.cfg"
|
||||
],
|
||||
"jobs" : [{
|
||||
"name" : "boot",
|
||||
"cmds" : [
|
||||
|
||||
@@ -27,13 +27,13 @@ hw_sc.build.os.version=2.2.0
|
||||
# ohos release type
|
||||
hw_sc.build.os.releasetype=Canary1
|
||||
|
||||
ro.actionable_compatible_property.enabled=false
|
||||
ro.postinstall.fstab.prefix=/system
|
||||
ro.secure=1
|
||||
const.actionable_compatible_property.enabled=false
|
||||
const.postinstall.fstab.prefix=/system
|
||||
const.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"
|
||||
const.allow.mock.location=0
|
||||
const.debuggable=1
|
||||
const.build.characteristics="default"
|
||||
const.product.model="ohos"
|
||||
const.product.name="OpenHarmony 2.0 Canary"
|
||||
persist.sys.usb.config=hdc
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* 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_INITLITE_CMDS_H
|
||||
#define BASE_STARTUP_INITLITE_CMDS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MAX_CMD_NAME_LEN 32
|
||||
#define MAX_CMD_CONTENT_LEN 256
|
||||
#define MAX_CMD_CNT_IN_ONE_JOB 200
|
||||
#define MAX_COPY_BUF_SIZE 256
|
||||
#define DEFAULT_COPY_ARGS_CNT 2
|
||||
|
||||
#ifndef OHOS_LITE
|
||||
// Limit max length of parameter value to 96
|
||||
#define MAX_PARAM_VALUE_LEN 96
|
||||
// Limit max length of parameter name to 96
|
||||
#define MAX_PARAM_NAME_LEN 96
|
||||
#else
|
||||
// For lite ohos, do not support parameter operation
|
||||
#define MAX_PARAM_VALUE_LEN 0
|
||||
#define MAX_PARAM_NAME_LEN 0
|
||||
#endif
|
||||
|
||||
// one cmd line
|
||||
typedef struct {
|
||||
char name[MAX_CMD_NAME_LEN + 1];
|
||||
char cmdContent[MAX_CMD_CONTENT_LEN + 1];
|
||||
} CmdLine;
|
||||
|
||||
struct CmdArgs {
|
||||
int argc;
|
||||
char **argv;
|
||||
};
|
||||
|
||||
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 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, unsigned int *index);
|
||||
const char *GetCmdKey(unsigned int index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // BASE_STARTUP_INITLITE_CMDS_H
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* 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_INITLITE_SERVICE_H
|
||||
#define BASE_STARTUP_INITLITE_SERVICE_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "init_cmds.h"
|
||||
#include "init_service_socket.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// return value
|
||||
#define SERVICE_FAILURE (-1)
|
||||
#define SERVICE_SUCCESS 0
|
||||
|
||||
// service attributes
|
||||
#define SERVICE_ATTR_INVALID 0x001 // option invalid
|
||||
#define SERVICE_ATTR_ONCE 0x002 // do not restart when it exits
|
||||
#define SERVICE_ATTR_NEED_RESTART 0x004 // will restart in the near future
|
||||
#define SERVICE_ATTR_NEED_STOP 0x008 // will stop in reap
|
||||
#define SERVICE_ATTR_IMPORTANT 0x010 // will reboot if it crash
|
||||
#define SERVICE_ATTR_CRITICAL 0x020 // critical, will reboot if it crash 4 times in 4 minutes
|
||||
#define SERVICE_ATTR_DISABLED 0x040 // disabled
|
||||
#define SERVICE_ATTR_CONSOLE 0x080 // console
|
||||
#define SERVICE_ATTR_DYNAMIC 0x100 // dynamic service
|
||||
|
||||
#define MAX_SERVICE_NAME 32
|
||||
#define MAX_WRITEPID_FILES 100
|
||||
|
||||
#define CAP_NUM 2
|
||||
|
||||
#define SERVICES_ARR_NAME_IN_JSON "services"
|
||||
|
||||
typedef struct {
|
||||
uid_t uID;
|
||||
gid_t *gIDArray;
|
||||
int gIDCnt;
|
||||
unsigned int *caps;
|
||||
unsigned int capsCnt;
|
||||
} Perms;
|
||||
|
||||
struct OnRestartCmd {
|
||||
CmdLine *cmdLine;
|
||||
int cmdNum;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char name[MAX_SERVICE_NAME + 1];
|
||||
char** pathArgs;
|
||||
int pathArgsCnt;
|
||||
int pid;
|
||||
int crashCnt;
|
||||
time_t firstCrashTime;
|
||||
char *writepidFiles[MAX_WRITEPID_FILES];
|
||||
unsigned int attribute;
|
||||
int importance;
|
||||
Perms servPerm;
|
||||
struct OnRestartCmd *onRestart;
|
||||
struct ServiceSocket *socketCfg;
|
||||
} Service;
|
||||
|
||||
int ServiceStart(Service *service);
|
||||
int ServiceStop(Service *service);
|
||||
void ServiceReap(Service *service);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // BASE_STARTUP_INITLITE_SERVICE_H
|
||||
@@ -28,18 +28,23 @@ extern "C" {
|
||||
#define BINARY_BASE 2
|
||||
#define OCTAL_BASE 8
|
||||
#define DECIMAL_BASE 10
|
||||
#define WAIT_MAX_COUNT 10
|
||||
|
||||
#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);
|
||||
int SplitString(char *srcPtr, const char *del, char **dstPtr, int maxNum);
|
||||
void WaitForFile(const char *source, unsigned int maxCount);
|
||||
size_t WriteAll(int fd, const char *buffer, size_t size);
|
||||
char *Realpath(const char *source, char *resolvedPath, size_t resolvedPathSize);
|
||||
char *GetRealPath(const char *source);
|
||||
int StringToInt(const char *str, int defaultValue);
|
||||
int MakeDirRecursive(const char *dir, mode_t mode);
|
||||
int MakeDir(const char *dir, mode_t mode);
|
||||
|
||||
int ReadFileInDir(const char *dirPath, const char *includeExt,
|
||||
int (*processFile)(const char *fileName, void *context), void *context);
|
||||
char **SplitStringExt(char *buffer, const char *del, int *returnCount, int maxItemCount);
|
||||
void FreeStringVector(char **vector, int count);
|
||||
int InUpdaterMode(void);
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
Regular → Executable
+2
-2
@@ -97,10 +97,10 @@ void DoTriggerExec(const char *triggerName);
|
||||
|
||||
/**
|
||||
* 对Init接口
|
||||
* 按名字执行对应的trigger。
|
||||
* dump 参数和trigger信息
|
||||
*
|
||||
*/
|
||||
int SystemTraversalParam(void (*traversalParameter)(ParamHandle handle, void* cookie), void* cookie);
|
||||
void DumpParametersAndTriggers(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
|
||||
Regular → Executable
Regular → Executable
+4
-10
@@ -13,13 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef INIT_CAPABILITY_H
|
||||
#define INIT_CAPABILITY_H
|
||||
|
||||
#include "cJSON.h"
|
||||
#include "init_service.h"
|
||||
|
||||
int GetServiceCaps(const cJSON* curArrItem, Service* curServ);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef INIT_SWITCH_ROOT_H
|
||||
#define INIT_SWITCH_ROOT_H
|
||||
int SwitchRoot(const char *newRoot);
|
||||
#endif // INIT_SWITCH_ROOT_H
|
||||
Regular → Executable
+38
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2020-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
|
||||
@@ -12,23 +12,26 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init_adapter.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <semaphore.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <unistd.h>
|
||||
#if defined OHOS_LITE && !defined __LINUX__
|
||||
#include <sys/capability.h>
|
||||
#else
|
||||
#include <linux/capability.h>
|
||||
#endif
|
||||
|
||||
#if ((defined __LINUX__) || (!defined OHOS_LITE))
|
||||
#include <linux/securebits.h>
|
||||
#endif
|
||||
#ifdef __LINUX__
|
||||
#include "init_signal_handler.h"
|
||||
#endif
|
||||
#include "init_log.h"
|
||||
|
||||
void RebootSystem()
|
||||
void RebootSystem(void)
|
||||
{
|
||||
int ret = reboot(RB_AUTOBOOT);
|
||||
if (ret != 0) {
|
||||
@@ -36,7 +39,7 @@ void RebootSystem()
|
||||
}
|
||||
}
|
||||
|
||||
int KeepCapability()
|
||||
int KeepCapability(void)
|
||||
{
|
||||
#if ((defined __LINUX__) || (!defined OHOS_LITE))
|
||||
if (prctl(PR_SET_SECUREBITS, SECBIT_NO_SETUID_FIXUP | SECBIT_NO_SETUID_FIXUP_LOCKED)) {
|
||||
@@ -58,7 +61,33 @@ int SetAmbientCapability(int cap)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ExecuteRcs()
|
||||
#ifdef __LINUX__
|
||||
static pid_t g_waitPid = -1;
|
||||
static sem_t *g_waitSem = NULL;
|
||||
static void SignalRegWaitSem(pid_t waitPid, sem_t *waitSem)
|
||||
{
|
||||
g_waitPid = waitPid;
|
||||
g_waitSem = waitSem;
|
||||
}
|
||||
|
||||
void CheckWaitPid(pid_t sigPID)
|
||||
{
|
||||
if (g_waitPid == sigPID && g_waitSem != NULL) {
|
||||
if (sem_post(g_waitSem) != 0) {
|
||||
INIT_LOGE("CheckWaitPid, sem_post failed, errno %d.", errno);
|
||||
}
|
||||
g_waitPid = -1;
|
||||
g_waitSem = NULL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
void CheckWaitPid(pid_t sigPID)
|
||||
{
|
||||
(void)(sigPID);
|
||||
}
|
||||
#endif
|
||||
|
||||
void SystemExecuteRcs(void)
|
||||
{
|
||||
#if (defined __LINUX__) && (defined NEED_EXEC_RCS_LINUX)
|
||||
pid_t retPid = fork();
|
||||
@@ -90,4 +119,3 @@ void ExecuteRcs()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Regular → Executable
+1
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2020-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
|
||||
@@ -12,10 +12,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BASE_STARTUP_INITLITE_DEVICE_H
|
||||
#define BASE_STARTUP_INITLITE_DEVICE_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
Regular → Executable
+24
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2020-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
|
||||
@@ -12,14 +12,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BASE_STARTUP_INITLITE_SIGNAL_HANDLE_H
|
||||
#define BASE_STARTUP_INITLITE_SIGNAL_HANDLE_H
|
||||
|
||||
#ifdef __LINUX__
|
||||
#include <semaphore.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifndef BASE_STARTUP_INIT_H
|
||||
#define BASE_STARTUP_INIT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
@@ -27,16 +21,31 @@ extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void SignalInitModule();
|
||||
|
||||
#ifdef __LINUX__
|
||||
void SignalRegWaitSem(pid_t waitPid, sem_t* waitSem);
|
||||
#ifndef PARAM_VALUE_LEN_MAX
|
||||
#define PARAM_VALUE_LEN_MAX 96
|
||||
#endif
|
||||
|
||||
#define PROCESS_EXIT_CODE 0x7f // 0x7f: user specified
|
||||
// kit framework
|
||||
#define DEFAULT_UID_KIT_FRAMEWORK 3
|
||||
// max length of one param/path
|
||||
#define MAX_ONE_ARG_LEN 200
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
void SystemInit(void);
|
||||
void LogInit(void);
|
||||
void SystemPrepare(void);
|
||||
void SystemConfig(void);
|
||||
void SystemRun(void);
|
||||
void SystemExecuteRcs(void);
|
||||
|
||||
void ReadConfig(void);
|
||||
void SignalInit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // BASE_STARTUP_INITLITE_SIGNAL_HANDLE_H
|
||||
#endif // BASE_STARTUP_INIT_H
|
||||
Regular → Executable
+12
-19
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2020-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
|
||||
@@ -12,16 +12,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BASE_STARTUP_INITLITE_ADAPTER_H
|
||||
#define BASE_STARTUP_INITLITE_ADAPTER_H
|
||||
|
||||
#if defined OHOS_LITE && !defined __LINUX__
|
||||
#include <sys/capability.h>
|
||||
#else
|
||||
#include <linux/capability.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
@@ -31,27 +24,27 @@ extern "C" {
|
||||
#ifndef OHOS_LITE
|
||||
/* Control the ambient capability set */
|
||||
#ifndef PR_CAP_AMBIENT
|
||||
#define PR_CAP_AMBIENT 47
|
||||
#define PR_CAP_AMBIENT 47
|
||||
#endif
|
||||
#ifndef PR_CAP_AMBIENT_IS_SET
|
||||
#define PR_CAP_AMBIENT_IS_SET 1
|
||||
#define PR_CAP_AMBIENT_IS_SET 1
|
||||
#endif
|
||||
#ifndef PR_CAP_AMBIENT_RAISE
|
||||
#define PR_CAP_AMBIENT_RAISE 2
|
||||
#define PR_CAP_AMBIENT_RAISE 2
|
||||
#endif
|
||||
#ifndef PR_CAP_AMBIENT_LOWER
|
||||
#define PR_CAP_AMBIENT_LOWER 3
|
||||
#define PR_CAP_AMBIENT_LOWER 3
|
||||
#endif
|
||||
#ifndef PR_CAP_AMBIENT_CLEAR_ALL
|
||||
#define PR_CAP_AMBIENT_CLEAR_ALL 4
|
||||
#define PR_CAP_AMBIENT_CLEAR_ALL 4
|
||||
#endif
|
||||
extern int capset(void *a, void *b);
|
||||
#endif
|
||||
|
||||
void RebootSystem();
|
||||
int KeepCapability();
|
||||
void RebootSystem(void);
|
||||
int KeepCapability(void);
|
||||
int SetAmbientCapability(int cap);
|
||||
void ExecuteRcs();
|
||||
void ExecuteRcs(void);
|
||||
void CheckWaitPid(pid_t sigPID);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
@@ -59,4 +52,4 @@ void ExecuteRcs();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // BASE_STARTUP_INITLITE_ADAPTER_H
|
||||
#endif // BASE_STARTUP_INITLITE_ADAPTER_H
|
||||
Executable
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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_INIT_CMDS_H
|
||||
#define BASE_STARTUP_INIT_CMDS_H
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include "cJSON.h"
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DEFAULT_DIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH) // mkdir, default mode
|
||||
#define SPACES_CNT_IN_CMD_MAX 10 // mount, max number of spaces in cmdline
|
||||
#define SPACES_CNT_IN_CMD_MIN 2 // mount, min number of spaces in cmdline
|
||||
|
||||
#define LOADCFG_BUF_SIZE 128 // loadcfg, max buffer for one cmdline
|
||||
#define LOADCFG_MAX_FILE_LEN 51200 // loadcfg, max file size is 50K
|
||||
#define LOADCFG_MAX_LOOP 20 // loadcfg, to prevent to be trapped in infite loop
|
||||
#define OCTAL_TYPE 8 // 8 means octal to decimal
|
||||
#define MAX_BUFFER 256UL
|
||||
#define AUTHORITY_MAX_SIZE 128
|
||||
|
||||
#define MAX_CMD_NAME_LEN 32
|
||||
#define MAX_CMD_CONTENT_LEN 256
|
||||
#define MAX_CMD_CNT_IN_ONE_JOB 200
|
||||
#define MAX_COPY_BUF_SIZE 256
|
||||
#define DEFAULT_COPY_ARGS_CNT 2
|
||||
|
||||
#define OPTIONS_SIZE 128
|
||||
|
||||
#define SUPPORT_MAX_ARG_FOR_EXEC 10
|
||||
// one cmd line
|
||||
typedef struct {
|
||||
int cmdIndex;
|
||||
char cmdContent[MAX_CMD_CONTENT_LEN + 1];
|
||||
} CmdLine;
|
||||
|
||||
typedef struct {
|
||||
int cmdNum;
|
||||
CmdLine cmds[0];
|
||||
} CmdLines;
|
||||
|
||||
struct CmdArgs {
|
||||
int argc;
|
||||
char *argv[0];
|
||||
};
|
||||
|
||||
struct CmdTable {
|
||||
char name[MAX_CMD_NAME_LEN];
|
||||
unsigned char minArg;
|
||||
unsigned char maxArg;
|
||||
void (*DoFuncion)(const struct CmdArgs *ctx, const char *cmdContent);
|
||||
};
|
||||
|
||||
int GetParamValue(const char *symValue, unsigned int symLen, char *paramValue, unsigned int paramLen);
|
||||
const struct CmdArgs *GetCmdArg(const char *cmdContent, const char *delim, int argsCount);
|
||||
void FreeCmdArg(struct CmdArgs *cmd);
|
||||
void DoCmdByName(const char *name, const char *cmdContent);
|
||||
void DoCmdByIndex(int index, const char *cmdContent);
|
||||
const char *GetMatchCmd(const char *cmdStr, int *index);
|
||||
const char *GetCmdKey(int index);
|
||||
const struct CmdTable *GetCmdTable(int *number);
|
||||
int GetCmdLinesFromJson(const cJSON *root, CmdLines **cmdLines);
|
||||
const struct CmdTable *GetCmdByName(const char *name);
|
||||
void ExecReboot(const char *value);
|
||||
char *BuildStringFromCmdArg(const struct CmdArgs *ctx, int startIndex);
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // BASE_STARTUP_INITLITE_CMDS_H
|
||||
Regular → Executable
+12
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2020-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
|
||||
@@ -12,12 +12,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BASE_STARTUP_INITLITE_JOBS_H
|
||||
#define BASE_STARTUP_INITLITE_JOBS_H
|
||||
|
||||
#include "init_cmds.h"
|
||||
#include "cJSON.h"
|
||||
#include "init_cmds.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
@@ -30,14 +28,20 @@ extern "C" {
|
||||
// one job, could have many cmd lines
|
||||
typedef struct {
|
||||
char name[MAX_JOB_NAME_LEN + 1];
|
||||
int cmdLinesCnt;
|
||||
CmdLine* cmdLines;
|
||||
CmdLines *cmdLines;
|
||||
} Job;
|
||||
|
||||
void ParseAllJobs(const cJSON* fileRoot);
|
||||
void DoJob(const char* jobName);
|
||||
void ParseAllJobs(const cJSON *fileRoot);
|
||||
void DoJob(const char *jobName);
|
||||
void ReleaseAllJobs(void);
|
||||
void DumpAllJobs(void);
|
||||
|
||||
#define INIT_CONFIGURATION_FILE "/etc/init.cfg"
|
||||
#define OTHER_CFG_PATH "/system/etc/init"
|
||||
#define MAX_PATH_ARGS_CNT 20
|
||||
|
||||
void ReadConfig(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
Executable
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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_SERVICE_H
|
||||
#define BASE_STARTUP_INITLITE_SERVICE_H
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "cJSON.h"
|
||||
#include "init_cmds.h"
|
||||
#include "init_service_socket.h"
|
||||
#include "list.h"
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// return value
|
||||
#define SERVICE_FAILURE (-1)
|
||||
#define SERVICE_SUCCESS 0
|
||||
|
||||
// service attributes
|
||||
#define SERVICE_ATTR_INVALID 0x001 // option invalid
|
||||
#define SERVICE_ATTR_ONCE 0x002 // do not restart when it exits
|
||||
#define SERVICE_ATTR_NEED_RESTART 0x004 // will restart in the near future
|
||||
#define SERVICE_ATTR_NEED_STOP 0x008 // will stop in reap
|
||||
#define SERVICE_ATTR_IMPORTANT 0x010 // will reboot if it crash
|
||||
#define SERVICE_ATTR_CRITICAL 0x020 // critical, will reboot if it crash 4 times in 4 minutes
|
||||
#define SERVICE_ATTR_DISABLED 0x040 // disabled
|
||||
#define SERVICE_ATTR_CONSOLE 0x080 // console
|
||||
#define SERVICE_ATTR_DYNAMIC 0x100 // dynamic service
|
||||
|
||||
#define MAX_SERVICE_NAME 32
|
||||
#define MAX_WRITEPID_FILES 100
|
||||
|
||||
#define FULL_CAP 0xFFFFFFFF
|
||||
// init
|
||||
#define DEFAULT_UMASK_INIT 022
|
||||
|
||||
#define CAP_NUM 2
|
||||
|
||||
#define SERVICES_ARR_NAME_IN_JSON "services"
|
||||
|
||||
typedef struct {
|
||||
uid_t uID;
|
||||
gid_t *gIDArray;
|
||||
int gIDCnt;
|
||||
unsigned int *caps;
|
||||
unsigned int capsCnt;
|
||||
} Perms;
|
||||
|
||||
typedef struct {
|
||||
int count;
|
||||
char **argv;
|
||||
} ServiceArgs;
|
||||
|
||||
typedef struct {
|
||||
ListNode node;
|
||||
char name[MAX_SERVICE_NAME + 1];
|
||||
int pid;
|
||||
int crashCnt;
|
||||
time_t firstCrashTime;
|
||||
unsigned int attribute;
|
||||
int importance;
|
||||
Perms servPerm;
|
||||
ServiceArgs pathArgs;
|
||||
ServiceArgs writePidArgs;
|
||||
CmdLines *restartArg;
|
||||
ServiceSocket *socketCfg;
|
||||
} Service;
|
||||
|
||||
int ServiceStart(Service *service);
|
||||
int ServiceStop(Service *service);
|
||||
void ServiceReap(Service *service);
|
||||
void ReapService(Service *service);
|
||||
|
||||
void NotifyServiceChange(const char *serviceName, const char *change);
|
||||
int IsForbidden(const char *fieldStr);
|
||||
int SetImportantValue(Service *curServ, const char *attrName, int value, int flag);
|
||||
int GetServiceCaps(const cJSON *curArrItem, Service *curServ);
|
||||
int ServiceExec(const Service *service);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // BASE_STARTUP_INITLITE_SERVICE_H
|
||||
Regular → Executable
+26
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2020-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
|
||||
@@ -12,12 +12,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BASE_STARTUP_INITLITE_SERVICEMANAGER_H
|
||||
#define BASE_STARTUP_INITLITE_SERVICEMANAGER_H
|
||||
|
||||
#include "init_service.h"
|
||||
#include "cJSON.h"
|
||||
#include "list.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
@@ -25,26 +25,37 @@ extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define UID_STR_IN_CFG "uid"
|
||||
#define GID_STR_IN_CFG "gid"
|
||||
#define ONCE_STR_IN_CFG "once"
|
||||
#define IMPORTANT_STR_IN_CFG "importance"
|
||||
#define BIN_SH_NOT_ALLOWED "/bin/sh"
|
||||
#define CRITICAL_STR_IN_CFG "critical"
|
||||
#define DISABLED_STR_IN_CFG "disabled"
|
||||
#define CONSOLE_STR_IN_CFG "console"
|
||||
#define UID_STR_IN_CFG "uid"
|
||||
#define GID_STR_IN_CFG "gid"
|
||||
#define ONCE_STR_IN_CFG "once"
|
||||
#define IMPORTANT_STR_IN_CFG "importance"
|
||||
#define BIN_SH_NOT_ALLOWED "/bin/sh"
|
||||
#define CRITICAL_STR_IN_CFG "critical"
|
||||
#define DISABLED_STR_IN_CFG "disabled"
|
||||
#define CONSOLE_STR_IN_CFG "console"
|
||||
|
||||
#define MAX_SERVICES_CNT_IN_FILE 100
|
||||
|
||||
void RegisterServices(Service *services, int servicesCnt);
|
||||
typedef struct {
|
||||
char *capStr;
|
||||
unsigned int CapNum;
|
||||
} CapStrCapNum;
|
||||
|
||||
typedef struct {
|
||||
ListNode services;
|
||||
int serviceCount;
|
||||
} ServiceSpace;
|
||||
|
||||
Service *GetServiceByPid(pid_t pid);
|
||||
Service *GetServiceByName(const char *servName);
|
||||
cJSON *GetArrayItem(const cJSON *fileRoot, int *arrSize, const char *arrName);
|
||||
|
||||
void StartServiceByName(const char *serviceName, bool checkDynamic);
|
||||
void StopServiceByName(const char *serviceName);
|
||||
void StopAllServices(void);
|
||||
void StopAllServicesBeforeReboot(void);
|
||||
void ReapServiceByPID(int pid);
|
||||
void StopAllServices(int flags);
|
||||
void ParseAllServices(const cJSON *fileRoot);
|
||||
#ifdef OHOS_SERVICE_DUMP
|
||||
void DumpAllServices(void);
|
||||
void DumpAllServices();
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
Regular → Executable
+26
-17
@@ -1,10 +1,10 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -12,17 +12,21 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef INIT_SERVICE_SOCKET_
|
||||
#define INIT_SERVICE_SOCKET_
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define MAX_SOCK_NAME_LEN 16
|
||||
#define SOCK_OPT_NUMS 6
|
||||
#define MAX_SOCK_NAME_LEN 16
|
||||
#define SOCK_OPT_NUMS 6
|
||||
enum SockOptionTab {
|
||||
SERVICE_SOCK_NAME = 0,
|
||||
SERVICE_SOCK_TYPE,
|
||||
@@ -32,18 +36,23 @@ enum SockOptionTab {
|
||||
SERVICE_SOCK_SETOPT
|
||||
};
|
||||
|
||||
struct ServiceSocket;
|
||||
struct ServiceSocket {
|
||||
char *name; // service name
|
||||
int type; // socket type
|
||||
uid_t uid; // uid
|
||||
gid_t gid; // gid
|
||||
bool passcred; // setsocketopt
|
||||
mode_t perm; // Setting permissions
|
||||
typedef struct ServiceSocket_ {
|
||||
struct ServiceSocket_ *next;
|
||||
int type; // socket type
|
||||
uid_t uid; // uid
|
||||
gid_t gid; // gid
|
||||
bool passcred; // setsocketopt
|
||||
mode_t perm; // Setting permissions
|
||||
int sockFd;
|
||||
struct ServiceSocket *next;
|
||||
};
|
||||
char name[0]; // service name
|
||||
} ServiceSocket;
|
||||
|
||||
int DoCreateSocket(struct ServiceSocket *sockopt);
|
||||
int CreateServiceSocket(ServiceSocket *sockopt);
|
||||
void CloseServiceSocket(ServiceSocket *sockopt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
Executable
+130
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if defined OHOS_LITE && !defined __LINUX__
|
||||
#include <sys/capability.h>
|
||||
#else
|
||||
#include <linux/capability.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "init_log.h"
|
||||
#include "init_service.h"
|
||||
#include "init_service_manager.h"
|
||||
#include "init_utils.h"
|
||||
|
||||
#define MAX_CAPS_CNT_FOR_ONE_SERVICE 100
|
||||
|
||||
static unsigned int GetCapByString(const char *capStr)
|
||||
{
|
||||
static const CapStrCapNum capStrCapNum[] = {
|
||||
{ "CHOWN", CAP_CHOWN },
|
||||
{ "DAC_OVERRIDE", CAP_DAC_OVERRIDE },
|
||||
{ "DAC_READ_SEARCH", CAP_DAC_READ_SEARCH },
|
||||
{ "FOWNER", CAP_FOWNER },
|
||||
{ "FSETID", CAP_FSETID },
|
||||
{ "KILL", CAP_KILL },
|
||||
{ "SETGID", CAP_SETGID },
|
||||
{ "SETUID", CAP_SETUID },
|
||||
{ "SETPCAP", CAP_SETPCAP },
|
||||
{ "LINUX_IMMUTABLE", CAP_LINUX_IMMUTABLE },
|
||||
{ "NET_BIND_SERVICE", CAP_NET_BIND_SERVICE },
|
||||
{ "NET_BROADCAST", CAP_NET_BROADCAST },
|
||||
{ "NET_ADMIN", CAP_NET_ADMIN },
|
||||
{ "NET_RAW", CAP_NET_RAW },
|
||||
{ "IPC_LOCK", CAP_IPC_LOCK },
|
||||
{ "IPC_OWNER", CAP_IPC_OWNER },
|
||||
{ "SYS_MODULE", CAP_SYS_MODULE },
|
||||
{ "SYS_RAWIO", CAP_SYS_RAWIO },
|
||||
{ "SYS_CHROOT", CAP_SYS_CHROOT },
|
||||
{ "SYS_PTRACE", CAP_SYS_PTRACE },
|
||||
{ "SYS_PACCT", CAP_SYS_PACCT },
|
||||
{ "SYS_ADMIN", CAP_SYS_ADMIN },
|
||||
{ "SYS_BOOT", CAP_SYS_BOOT },
|
||||
{ "SYS_NICE", CAP_SYS_NICE },
|
||||
{ "SYS_RESOURCE", CAP_SYS_RESOURCE },
|
||||
{ "SYS_TIME", CAP_SYS_TIME },
|
||||
{ "SYS_TTY_CONFIG", CAP_SYS_TTY_CONFIG },
|
||||
{ "MKNOD", CAP_MKNOD },
|
||||
{ "LEASE", CAP_LEASE },
|
||||
{ "AUDIT_WRITE", CAP_AUDIT_WRITE },
|
||||
{ "AUDIT_CONTROL", CAP_AUDIT_CONTROL },
|
||||
{ "SETFCAP", CAP_SETFCAP },
|
||||
{ "MAC_OVERRIDE", CAP_MAC_OVERRIDE },
|
||||
{ "MAC_ADMIN", CAP_MAC_ADMIN },
|
||||
{ "SYSLOG", CAP_SYSLOG },
|
||||
{ "WAKE_ALARM", CAP_WAKE_ALARM },
|
||||
{ "BLOCK_SUSPEND", CAP_BLOCK_SUSPEND },
|
||||
{ "AUDIT_READ", CAP_AUDIT_READ },
|
||||
};
|
||||
int mapSize = (int)ARRAY_LENGTH(capStrCapNum);
|
||||
for (int j = 0; j < mapSize; j++) {
|
||||
if (strcmp(capStr, capStrCapNum[j].capStr) == 0) {
|
||||
return capStrCapNum[j].CapNum;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int GetServiceCaps(const cJSON *curArrItem, Service *service)
|
||||
{
|
||||
INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "service is null ptr.");
|
||||
INIT_ERROR_CHECK(curArrItem != NULL, return SERVICE_FAILURE, "json is null ptr.");
|
||||
service->servPerm.capsCnt = 0;
|
||||
service->servPerm.caps = NULL;
|
||||
int capsCnt = 0;
|
||||
cJSON *filedJ = GetArrayItem(curArrItem, &capsCnt, "caps");
|
||||
if (filedJ == NULL) {
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
if (capsCnt > MAX_CAPS_CNT_FOR_ONE_SERVICE) {
|
||||
INIT_LOGE("service=%s, too many caps[cnt %d] for one service", service->name, capsCnt);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
service->servPerm.caps = (unsigned int *)calloc(1, sizeof(unsigned int) * capsCnt);
|
||||
if (service->servPerm.caps == NULL) {
|
||||
INIT_LOGE("Failed to malloc for service %s", service->name);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
service->servPerm.capsCnt = capsCnt;
|
||||
unsigned int caps = FULL_CAP;
|
||||
for (int i = 0; i < capsCnt; ++i) { // number form
|
||||
cJSON *capJson = cJSON_GetArrayItem(filedJ, i);
|
||||
if (cJSON_IsNumber(capJson)) { // for number
|
||||
caps = (unsigned int)cJSON_GetNumberValue(capJson);
|
||||
} else if (cJSON_IsString(capJson)) {
|
||||
char *capStr = cJSON_GetStringValue(capJson);
|
||||
if (capStr == NULL || strlen(capStr) <= 0) { // check all errors
|
||||
INIT_LOGE("service=%s, parse item[%d] as string, error.", service->name, i);
|
||||
break;
|
||||
}
|
||||
caps = GetCapByString(capStr);
|
||||
}
|
||||
if (caps < 0) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
if ((caps > CAP_LAST_CAP) && (caps != (unsigned int)FULL_CAP)) {
|
||||
INIT_LOGE("service=%s, caps = %d, error.", service->name, caps);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
service->servPerm.caps[i] = (unsigned int)caps;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Executable
+731
@@ -0,0 +1,731 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "init_cmds.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <net/if.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "init.h"
|
||||
#include "init_jobs.h"
|
||||
#include "init_log.h"
|
||||
#include "init_service_manager.h"
|
||||
#include "init_utils.h"
|
||||
#include "securec.h"
|
||||
|
||||
static char *AddOneArg(const char *param, size_t paramLen)
|
||||
{
|
||||
int valueCount = 1;
|
||||
char *begin = strchr(param, '$');
|
||||
while (begin != NULL) {
|
||||
valueCount++;
|
||||
begin = strchr(begin + 1, '$');
|
||||
}
|
||||
size_t allocSize = paramLen + (PARAM_VALUE_LEN_MAX * valueCount) + 1;
|
||||
char *arg = calloc(sizeof(char), allocSize);
|
||||
INIT_CHECK(arg != NULL, return NULL);
|
||||
int ret = GetParamValue(param, paramLen, arg, allocSize);
|
||||
INIT_ERROR_CHECK(ret == 0, free(arg);
|
||||
return NULL, "Failed to get value for %s", param);
|
||||
return arg;
|
||||
}
|
||||
|
||||
char *BuildStringFromCmdArg(const struct CmdArgs *ctx, int startIndex)
|
||||
{
|
||||
char *options = (char *)calloc(1, OPTIONS_SIZE + 1);
|
||||
INIT_ERROR_CHECK(options != NULL, return NULL, "Failed to get memory ");
|
||||
options[0] = '\0';
|
||||
int curr = 0;
|
||||
for (int i = startIndex; i < ctx->argc; i++) { // save opt
|
||||
if (ctx->argv[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
int len = snprintf_s(options + curr, OPTIONS_SIZE - curr, OPTIONS_SIZE - 1 - curr, "%s ", ctx->argv[i]);
|
||||
if (len <= 0) {
|
||||
INIT_LOGE("Failed to format other opt");
|
||||
options[0] = '\0';
|
||||
return options;
|
||||
}
|
||||
curr += len;
|
||||
}
|
||||
if ((curr > 0) && (curr < OPTIONS_SIZE)) {
|
||||
options[curr - 1] = '\0';
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
const struct CmdArgs *GetCmdArg(const char *cmdContent, const char *delim, int argsCount)
|
||||
{
|
||||
INIT_CHECK_RETURN_VALUE(cmdContent != NULL, NULL);
|
||||
if (argsCount > SPACES_CNT_IN_CMD_MAX) {
|
||||
INIT_LOGW("Too much arguments for command, max number is %d", SPACES_CNT_IN_CMD_MAX);
|
||||
argsCount = SPACES_CNT_IN_CMD_MAX;
|
||||
}
|
||||
struct CmdArgs *ctx = (struct CmdArgs *)calloc(1, sizeof(struct CmdArgs) + sizeof(char *) * (argsCount + 1));
|
||||
INIT_ERROR_CHECK(ctx != NULL, return NULL, "Failed to malloc memory for arg");
|
||||
ctx->argc = 0;
|
||||
char *p = (char *)cmdContent;
|
||||
char *end = (char *)cmdContent + strlen(cmdContent);
|
||||
char *token = NULL;
|
||||
do {
|
||||
// Skip lead whitespaces
|
||||
while (isspace(*p)) {
|
||||
p++;
|
||||
}
|
||||
token = strstr(p, delim);
|
||||
if (token == NULL) {
|
||||
ctx->argv[ctx->argc] = AddOneArg(p, end - p);
|
||||
INIT_CHECK(ctx->argv[ctx->argc] != NULL, FreeCmdArg(ctx);
|
||||
return NULL);
|
||||
} else {
|
||||
ctx->argv[ctx->argc] = AddOneArg(p, token - p);
|
||||
INIT_CHECK(ctx->argv[ctx->argc] != NULL, FreeCmdArg(ctx);
|
||||
return NULL);
|
||||
}
|
||||
ctx->argc++;
|
||||
ctx->argv[ctx->argc] = NULL;
|
||||
if (ctx->argc == argsCount) {
|
||||
break;
|
||||
}
|
||||
p = token;
|
||||
} while (token != NULL);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void FreeCmdArg(struct CmdArgs *cmd)
|
||||
{
|
||||
INIT_CHECK_ONLY_RETURN(cmd != NULL);
|
||||
for (int i = 0; i < cmd->argc; ++i) {
|
||||
if (cmd->argv[i] != NULL) {
|
||||
free(cmd->argv[i]);
|
||||
}
|
||||
}
|
||||
free(cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
static void ExecCmd(const struct CmdTable *cmd, const char *cmdContent)
|
||||
{
|
||||
if (cmd == NULL) {
|
||||
INIT_LOGE("Invalid cmd for %s", cmdContent);
|
||||
return;
|
||||
}
|
||||
|
||||
const struct CmdArgs *ctx = GetCmdArg(cmdContent, " ", cmd->maxArg);
|
||||
if (ctx == NULL) {
|
||||
INIT_LOGE("Invalid arguments cmd: %s content: %s", cmd->name, cmdContent);
|
||||
} else if ((ctx->argc <= cmd->maxArg) && (ctx->argc >= cmd->minArg)) {
|
||||
cmd->DoFuncion(ctx, cmdContent);
|
||||
} else {
|
||||
INIT_LOGE("Invalid arguments cmd: %s content: %s argc: %d %d", cmd->name, cmdContent, ctx->argc, cmd->maxArg);
|
||||
}
|
||||
FreeCmdArg((struct CmdArgs *)ctx);
|
||||
}
|
||||
|
||||
static void SetProcName(const struct CmdArgs *ctx, const char *procFile)
|
||||
{
|
||||
int fd = open(procFile, O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
INIT_ERROR_CHECK(fd >= 0, return, "Failed to set %s errno: %d", procFile, errno);
|
||||
|
||||
size_t size = strlen(ctx->argv[0]);
|
||||
ssize_t n = write(fd, ctx->argv[0], size);
|
||||
INIT_ERROR_CHECK(n == (ssize_t)size, close(fd);
|
||||
return, "Failed to write domainname errno: %d", errno);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void DoSetDomainname(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
SetProcName(ctx, "/proc/sys/kernel/domainname");
|
||||
}
|
||||
|
||||
static void DoSetHostname(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
SetProcName(ctx, "/proc/sys/kernel/hostname");
|
||||
}
|
||||
|
||||
static void DoSleep(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
errno = 0;
|
||||
unsigned long sleepTime = strtoul(ctx->argv[0], NULL, DECIMAL_BASE);
|
||||
if (errno != 0) {
|
||||
INIT_LOGE("cannot covert sleep time in command \" sleep \"");
|
||||
return;
|
||||
}
|
||||
|
||||
// Limit sleep time in 5 seconds
|
||||
const unsigned long sleepTimeLimit = 5;
|
||||
if (sleepTime > sleepTimeLimit) {
|
||||
sleepTime = sleepTimeLimit;
|
||||
}
|
||||
INIT_LOGI("Sleeping %d second(s)", sleepTime);
|
||||
sleep((unsigned int)sleepTime);
|
||||
}
|
||||
|
||||
static void DoStart(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(ctx);
|
||||
INIT_LOGD("DoStart %s", cmdContent);
|
||||
StartServiceByName(cmdContent, true);
|
||||
}
|
||||
|
||||
static void DoStop(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(ctx);
|
||||
INIT_LOGD("DoStop %s", cmdContent);
|
||||
StopServiceByName(cmdContent);
|
||||
return;
|
||||
}
|
||||
|
||||
static void DoReset(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(ctx);
|
||||
INIT_LOGD("DoReset %s", cmdContent);
|
||||
DoStop(ctx, cmdContent);
|
||||
DoStart(ctx, cmdContent);
|
||||
}
|
||||
|
||||
static void DoCopy(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
int srcFd = -1;
|
||||
int dstFd = -1;
|
||||
char buf[MAX_COPY_BUF_SIZE] = { 0 };
|
||||
char *realPath1 = NULL;
|
||||
char *realPath2 = NULL;
|
||||
if (ctx == NULL || ctx->argc != DEFAULT_COPY_ARGS_CNT) {
|
||||
INIT_LOGE("DoCopy invalid arguments :%s", cmdContent);
|
||||
return;
|
||||
}
|
||||
do {
|
||||
realPath1 = GetRealPath(ctx->argv[0]);
|
||||
if (realPath1 == NULL) {
|
||||
INIT_LOGE("Failed to get real path %s", ctx->argv[0]);
|
||||
break;
|
||||
}
|
||||
srcFd = open(realPath1, O_RDONLY);
|
||||
if (srcFd < 0) {
|
||||
INIT_LOGE("Failed to open source path %s %d", ctx->argv[0], errno);
|
||||
break;
|
||||
}
|
||||
struct stat fileStat = { 0 };
|
||||
if (stat(ctx->argv[0], &fileStat) != 0) {
|
||||
INIT_LOGE("Failed to state source path %s %d", ctx->argv[0], errno);
|
||||
break;
|
||||
}
|
||||
mode_t mode = fileStat.st_mode;
|
||||
realPath2 = GetRealPath(ctx->argv[1]);
|
||||
if (realPath2 != NULL) {
|
||||
dstFd = open(realPath2, O_WRONLY | O_TRUNC | O_CREAT, mode);
|
||||
} else {
|
||||
dstFd = open(ctx->argv[1], O_WRONLY | O_TRUNC | O_CREAT, mode);
|
||||
}
|
||||
if (srcFd < 0) {
|
||||
INIT_LOGE("Failed to open dest path %s %d", ctx->argv[1], errno);
|
||||
break;
|
||||
}
|
||||
int rdLen = 0;
|
||||
while ((rdLen = read(srcFd, buf, sizeof(buf) - 1)) > 0) {
|
||||
int rtLen = write(dstFd, buf, rdLen);
|
||||
if (rtLen != rdLen) {
|
||||
INIT_LOGE("Failed to write to dest path %s %d", ctx->argv[1], errno);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fsync(dstFd);
|
||||
} while (0);
|
||||
INIT_CHECK(srcFd < 0, close(srcFd));
|
||||
INIT_CHECK(dstFd < 0, close(dstFd));
|
||||
INIT_CHECK(realPath1 == NULL, free(realPath1));
|
||||
INIT_CHECK(realPath2 == NULL, free(realPath2));
|
||||
}
|
||||
|
||||
static int SetOwner(const char *file, const char *ownerStr, const char *groupStr)
|
||||
{
|
||||
INIT_ERROR_CHECK(file != NULL, return -1, "SetOwner invalid file.");
|
||||
INIT_ERROR_CHECK(ownerStr != NULL, return -1, "SetOwner invalid file.");
|
||||
INIT_ERROR_CHECK(groupStr != NULL, return -1, "SetOwner invalid file.");
|
||||
|
||||
uid_t owner = DecodeUid(ownerStr);
|
||||
INIT_ERROR_CHECK(owner != (uid_t)-1, return -1, "SetOwner invalid uid :%s.", ownerStr);
|
||||
gid_t group = DecodeUid(groupStr);
|
||||
INIT_ERROR_CHECK(group != (gid_t)-1, return -1, "SetOwner invalid gid :%s.", groupStr);
|
||||
return (chown(file, owner, group) != 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
static void DoChown(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
// format: chown owner group /xxx/xxx/xxx
|
||||
const int pathPos = 2;
|
||||
int ret = SetOwner(ctx->argv[pathPos], ctx->argv[0], ctx->argv[1]);
|
||||
if (ret != 0) {
|
||||
INIT_LOGE("Failed to change owner %s, err %d.", cmdContent, errno);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void DoMkDir(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
// mkdir support format:
|
||||
// 1.mkdir path
|
||||
// 2.mkdir path mode
|
||||
// 3.mkdir path mode owner group
|
||||
UNUSED(cmdContent);
|
||||
const int ownerPos = 2;
|
||||
const int groupPos = 3;
|
||||
if (ctx->argc != 1 && ctx->argc != (groupPos + 1) && ctx->argc != ownerPos) {
|
||||
INIT_LOGE("DoMkDir invalid arguments: %s", cmdContent);
|
||||
return;
|
||||
}
|
||||
mode_t mode = DEFAULT_DIR_MODE;
|
||||
if (mkdir(ctx->argv[0], mode) != 0 && errno != EEXIST) {
|
||||
INIT_LOGE("DoMkDir, failed for '%s', err %d.", ctx->argv[0], errno);
|
||||
return;
|
||||
}
|
||||
if (ctx->argc <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
mode = strtoul(ctx->argv[1], NULL, OCTAL_TYPE);
|
||||
if (chmod(ctx->argv[0], mode) != 0) {
|
||||
INIT_LOGE("DoMkDir failed for '%s', err %d.", ctx->argv[0], errno);
|
||||
}
|
||||
if (ctx->argc <= ownerPos) {
|
||||
return;
|
||||
}
|
||||
int ret = SetOwner(ctx->argv[0], ctx->argv[ownerPos], ctx->argv[groupPos]);
|
||||
if (ret != 0) {
|
||||
INIT_LOGE("Failed to change owner %s, err %d.", cmdContent, errno);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void DoChmod(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
// format: chmod xxxx /xxx/xxx/xxx
|
||||
mode_t mode = strtoul(ctx->argv[0], NULL, OCTAL_TYPE);
|
||||
if (mode == 0) {
|
||||
INIT_LOGE("DoChmod, strtoul failed for %s, er %d.", cmdContent, errno);
|
||||
return;
|
||||
}
|
||||
|
||||
if (chmod(ctx->argv[1], mode) != 0) {
|
||||
INIT_LOGE("Failed to change mode \" %s \" mode to %04o, err = %d", ctx->argv[1], mode, errno);
|
||||
}
|
||||
}
|
||||
|
||||
static int GetMountFlag(unsigned long *mountflag, const char *targetStr, const char *source)
|
||||
{
|
||||
if (targetStr == NULL || mountflag == NULL) {
|
||||
return 0;
|
||||
}
|
||||
struct {
|
||||
char *flagName;
|
||||
int value;
|
||||
} mountFlagMap[] = {
|
||||
{ "noatime", MS_NOATIME },
|
||||
{ "noexec", MS_NOEXEC },
|
||||
{ "nosuid", MS_NOSUID },
|
||||
{ "nodev", MS_NODEV },
|
||||
{ "nodiratime", MS_NODIRATIME },
|
||||
{ "ro", MS_RDONLY },
|
||||
{ "rdonly", MS_RDONLY },
|
||||
{ "rw", 0 },
|
||||
{ "sync", MS_SYNCHRONOUS },
|
||||
{ "remount", MS_REMOUNT },
|
||||
{ "bind", MS_BIND },
|
||||
{ "rec", MS_REC },
|
||||
{ "unbindable", MS_UNBINDABLE },
|
||||
{ "private", MS_PRIVATE },
|
||||
{ "slave", MS_SLAVE },
|
||||
{ "shared", MS_SHARED },
|
||||
{ "defaults", 0 },
|
||||
};
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH(mountFlagMap); i++) {
|
||||
if (strncmp(targetStr, mountFlagMap[i].flagName, strlen(mountFlagMap[i].flagName)) == 0) {
|
||||
*mountflag |= mountFlagMap[i].value;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (strncmp(targetStr, "wait", strlen("wait")) == 0) {
|
||||
WaitForFile(source, WAIT_MAX_COUNT);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void DoMount(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(ctx);
|
||||
INIT_ERROR_CHECK(ctx->argc <= SPACES_CNT_IN_CMD_MAX, return, "Invalid arg number");
|
||||
// format: fileSystemType source target mountFlag1 mountFlag2... data
|
||||
int index = 0;
|
||||
char *fileSysType = (ctx->argc > index) ? ctx->argv[index] : NULL;
|
||||
INIT_ERROR_CHECK(fileSysType != NULL, return, "Failed to get fileSysType %s", cmdContent);
|
||||
index++;
|
||||
|
||||
char *source = (ctx->argc > index) ? ctx->argv[index] : NULL;
|
||||
INIT_ERROR_CHECK(source != NULL, return, "Failed to get source %s", cmdContent);
|
||||
index++;
|
||||
|
||||
// maybe only has "filesystype source target", 2 spaces
|
||||
char *target = (ctx->argc > index) ? ctx->argv[index] : NULL;
|
||||
INIT_ERROR_CHECK(target != NULL, return, "Failed to get target %s", cmdContent);
|
||||
++index;
|
||||
|
||||
int ret = 0;
|
||||
unsigned long mountflags = 0;
|
||||
while (index < ctx->argc) {
|
||||
ret = GetMountFlag(&mountflags, ctx->argv[index], source);
|
||||
if (ret == 0) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if (index >= ctx->argc) {
|
||||
ret = mount(source, target, fileSysType, mountflags, NULL);
|
||||
} else {
|
||||
char *data = BuildStringFromCmdArg(ctx, index);
|
||||
INIT_ERROR_CHECK(data != NULL, return, "Failed to get data %s", cmdContent);
|
||||
ret = mount(source, target, fileSysType, mountflags, data);
|
||||
free(data);
|
||||
}
|
||||
if (ret != 0) {
|
||||
INIT_LOGE("Failed to mount %s, err %d.", cmdContent, errno);
|
||||
}
|
||||
}
|
||||
|
||||
static bool CheckValidCfg(const char *path)
|
||||
{
|
||||
static const char *supportCfg[] = {
|
||||
"/etc/patch.cfg",
|
||||
"/patch/fstab.cfg",
|
||||
};
|
||||
INIT_ERROR_CHECK(path != NULL, return false, "Invalid path for cfg");
|
||||
struct stat fileStat = { 0 };
|
||||
if (stat(path, &fileStat) != 0 || fileStat.st_size <= 0 || fileStat.st_size > LOADCFG_MAX_FILE_LEN) {
|
||||
return false;
|
||||
}
|
||||
size_t cfgCnt = ARRAY_LENGTH(supportCfg);
|
||||
for (size_t i = 0; i < cfgCnt; ++i) {
|
||||
if (strcmp(path, supportCfg[i]) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void DoLoadCfg(const struct CmdArgs *ctx, const char *path)
|
||||
{
|
||||
UNUSED(ctx);
|
||||
char buf[LOADCFG_BUF_SIZE] = { 0 };
|
||||
size_t maxLoop = 0;
|
||||
int len;
|
||||
if (!CheckValidCfg(path)) {
|
||||
INIT_LOGE("CheckCfg file %s Failed", path);
|
||||
return;
|
||||
}
|
||||
char *realPath = GetRealPath(path);
|
||||
INIT_ERROR_CHECK(realPath != NULL, return, "Failed to get realpath %s", path);
|
||||
FILE *fp = fopen(realPath, "r");
|
||||
if (fp == NULL) {
|
||||
INIT_LOGE("Failed to open cfg %s error:%d", path, errno);
|
||||
free(realPath);
|
||||
return;
|
||||
}
|
||||
|
||||
while (fgets(buf, LOADCFG_BUF_SIZE - 1, fp) != NULL && maxLoop < LOADCFG_MAX_LOOP) {
|
||||
maxLoop++;
|
||||
len = strlen(buf);
|
||||
if (len < 1) {
|
||||
continue;
|
||||
}
|
||||
if (buf[len - 1] == '\n') {
|
||||
buf[len - 1] = '\0'; // we replace '\n' with '\0'
|
||||
}
|
||||
const struct CmdTable *cmd = GetCmdByName(buf);
|
||||
if (cmd == NULL) {
|
||||
INIT_LOGE("Cannot support command: %s", buf);
|
||||
continue;
|
||||
}
|
||||
ExecCmd(cmd, &buf[strlen(cmd->name) + 1]);
|
||||
}
|
||||
free(realPath);
|
||||
(void)fclose(fp);
|
||||
}
|
||||
|
||||
static void DoWrite(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
// format: write path content
|
||||
char *realPath = GetRealPath(ctx->argv[0]);
|
||||
int fd = -1;
|
||||
if (realPath != NULL) {
|
||||
fd = open(realPath, O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR);
|
||||
} else {
|
||||
fd = open(ctx->argv[0], O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR);
|
||||
}
|
||||
if (fd >= 0) {
|
||||
size_t ret = write(fd, ctx->argv[1], strlen(ctx->argv[1]));
|
||||
if (ret < 0) {
|
||||
INIT_LOGE("DoWrite: write to file %s failed: %d", ctx->argv[0], errno);
|
||||
}
|
||||
}
|
||||
if (realPath != NULL) {
|
||||
free(realPath);
|
||||
}
|
||||
realPath = NULL;
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void DoRmdir(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
// format: rmdir path
|
||||
int ret = rmdir(ctx->argv[0]);
|
||||
if (ret == -1) {
|
||||
INIT_LOGE("DoRmdir: remove %s failed: %d.", ctx->argv[0], errno);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void DoRebootCmd(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(ctx);
|
||||
ExecReboot(cmdContent);
|
||||
return;
|
||||
}
|
||||
|
||||
static void DoSetrlimit(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
static const char *resource[] = {
|
||||
"RLIMIT_CPU", "RLIMIT_FSIZE", "RLIMIT_DATA", "RLIMIT_STACK", "RLIMIT_CORE", "RLIMIT_RSS",
|
||||
"RLIMIT_NPROC", "RLIMIT_NOFILE", "RLIMIT_MEMLOCK", "RLIMIT_AS", "RLIMIT_LOCKS", "RLIMIT_SIGPENDING",
|
||||
"RLIMIT_MSGQUEUE", "RLIMIT_NICE", "RLIMIT_RTPRIO", "RLIMIT_RTTIME", "RLIM_NLIMITS"
|
||||
};
|
||||
// format: setrlimit resource curValue maxValue
|
||||
const int rlimMaxPos = 2;
|
||||
struct rlimit limit;
|
||||
limit.rlim_cur = (rlim_t)atoi(ctx->argv[1]);
|
||||
limit.rlim_max = (rlim_t)atoi(ctx->argv[rlimMaxPos]);
|
||||
int rcs = -1;
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH(resource); ++i) {
|
||||
if (strcmp(ctx->argv[0], resource[i]) == 0) {
|
||||
rcs = (int)i;
|
||||
}
|
||||
}
|
||||
if (rcs == -1) {
|
||||
INIT_LOGE("DoSetrlimit failed, resouces :%s not support.", ctx->argv[0]);
|
||||
return;
|
||||
}
|
||||
int ret = setrlimit(rcs, &limit);
|
||||
if (ret) {
|
||||
INIT_LOGE("DoSetrlimit failed : %d", errno);
|
||||
}
|
||||
}
|
||||
|
||||
static void DoRm(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
// format: rm /xxx/xxx/xxx
|
||||
int ret = unlink(ctx->argv[0]);
|
||||
if (ret == -1) {
|
||||
INIT_LOGE("DoRm: unlink %s failed: %d.", ctx->argv[0], errno);
|
||||
}
|
||||
}
|
||||
|
||||
static void DoExport(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
// format: export xxx /xxx/xxx/xxx
|
||||
int ret = setenv(ctx->argv[0], ctx->argv[1], 1);
|
||||
if (ret != 0) {
|
||||
INIT_LOGE("DoExport: set %s with %s failed: %d", ctx->argv[0], ctx->argv[1], errno);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct CmdTable g_cmdTable[] = {
|
||||
{ "start ", 0, 1, DoStart },
|
||||
{ "mkdir ", 1, 4, DoMkDir },
|
||||
{ "chmod ", 2, 2, DoChmod },
|
||||
{ "chown ", 3, 3, DoChown },
|
||||
{ "mount ", 1, 10, DoMount },
|
||||
{ "export ", 2, 2, DoExport },
|
||||
{ "loadcfg ", 1, 1, DoLoadCfg },
|
||||
{ "rm ", 1, 1, DoRm },
|
||||
{ "rmdir ", 1, 1, DoRmdir },
|
||||
{ "write ", 2, 2, DoWrite },
|
||||
{ "stop ", 1, 1, DoStop },
|
||||
{ "reset ", 1, 1, DoReset },
|
||||
{ "copy ", 2, 2, DoCopy },
|
||||
{ "reboot ", 1, 1, DoRebootCmd },
|
||||
{ "setrlimit ", 3, 3, DoSetrlimit },
|
||||
{ "sleep ", 1, 1, DoSleep },
|
||||
{ "hostname ", 1, 1, DoSetHostname },
|
||||
{ "domainname ", 1, 1, DoSetDomainname }
|
||||
};
|
||||
|
||||
static const struct CmdTable *GetCommCmdTable(int *number)
|
||||
{
|
||||
*number = (int)ARRAY_LENGTH(g_cmdTable);
|
||||
return g_cmdTable;
|
||||
}
|
||||
|
||||
const struct CmdTable *GetCmdByName(const char *name)
|
||||
{
|
||||
int cmdCnt = 0;
|
||||
const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt);
|
||||
for (int i = 0; i < cmdCnt; ++i) {
|
||||
if (strncmp(name, commCmds[i].name, strlen(commCmds[i].name)) == 0) {
|
||||
return &commCmds[i];
|
||||
}
|
||||
}
|
||||
int number = 0;
|
||||
const struct CmdTable *cmds = GetCmdTable(&number);
|
||||
for (int i = 0; i < number; ++i) {
|
||||
if (strncmp(name, cmds[i].name, strlen(cmds[i].name)) == 0) {
|
||||
return &cmds[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *GetMatchCmd(const char *cmdStr, int *index)
|
||||
{
|
||||
if (cmdStr == NULL || index == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
int cmdCnt = 0;
|
||||
const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt);
|
||||
for (int i = 0; i < cmdCnt; ++i) {
|
||||
if (strncmp(cmdStr, commCmds[i].name, strlen(commCmds[i].name)) == 0) {
|
||||
*index = i;
|
||||
return commCmds[i].name;
|
||||
}
|
||||
}
|
||||
int number = 0;
|
||||
const struct CmdTable *cmds = GetCmdTable(&number);
|
||||
for (int i = 0; i < number; ++i) {
|
||||
if (strncmp(cmdStr, cmds[i].name, strlen(cmds[i].name)) == 0) {
|
||||
*index = cmdCnt + i;
|
||||
return cmds[i].name;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *GetCmdKey(int index)
|
||||
{
|
||||
int cmdCnt = 0;
|
||||
const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt);
|
||||
if (index < cmdCnt) {
|
||||
return commCmds[index].name;
|
||||
}
|
||||
int number = 0;
|
||||
const struct CmdTable *cmds = GetCmdTable(&number);
|
||||
if (index < number) {
|
||||
return cmds[index].name;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int GetCmdLinesFromJson(const cJSON *root, CmdLines **cmdLines)
|
||||
{
|
||||
INIT_CHECK(root != NULL, return -1);
|
||||
INIT_CHECK(cmdLines != NULL, return -1);
|
||||
*cmdLines = NULL;
|
||||
if (!cJSON_IsArray(root)) {
|
||||
return -1;
|
||||
}
|
||||
int cmdCnt = cJSON_GetArraySize(root);
|
||||
if (cmdCnt <= 0) {
|
||||
return -1;
|
||||
}
|
||||
*cmdLines = (CmdLines *)calloc(1, sizeof(CmdLines) + sizeof(CmdLine) * cmdCnt);
|
||||
if (*cmdLines == NULL) {
|
||||
return -1;
|
||||
}
|
||||
(*cmdLines)->cmdNum = 0;
|
||||
for (int i = 0; i < cmdCnt; ++i) {
|
||||
cJSON *line = cJSON_GetArrayItem(root, i);
|
||||
if (!cJSON_IsString(line)) {
|
||||
continue;
|
||||
}
|
||||
char *tmp = cJSON_GetStringValue(line);
|
||||
if (tmp == NULL) {
|
||||
continue;
|
||||
}
|
||||
int index = 0;
|
||||
const char *cmd = GetMatchCmd(tmp, &index);
|
||||
if (cmd == NULL) {
|
||||
INIT_LOGE("Cannot support command: %s", tmp);
|
||||
continue;
|
||||
}
|
||||
int ret = strcpy_s((*cmdLines)->cmds[(*cmdLines)->cmdNum].cmdContent, MAX_CMD_CONTENT_LEN, tmp + strlen(cmd));
|
||||
if (ret != EOK) {
|
||||
INIT_LOGE("Invalid cmd arg: %s", tmp);
|
||||
continue;
|
||||
}
|
||||
(*cmdLines)->cmds[(*cmdLines)->cmdNum].cmdIndex = index;
|
||||
(*cmdLines)->cmdNum++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DoCmdByName(const char *name, const char *cmdContent)
|
||||
{
|
||||
if (name == NULL || cmdContent == NULL) {
|
||||
return;
|
||||
}
|
||||
const struct CmdTable *cmd = GetCmdByName(name);
|
||||
ExecCmd(cmd, cmdContent);
|
||||
}
|
||||
|
||||
void DoCmdByIndex(int index, const char *cmdContent)
|
||||
{
|
||||
if (cmdContent == NULL) {
|
||||
return;
|
||||
}
|
||||
int cmdCnt = 0;
|
||||
const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt);
|
||||
if (index < cmdCnt) {
|
||||
ExecCmd(&commCmds[index], cmdContent);
|
||||
return;
|
||||
}
|
||||
int number = 0;
|
||||
const struct CmdTable *cmds = GetCmdTable(&number);
|
||||
if (index < (cmdCnt + number)) {
|
||||
ExecCmd(&cmds[index - cmdCnt], cmdContent);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+101
-118
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2020-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
|
||||
@@ -12,12 +12,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init_service.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -25,46 +23,32 @@
|
||||
#ifdef __MUSL__
|
||||
#include <stropts.h>
|
||||
#endif
|
||||
#include <sys/capability.h>
|
||||
#include <sys/param.h>
|
||||
#ifndef OHOS_LITE
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "init.h"
|
||||
#include "init_adapter.h"
|
||||
#include "init_cmds.h"
|
||||
#include "init_log.h"
|
||||
#ifndef OHOS_LITE
|
||||
#include "init_param.h"
|
||||
#endif
|
||||
#include "init_perms.h"
|
||||
#include "init_reboot.h"
|
||||
#include "init_service_socket.h"
|
||||
#include "init_utils.h"
|
||||
#include "securec.h"
|
||||
#ifndef OHOS_LITE
|
||||
#include "sys_param.h"
|
||||
#endif
|
||||
|
||||
#define CAP_NUM 2
|
||||
#define WAIT_MAX_COUNT 10
|
||||
|
||||
#ifndef TIOCSCTTY
|
||||
#define TIOCSCTTY 0x540E
|
||||
#endif
|
||||
// 240 seconds, 4 minutes
|
||||
static const int CRASH_TIME_LIMIT = 240;
|
||||
static const int CRASH_TIME_LIMIT = 240;
|
||||
// maximum number of crashes within time CRASH_TIME_LIMIT for one service
|
||||
static const int CRASH_COUNT_LIMIT = 4;
|
||||
|
||||
// 240 seconds, 4 minutes
|
||||
static const int CRITICAL_CRASH_TIME_LIMIT = 240;
|
||||
static const int CRITICAL_CRASH_TIME_LIMIT = 240;
|
||||
// maximum number of crashes within time CRITICAL_CRASH_TIME_LIMIT for one service
|
||||
static const int CRITICAL_CRASH_COUNT_LIMIT = 4;
|
||||
static const int MAX_PID_STRING_LENGTH = 50;
|
||||
|
||||
|
||||
static int SetAllAmbientCapability(void)
|
||||
{
|
||||
@@ -101,14 +85,13 @@ static int SetPerms(const Service *service)
|
||||
struct __user_cap_header_struct capHeader;
|
||||
capHeader.version = _LINUX_CAPABILITY_VERSION_3;
|
||||
capHeader.pid = 0;
|
||||
|
||||
struct __user_cap_data_struct capData[CAP_NUM] = {};
|
||||
for (unsigned int i = 0; i < service->servPerm.capsCnt; ++i) {
|
||||
if (service->servPerm.caps[i] == FULL_CAP) {
|
||||
for (int i = 0; i < CAP_NUM; ++i) {
|
||||
capData[i].effective = FULL_CAP;
|
||||
capData[i].permitted = FULL_CAP;
|
||||
capData[i].inheritable = FULL_CAP;
|
||||
for (int j = 0; j < CAP_NUM; ++j) {
|
||||
capData[j].effective = FULL_CAP;
|
||||
capData[j].permitted = FULL_CAP;
|
||||
capData[j].inheritable = FULL_CAP;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -135,6 +118,7 @@ static int SetPerms(const Service *service)
|
||||
|
||||
static void OpenConsole(void)
|
||||
{
|
||||
const int stdError = 2;
|
||||
setsid();
|
||||
WaitForFile("/dev/console", WAIT_MAX_COUNT);
|
||||
int fd = open("/dev/console", O_RDWR);
|
||||
@@ -142,7 +126,7 @@ static void OpenConsole(void)
|
||||
ioctl(fd, TIOCSCTTY, 0);
|
||||
dup2(fd, 0);
|
||||
dup2(fd, 1);
|
||||
dup2(fd, 2); // Redirect fd to 0, 1, 2
|
||||
dup2(fd, stdError); // Redirect fd to 0, 1, 2
|
||||
close(fd);
|
||||
} else {
|
||||
INIT_LOGE("Open /dev/console failed. err = %d", errno);
|
||||
@@ -150,107 +134,106 @@ static void OpenConsole(void)
|
||||
return;
|
||||
}
|
||||
|
||||
static void WriteServicePid(const Service *service, pid_t pid)
|
||||
static int WritePid(const Service *service)
|
||||
{
|
||||
char pidString[MAX_PID_STRING_LENGTH];
|
||||
INIT_ERROR_CHECK(snprintf_s(pidString, MAX_PID_STRING_LENGTH, MAX_PID_STRING_LENGTH - 1, "%d", pid) >= 0,
|
||||
_exit(0x7f), "Build pid string failed");
|
||||
|
||||
for (int i = 0; i < MAX_WRITEPID_FILES; i++) {
|
||||
if (service->writepidFiles[i] == NULL) {
|
||||
break;
|
||||
}
|
||||
char *realPath = realpath(service->writepidFiles[i], NULL);
|
||||
if (realPath == NULL) {
|
||||
const int maxPidStrLen = 50;
|
||||
char pidString[maxPidStrLen];
|
||||
pid_t childPid = getpid();
|
||||
int len = snprintf_s(pidString, maxPidStrLen, maxPidStrLen - 1, "%d", childPid);
|
||||
if (len <= 0) {
|
||||
INIT_LOGE("Failed to format pid for service %s", service->name);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
for (int i = 0; i < service->writePidArgs.count; i++) {
|
||||
if (service->writePidArgs.argv[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
FILE *fd = fopen(realPath, "wb");
|
||||
free(realPath);
|
||||
realPath = NULL;
|
||||
INIT_ERROR_CHECK(fd != NULL, continue, "Open file %s failed, err = %d", service->writepidFiles[i], errno);
|
||||
INIT_CHECK_ONLY_ELOG(fwrite(pidString, 1, strlen(pidString), fd) == strlen(pidString),
|
||||
"write pid %s to file %s failed, err = %d", pidString, service->writepidFiles[i], errno);
|
||||
fclose(fd);
|
||||
FILE *fd = NULL;
|
||||
char *realPath = GetRealPath(service->writePidArgs.argv[i]);
|
||||
if (realPath != NULL) {
|
||||
fd = fopen(realPath, "wb");
|
||||
} else {
|
||||
fd = fopen(service->writePidArgs.argv[i], "wb");
|
||||
}
|
||||
if (fd != NULL) {
|
||||
if ((int)fwrite(pidString, 1, len, fd) != len) {
|
||||
INIT_LOGE("Failed to write %s pid:%s", service->writePidArgs.argv[i], pidString);
|
||||
}
|
||||
(void)fclose(fd);
|
||||
} else {
|
||||
INIT_LOGE("Failed to open %s.", service->writePidArgs.argv[i]);
|
||||
}
|
||||
if (realPath != NULL) {
|
||||
free(realPath);
|
||||
}
|
||||
INIT_LOGD("ServiceStart writepid filename=%s, childPid=%s, ok", service->writePidArgs.argv[i], pidString);
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
int ServiceStart(Service *service)
|
||||
{
|
||||
INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "start service failed! null ptr.");
|
||||
INIT_INFO_CHECK(service->pid <= 0, return SERVICE_SUCCESS, "service : %s had started already.", service->name);
|
||||
INIT_ERROR_CHECK(service->pid <= 0, return SERVICE_SUCCESS, "service : %s had started already.", service->name);
|
||||
INIT_ERROR_CHECK(service->pathArgs.count > 0,
|
||||
return SERVICE_FAILURE, "start service %s pathArgs is NULL.", service->name);
|
||||
if (service->attribute & SERVICE_ATTR_INVALID) {
|
||||
INIT_LOGE("start service %s invalid.", service->name);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
INIT_ERROR_CHECK(service->pathArgs != NULL, return SERVICE_FAILURE, "start service pathArgs is NULL.");
|
||||
struct stat pathStat = {0};
|
||||
struct stat pathStat = { 0 };
|
||||
service->attribute &= (~(SERVICE_ATTR_NEED_RESTART | SERVICE_ATTR_NEED_STOP));
|
||||
INIT_ERROR_CHECK(stat(service->pathArgs[0], &pathStat) == 0, service->attribute |= SERVICE_ATTR_INVALID;
|
||||
return SERVICE_FAILURE, "start service %s invalid, please check %s.", service->name, service->pathArgs[0]);
|
||||
pid_t pid = fork();
|
||||
if (stat(service->pathArgs.argv[0], &pathStat) != 0) {
|
||||
service->attribute |= SERVICE_ATTR_INVALID;
|
||||
INIT_LOGE("start service %s invalid, please check %s.", service->name, service->pathArgs.argv[0]);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
int pid = fork();
|
||||
if (pid == 0) {
|
||||
if (service->socketCfg != NULL) { // start socket service
|
||||
INIT_ERROR_CHECK(DoCreateSocket(service->socketCfg) >= 0, _exit(0x7f), "Create Socket failed. ");
|
||||
int ret = CreateServiceSocket(service->socketCfg);
|
||||
if (ret < 0) {
|
||||
INIT_LOGE("service %s exit! create socket failed!", service->name);
|
||||
_exit(PROCESS_EXIT_CODE);
|
||||
}
|
||||
if (service->attribute & SERVICE_ATTR_CONSOLE) {
|
||||
OpenConsole();
|
||||
}
|
||||
INIT_ERROR_CHECK(SetPerms(service) == SERVICE_SUCCESS, _exit(0x7f),
|
||||
"service %s exit! set perms failed! err %d.", service->name, errno);
|
||||
WriteServicePid(service, getpid());
|
||||
INIT_LOGI("service->name is %s ", service->name);
|
||||
#ifndef OHOS_LITE
|
||||
if (service->importance != 0) {
|
||||
INIT_ERROR_CHECK(setpriority(PRIO_PROCESS, 0, service->importance) == 0, _exit(0x7f),
|
||||
"setpriority failed for %s, importance = %d", service->name, service->importance);
|
||||
// permissions
|
||||
if (SetPerms(service) != SERVICE_SUCCESS) {
|
||||
INIT_LOGE("service %s exit! set perms failed! err %d.", service->name, errno);
|
||||
_exit(PROCESS_EXIT_CODE);
|
||||
}
|
||||
// L2 Can not be reset env
|
||||
INIT_CHECK_ONLY_ELOG(execv(service->pathArgs[0], service->pathArgs) == 0,
|
||||
"service %s execve failed! err %d.", service->name, errno);
|
||||
#else
|
||||
char* env[] = {"LD_LIBRARY_PATH=/storage/app/libs", NULL};
|
||||
INIT_CHECK_ONLY_ELOG(execve(service->pathArgs[0], service->pathArgs, env) == 0,
|
||||
"service %s execve failed! err %d.", service->name, errno);
|
||||
#endif
|
||||
_exit(0x7f); // 0x7f: user specified
|
||||
// write pid
|
||||
if (WritePid(service) != SERVICE_SUCCESS) {
|
||||
INIT_LOGE("service %s exit! write pid failed!", service->name);
|
||||
_exit(PROCESS_EXIT_CODE);
|
||||
}
|
||||
ServiceExec(service);
|
||||
_exit(PROCESS_EXIT_CODE);
|
||||
} else if (pid < 0) {
|
||||
INIT_LOGE("start service %s fork failed!", service->name);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
INIT_LOGI("service %s starting pid %d", service->name, pid);
|
||||
service->pid = pid;
|
||||
#ifndef OHOS_LITE
|
||||
char paramName[PARAM_NAME_LEN_MAX] = {0};
|
||||
int ret = snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.svc.%s", service->name);
|
||||
INIT_CHECK_ONLY_ELOG(ret >= 0, "snprintf_s paramName error %d ", errno);
|
||||
SystemWriteParam(paramName, "running");
|
||||
#endif
|
||||
NotifyServiceChange(service->name, "running");
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
int ServiceStop(Service *service)
|
||||
{
|
||||
if (service == NULL) {
|
||||
INIT_LOGE("stop service failed! null ptr.");
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "stop service failed! null ptr.");
|
||||
service->attribute &= ~SERVICE_ATTR_NEED_RESTART;
|
||||
service->attribute |= SERVICE_ATTR_NEED_STOP;
|
||||
if (service->pid <= 0) {
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
CloseServiceSocket(service->socketCfg);
|
||||
if (kill(service->pid, SIGKILL) != 0) {
|
||||
INIT_LOGE("stop service %s pid %d failed! err %d.", service->name, service->pid, errno);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
#ifndef OHOS_LITE
|
||||
char paramName[PARAM_NAME_LEN_MAX] = {0};
|
||||
if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.svc.%s", service->name) < 0) {
|
||||
INIT_LOGE("snprintf_s paramName error %d ", errno);
|
||||
}
|
||||
SystemWriteParam(paramName, "stopping");
|
||||
#endif
|
||||
NotifyServiceChange(service->name, "stopping");
|
||||
INIT_LOGI("stop service %s, pid %d.", service->name, service->pid);
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
@@ -277,46 +260,37 @@ static bool CalculateCrashTime(Service *service, int crashTimeLimit, int crashCo
|
||||
|
||||
static int ExecRestartCmd(const Service *service)
|
||||
{
|
||||
INIT_LOGI("ExecRestartCmd ");
|
||||
if ((service == NULL) || (service->onRestart == NULL) || (service->onRestart->cmdLine == NULL)) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Exec service failed! null ptr.");
|
||||
INIT_ERROR_CHECK(service->restartArg != NULL, return SERVICE_FAILURE, "restartArg is null");
|
||||
|
||||
for (int i = 0; i < service->onRestart->cmdNum; i++) {
|
||||
INIT_LOGI("SetOnRestart cmdLine->name %s cmdLine->cmdContent %s ", service->onRestart->cmdLine[i].name,
|
||||
service->onRestart->cmdLine[i].cmdContent);
|
||||
DoCmd(&service->onRestart->cmdLine[i]);
|
||||
for (int i = 0; i < service->restartArg->cmdNum; i++) {
|
||||
INIT_LOGI("ExecRestartCmd cmdLine->cmdContent %s ", service->restartArg->cmds[i].cmdContent);
|
||||
DoCmdByIndex(service->restartArg->cmds[i].cmdIndex, service->restartArg->cmds[i].cmdContent);
|
||||
}
|
||||
free(service->onRestart->cmdLine);
|
||||
service->onRestart->cmdLine = NULL;
|
||||
free(service->onRestart);
|
||||
free(service->restartArg);
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
void ServiceReap(Service *service)
|
||||
{
|
||||
if (service == NULL) {
|
||||
INIT_LOGE("reap service failed! null ptr.");
|
||||
return;
|
||||
}
|
||||
INIT_CHECK(service != NULL, return);
|
||||
INIT_LOGI("Reap service %s, pid %d.", service->name, service->pid);
|
||||
service->pid = -1;
|
||||
#ifndef OHOS_LITE
|
||||
char paramName[PARAM_NAME_LEN_MAX] = {0};
|
||||
if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.svc.%s", service->name) < 0) {
|
||||
INIT_LOGE("snprintf_s paramName error %d ", errno);
|
||||
}
|
||||
SystemWriteParam(paramName, "stopped");
|
||||
#endif
|
||||
NotifyServiceChange(service->name, "stopped");
|
||||
|
||||
if (service->attribute & SERVICE_ATTR_INVALID) {
|
||||
INIT_LOGE("ServiceReap service %s invalid.", service->name);
|
||||
INIT_LOGE("Reap service %s invalid.", service->name);
|
||||
return;
|
||||
}
|
||||
|
||||
CloseServiceSocket(service->socketCfg);
|
||||
// stopped by system-init itself, no need to restart even if it is not one-shot service
|
||||
if (service->attribute & SERVICE_ATTR_NEED_STOP) {
|
||||
service->attribute &= (~SERVICE_ATTR_NEED_STOP);
|
||||
service->crashCnt = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// for one-shot service
|
||||
if (service->attribute & SERVICE_ATTR_ONCE) {
|
||||
// no need to restart
|
||||
@@ -324,12 +298,14 @@ void ServiceReap(Service *service)
|
||||
service->attribute &= (~SERVICE_ATTR_NEED_STOP);
|
||||
return;
|
||||
}
|
||||
// the service could be restart even if it is one-shot service
|
||||
}
|
||||
if (service->attribute & SERVICE_ATTR_CRITICAL) { // critical
|
||||
|
||||
if (service->attribute & SERVICE_ATTR_CRITICAL) { // critical
|
||||
if (CalculateCrashTime(service, CRITICAL_CRASH_TIME_LIMIT, CRITICAL_CRASH_COUNT_LIMIT) == false) {
|
||||
INIT_LOGE("Critical service \" %s \" crashed %d times, rebooting system",
|
||||
service->name, CRITICAL_CRASH_COUNT_LIMIT);
|
||||
DoReboot("reboot");
|
||||
ExecReboot("reboot");
|
||||
}
|
||||
} else if (!(service->attribute & SERVICE_ATTR_NEED_RESTART)) {
|
||||
if (CalculateCrashTime(service, CRASH_TIME_LIMIT, CRASH_COUNT_LIMIT) == false) {
|
||||
@@ -337,10 +313,17 @@ void ServiceReap(Service *service)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (service->onRestart != NULL) {
|
||||
INIT_CHECK_ONLY_ELOG(ExecRestartCmd(service) == SERVICE_SUCCESS, "SetOnRestart fail ");
|
||||
|
||||
int ret = 0;
|
||||
if (service->restartArg != NULL) {
|
||||
ret = ExecRestartCmd(service);
|
||||
if (ret != SERVICE_SUCCESS) {
|
||||
INIT_LOGE("Failed to exec restartArg for %s", service->name);
|
||||
}
|
||||
}
|
||||
ret = ServiceStart(service);
|
||||
if (ret != SERVICE_SUCCESS) {
|
||||
INIT_LOGE("reap service %s start failed!", service->name);
|
||||
}
|
||||
INIT_CHECK_ONLY_ELOG(ServiceStart(service) == SERVICE_SUCCESS, "reap service %s start failed!", service->name);
|
||||
service->attribute &= (~SERVICE_ATTR_NEED_RESTART);
|
||||
}
|
||||
|
||||
Executable
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "init.h"
|
||||
#include "init_jobs.h"
|
||||
#include "init_log.h"
|
||||
#include "init_service_manager.h"
|
||||
#include "init_utils.h"
|
||||
|
||||
static void ParseAllImports(const cJSON *root);
|
||||
|
||||
static void ParseInitCfgContents(const char *cfgName, const cJSON *root)
|
||||
{
|
||||
INIT_ERROR_CHECK(root != NULL, return, "Root is null");
|
||||
INIT_LOGI("Parse init cfg %s ", cfgName);
|
||||
|
||||
ParseAllServices(root);
|
||||
// parse jobs
|
||||
ParseAllJobs(root);
|
||||
// parse imports
|
||||
ParseAllImports(root);
|
||||
}
|
||||
|
||||
static int ParseInitCfg(const char *configFile, void *context)
|
||||
{
|
||||
UNUSED(context);
|
||||
char *fileBuf = ReadFileToBuf(configFile);
|
||||
INIT_ERROR_CHECK(fileBuf != NULL, return -1, "Failed to read file content %s", configFile);
|
||||
|
||||
cJSON *fileRoot = cJSON_Parse(fileBuf);
|
||||
INIT_ERROR_CHECK(fileRoot != NULL, free(fileBuf);
|
||||
return -1, "Failed to parse json file %s", configFile);
|
||||
|
||||
ParseInitCfgContents(configFile, fileRoot);
|
||||
cJSON_Delete(fileRoot);
|
||||
free(fileBuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ParseAllImports(const cJSON *root)
|
||||
{
|
||||
char *tmpParamValue = malloc(PARAM_VALUE_LEN_MAX + 1);
|
||||
INIT_ERROR_CHECK(tmpParamValue != 0, return, "Failed to alloc memory for param");
|
||||
|
||||
cJSON *importAttr = cJSON_GetObjectItemCaseSensitive(root, "import");
|
||||
if (!cJSON_IsArray(importAttr)) {
|
||||
free(tmpParamValue);
|
||||
return;
|
||||
}
|
||||
int importAttrSize = cJSON_GetArraySize(importAttr);
|
||||
for (int i = 0; i < importAttrSize; i++) {
|
||||
cJSON *importItem = cJSON_GetArrayItem(importAttr, i);
|
||||
if (!cJSON_IsString(importItem)) {
|
||||
INIT_LOGE("Invalid type of import item. should be string");
|
||||
break;
|
||||
}
|
||||
char *importContent = cJSON_GetStringValue(importItem);
|
||||
if (importContent == NULL) {
|
||||
INIT_LOGE("cannot get import config file");
|
||||
break;
|
||||
}
|
||||
int ret = GetParamValue(importContent, strlen(importContent), tmpParamValue, PARAM_VALUE_LEN_MAX);
|
||||
if (ret != 0) {
|
||||
INIT_LOGE("cannot get value for %s", importContent);
|
||||
continue;
|
||||
}
|
||||
INIT_LOGI("Import %s ...", tmpParamValue);
|
||||
ParseInitCfg(tmpParamValue, NULL);
|
||||
}
|
||||
free(tmpParamValue);
|
||||
return;
|
||||
}
|
||||
|
||||
void ReadConfig(void)
|
||||
{
|
||||
// parse cfg
|
||||
if (InUpdaterMode() == 0) {
|
||||
ParseInitCfg(INIT_CONFIGURATION_FILE, NULL);
|
||||
ReadFileInDir(OTHER_CFG_PATH, ".cfg", ParseInitCfg, NULL);
|
||||
} else {
|
||||
ReadFileInDir("/etc", ".cfg", ParseInitCfg, NULL);
|
||||
}
|
||||
}
|
||||
Executable
+584
@@ -0,0 +1,584 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "init_service_manager.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "cJSON.h"
|
||||
#include "init.h"
|
||||
#include "init_jobs.h"
|
||||
#include "init_log.h"
|
||||
#include "init_service_socket.h"
|
||||
#include "init_utils.h"
|
||||
#include "securec.h"
|
||||
|
||||
// All serivce processes that init will fork+exec.
|
||||
static ServiceSpace g_serviceSpace = { { &g_serviceSpace.services, &g_serviceSpace.services }, 0 };
|
||||
|
||||
#ifdef OHOS_SERVICE_DUMP
|
||||
static void DumpServiceArgs(const char *info, const ServiceArgs *args)
|
||||
{
|
||||
INIT_LOGD("\t\t%s count %d", info, args->count);
|
||||
for (int j = 0; j < args->count; j++) {
|
||||
if (args->argv[j] != NULL) {
|
||||
INIT_LOGD("\t\tinfo [%d] %s", j, args->argv[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DumpAllServices()
|
||||
{
|
||||
INIT_LOGD("Ready to dump all services:");
|
||||
INIT_LOGD("total service number: %d", g_serviceSpace.serviceCount);
|
||||
ListNode *node = g_serviceSpace.services.next;
|
||||
while (node != &g_serviceSpace.services) {
|
||||
Service *service = ListEntry(node, Service, node);
|
||||
INIT_LOGD("\tservice name: [%s]", service->name);
|
||||
INIT_LOGD("\tservice pid: [%d]", service->pid);
|
||||
INIT_LOGD("\tservice crashCnt: [%d]", service->crashCnt);
|
||||
INIT_LOGD("\tservice attribute: [%d]", service->attribute);
|
||||
INIT_LOGD("\tservice importance: [%d]", service->importance);
|
||||
INIT_LOGD("\tservice perms uID [%d]", service->servPerm.uID);
|
||||
DumpServiceArgs("path arg", &service->pathArgs);
|
||||
DumpServiceArgs("writepid file", &service->writePidArgs);
|
||||
|
||||
INIT_LOGD("\tservice perms groupId %d", service->servPerm.gIDCnt);
|
||||
for (int i = 0; i < service->servPerm.gIDCnt; i++) {
|
||||
INIT_LOGD("\t\tservice perms groupId %d", service->servPerm.gIDArray[i]);
|
||||
}
|
||||
|
||||
INIT_LOGD("\tservice perms capability %d", service->servPerm.capsCnt);
|
||||
for (int i = 0; i < service->servPerm.capsCnt; i++) {
|
||||
INIT_LOGD("\t\tservice perms capability %d", service->servPerm.caps[i]);
|
||||
}
|
||||
if (service->restartArg != NULL) {
|
||||
for (int j = 0; j < service->restartArg->cmdNum; j++) {
|
||||
CmdLine *cmd = &service->restartArg->cmds[j];
|
||||
INIT_LOGD("\t\tcmd arg: %s %s", GetCmdKey(cmd->cmdIndex), cmd->cmdContent);
|
||||
}
|
||||
}
|
||||
if (service->socketCfg != NULL) {
|
||||
INIT_LOGD("\tservice socket name: %s", service->socketCfg->name);
|
||||
INIT_LOGD("\tservice socket type: %d", service->socketCfg->type);
|
||||
INIT_LOGD("\tservice socket uid: %d", service->socketCfg->uid);
|
||||
INIT_LOGD("\tservice socket gid: %d", service->socketCfg->gid);
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
INIT_LOGD("Dump all services finished");
|
||||
}
|
||||
#endif
|
||||
|
||||
static void FreeServiceArg(ServiceArgs *arg)
|
||||
{
|
||||
if (arg != NULL) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < arg->count; ++i) {
|
||||
if (arg->argv[i] != NULL) {
|
||||
free(arg->argv[i]);
|
||||
arg->argv[i] = NULL;
|
||||
}
|
||||
}
|
||||
free(arg->argv);
|
||||
arg->argv = NULL;
|
||||
arg->count = 0;
|
||||
}
|
||||
|
||||
static void FreeServiceSocket(ServiceSocket *sockopt)
|
||||
{
|
||||
while (sockopt != NULL) {
|
||||
ServiceSocket *tmp = sockopt;
|
||||
if (tmp->sockFd >= 0) {
|
||||
close(tmp->sockFd);
|
||||
tmp->sockFd = -1;
|
||||
}
|
||||
sockopt = sockopt->next;
|
||||
free(tmp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static Service *AddService(void)
|
||||
{
|
||||
Service *service = (Service *)calloc(1, sizeof(Service));
|
||||
INIT_ERROR_CHECK(service != NULL, return NULL, "Failed to malloc for service");
|
||||
ListInit(&service->node);
|
||||
ListAddTail(&g_serviceSpace.services, &service->node);
|
||||
g_serviceSpace.serviceCount++;
|
||||
return service;
|
||||
}
|
||||
|
||||
static void ReleaseService(Service *service)
|
||||
{
|
||||
if (service == NULL) {
|
||||
return;
|
||||
}
|
||||
FreeServiceArg(&service->pathArgs);
|
||||
FreeServiceArg(&service->writePidArgs);
|
||||
|
||||
if (service->servPerm.caps != NULL) {
|
||||
free(service->servPerm.caps);
|
||||
service->servPerm.caps = NULL;
|
||||
}
|
||||
service->servPerm.capsCnt = 0;
|
||||
if (service->servPerm.gIDArray != NULL) {
|
||||
free(service->servPerm.gIDArray);
|
||||
service->servPerm.gIDArray = NULL;
|
||||
}
|
||||
service->servPerm.gIDCnt = 0;
|
||||
FreeServiceSocket(service->socketCfg);
|
||||
|
||||
if (!ListEmpty(service->node)) {
|
||||
ListRemove(&service->node);
|
||||
g_serviceSpace.serviceCount--;
|
||||
}
|
||||
free(service);
|
||||
}
|
||||
|
||||
static int GetStringItem(const cJSON *json, const char *name, char *buffer, int buffLen)
|
||||
{
|
||||
INIT_ERROR_CHECK(json != NULL, return SERVICE_FAILURE, "Invalid json for %s", name);
|
||||
char *fieldStr = cJSON_GetStringValue(cJSON_GetObjectItem(json, name));
|
||||
INIT_ERROR_CHECK(fieldStr != NULL, return SERVICE_FAILURE, "Failed to get string for %s", name);
|
||||
size_t strLen = strlen(fieldStr);
|
||||
if ((strLen == 0) || (strLen > (size_t)buffLen)) {
|
||||
INIT_LOGE("Invalid str filed %s for %s", fieldStr, name);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
return strcpy_s(buffer, buffLen, fieldStr);
|
||||
}
|
||||
|
||||
cJSON *GetArrayItem(const cJSON *fileRoot, int *arrSize, const char *arrName)
|
||||
{
|
||||
cJSON *arrItem = cJSON_GetObjectItemCaseSensitive(fileRoot, arrName);
|
||||
if (!cJSON_IsArray(arrItem)) {
|
||||
return NULL;
|
||||
}
|
||||
*arrSize = cJSON_GetArraySize(arrItem);
|
||||
if (*arrSize <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
return arrItem;
|
||||
}
|
||||
|
||||
static int GetServiceArgs(const cJSON *argJson, const char *name, int maxCount, ServiceArgs *args)
|
||||
{
|
||||
INIT_ERROR_CHECK(argJson != NULL, return SERVICE_FAILURE, "Invalid argJson");
|
||||
cJSON *obj = cJSON_GetObjectItem(argJson, name);
|
||||
INIT_CHECK(obj != NULL, return SERVICE_FAILURE);
|
||||
|
||||
int ret = cJSON_IsArray(obj);
|
||||
INIT_ERROR_CHECK(ret, return SERVICE_FAILURE, "Invalid type");
|
||||
int count = cJSON_GetArraySize(obj);
|
||||
INIT_ERROR_CHECK((count > 0) && (count < maxCount), return SERVICE_FAILURE, "Array size = %d is wrong", count);
|
||||
|
||||
args->argv = (char **)malloc((count + 1) * sizeof(char *));
|
||||
INIT_ERROR_CHECK(args->argv != NULL, return SERVICE_FAILURE, "Failed to malloc for argv");
|
||||
for (int i = 0; i < count + 1; ++i) {
|
||||
args->argv[i] = NULL;
|
||||
}
|
||||
args->count = count + 1;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
char *curParam = cJSON_GetStringValue(cJSON_GetArrayItem(obj, i));
|
||||
INIT_ERROR_CHECK(curParam != NULL, return SERVICE_FAILURE, "Invalid arg %d", i);
|
||||
INIT_ERROR_CHECK(strlen(curParam) <= MAX_ONE_ARG_LEN, return SERVICE_FAILURE, "Arg %s is tool long", curParam);
|
||||
args->argv[i] = strdup(curParam);
|
||||
INIT_ERROR_CHECK(args->argv[i] != NULL, return SERVICE_FAILURE, "Failed to dupstring %s", curParam);
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
static int GetUid(cJSON *json, uid_t *uid)
|
||||
{
|
||||
INIT_CHECK_RETURN_VALUE(json != NULL, SERVICE_SUCCESS);
|
||||
if (cJSON_IsString(json)) {
|
||||
char *str = cJSON_GetStringValue(json);
|
||||
INIT_ERROR_CHECK(str != NULL, return SERVICE_FAILURE, "Invalid str");
|
||||
*uid = DecodeUid(str);
|
||||
} else if (cJSON_IsNumber(json)) {
|
||||
*uid = (uid_t)cJSON_GetNumberValue(json);
|
||||
}
|
||||
if (*uid == (uid_t)(-1)) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
static int GetServiceGids(const cJSON *curArrItem, Service *curServ)
|
||||
{
|
||||
int gidCount = 0;
|
||||
cJSON *arrItem = cJSON_GetObjectItemCaseSensitive(curArrItem, GID_STR_IN_CFG);
|
||||
if (!cJSON_IsArray(arrItem)) {
|
||||
gidCount = 1;
|
||||
} else {
|
||||
gidCount = cJSON_GetArraySize(arrItem);
|
||||
}
|
||||
if ((gidCount == 0) || (gidCount > NGROUPS_MAX + 1)) {
|
||||
INIT_LOGE("Invalid gid count %d", gidCount);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t) * gidCount);
|
||||
INIT_ERROR_CHECK(curServ->servPerm.gIDArray != NULL, return SERVICE_FAILURE, "Failed to malloc");
|
||||
curServ->servPerm.gIDCnt = gidCount;
|
||||
|
||||
gid_t gid;
|
||||
if (!cJSON_IsArray(arrItem)) {
|
||||
int ret = GetUid(arrItem, &gid);
|
||||
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to uid");
|
||||
curServ->servPerm.gIDArray[0] = gid;
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
for (int i = 0; i < gidCount; ++i) {
|
||||
cJSON *item = cJSON_GetArrayItem(arrItem, i);
|
||||
int ret = GetUid(item, &gid);
|
||||
if (ret != 0) {
|
||||
curServ->servPerm.gIDArray[i] = 0;
|
||||
continue;
|
||||
}
|
||||
curServ->servPerm.gIDArray[i] = gid;
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
static int GetServiceAttr(const cJSON *curArrItem, Service *curServ, const char *attrName, int flag,
|
||||
int (*processAttr)(Service *curServ, const char *attrName, int value, int flag))
|
||||
{
|
||||
cJSON *filedJ = cJSON_GetObjectItem(curArrItem, attrName);
|
||||
if (filedJ == NULL) {
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
if (!cJSON_IsNumber(filedJ)) {
|
||||
INIT_LOGE("%s is null or is not a number, service name is %s", attrName, curServ->name);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
int value = (int)cJSON_GetNumberValue(filedJ);
|
||||
if (processAttr == NULL) {
|
||||
curServ->attribute &= ~flag;
|
||||
if (value == 1) {
|
||||
curServ->attribute |= flag;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return processAttr(curServ, attrName, value, flag);
|
||||
}
|
||||
|
||||
static int AddServiceSocket(cJSON *json, Service *service)
|
||||
{
|
||||
char *opt[SOCK_OPT_NUMS] = {
|
||||
NULL,
|
||||
};
|
||||
if (!cJSON_IsString(json) || !cJSON_GetStringValue(json)) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
char *sockStr = cJSON_GetStringValue(json);
|
||||
int num = SplitString(sockStr, " ", opt, SOCK_OPT_NUMS);
|
||||
if (num != SOCK_OPT_NUMS) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
if (opt[SERVICE_SOCK_NAME] == NULL || opt[SERVICE_SOCK_TYPE] == NULL || opt[SERVICE_SOCK_PERM] == NULL ||
|
||||
opt[SERVICE_SOCK_UID] == NULL || opt[SERVICE_SOCK_GID] == NULL || opt[SERVICE_SOCK_SETOPT] == NULL) {
|
||||
INIT_LOGE("Invalid socket opt");
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
ServiceSocket *sockopt = (ServiceSocket *)calloc(1, sizeof(ServiceSocket) + strlen(opt[SERVICE_SOCK_NAME]) + 1);
|
||||
INIT_INFO_CHECK(sockopt != NULL, return SERVICE_FAILURE, "Failed to malloc for socket %s", opt[SERVICE_SOCK_NAME]);
|
||||
int ret = strcpy_s(sockopt->name, strlen(opt[SERVICE_SOCK_NAME]) + 1, opt[SERVICE_SOCK_NAME]);
|
||||
INIT_INFO_CHECK(ret == 0, free(sockopt);
|
||||
return SERVICE_FAILURE, "Failed to copy socket name %s", opt[SERVICE_SOCK_NAME]);
|
||||
|
||||
sockopt->type = SOCK_SEQPACKET;
|
||||
if (strncmp(opt[SERVICE_SOCK_TYPE], "stream", strlen(opt[SERVICE_SOCK_TYPE])) == 0) {
|
||||
sockopt->type = SOCK_STREAM;
|
||||
} else if (strncmp(opt[SERVICE_SOCK_TYPE], "dgram", strlen(opt[SERVICE_SOCK_TYPE])) == 0) {
|
||||
sockopt->type = SOCK_DGRAM;
|
||||
}
|
||||
sockopt->perm = strtoul(opt[SERVICE_SOCK_PERM], 0, OCTAL_BASE);
|
||||
sockopt->uid = DecodeUid(opt[SERVICE_SOCK_UID]);
|
||||
sockopt->gid = DecodeUid(opt[SERVICE_SOCK_GID]);
|
||||
if (sockopt->uid == (uid_t)-1 || sockopt->gid == (uid_t)-1) {
|
||||
free(sockopt);
|
||||
INIT_LOGE("Invalid uid %d or gid %d", sockopt->uid, sockopt->gid);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
sockopt->passcred = false;
|
||||
if (strncmp(opt[SERVICE_SOCK_SETOPT], "passcred", strlen(opt[SERVICE_SOCK_SETOPT])) == 0) {
|
||||
sockopt->passcred = true;
|
||||
}
|
||||
sockopt->next = NULL;
|
||||
if (service->socketCfg == NULL) {
|
||||
service->socketCfg = sockopt;
|
||||
} else {
|
||||
sockopt->next = service->socketCfg->next;
|
||||
service->socketCfg->next = sockopt;
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
static int ParseServiceSocket(const cJSON *curArrItem, Service *curServ)
|
||||
{
|
||||
int sockCnt = 0;
|
||||
cJSON *filedJ = GetArrayItem(curArrItem, &sockCnt, "socket");
|
||||
INIT_CHECK(filedJ != NULL && sockCnt > 0, return SERVICE_FAILURE);
|
||||
int ret = 0;
|
||||
curServ->socketCfg = NULL;
|
||||
for (int i = 0; i < sockCnt; ++i) {
|
||||
cJSON *sockJ = cJSON_GetArrayItem(filedJ, i);
|
||||
ret = AddServiceSocket(sockJ, curServ);
|
||||
if (ret != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool IsServiceInMainStrap(Service *curServ)
|
||||
{
|
||||
char *mainServiceList[] = {
|
||||
"appspawn", "udevd", "samgr", "multimodalinput", "weston", "installs",
|
||||
"hiview", "hilogd", "hdf_devmgr", "distributedsche", "softbus_server", "foundation"
|
||||
};
|
||||
unsigned int length = ARRAY_LENGTH(mainServiceList);
|
||||
for (unsigned int i = 0; i < length; ++i) {
|
||||
if (strncmp(curServ->name, mainServiceList[i], strlen(mainServiceList[i])) == 0) {
|
||||
INIT_LOGI("%s must be main service", curServ->name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int GetDynamicService(const cJSON *curArrItem, Service *curServ)
|
||||
{
|
||||
cJSON *item = cJSON_GetObjectItem(curArrItem, "dynamic");
|
||||
if (item == NULL) {
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
INIT_ERROR_CHECK(cJSON_IsBool(item), return SERVICE_FAILURE,
|
||||
"Service : %s dynamic value only support bool.", curServ->name);
|
||||
bool isDynamic = (bool)cJSON_GetNumberValue(item);
|
||||
if (!isDynamic) {
|
||||
INIT_LOGI("Service : %s dynamic value is false, it will be started with init.", curServ->name);
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
if (IsServiceInMainStrap(curServ)) {
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
INIT_LOGI("%s is dynamic service", curServ->name);
|
||||
curServ->attribute |= SERVICE_ATTR_DYNAMIC;
|
||||
curServ->attribute |= SERVICE_ATTR_ONCE;
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
static int CheckServiceKeyName(const cJSON *curService)
|
||||
{
|
||||
char *cfgServiceKeyList[] = {
|
||||
"name", "path", "uid", "gid", "once", "importance", "caps", "disabled",
|
||||
"writepid", "critical", "socket", "console", "dynamic"
|
||||
};
|
||||
if (curService == NULL) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
cJSON *child = curService->child;
|
||||
if (child == NULL) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
while (child != NULL) {
|
||||
int i = 0;
|
||||
int keyListSize = ARRAY_LENGTH(cfgServiceKeyList);
|
||||
for (; i < keyListSize; i++) {
|
||||
if (strcmp(child->string, cfgServiceKeyList[i]) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < keyListSize) {
|
||||
child = child->next;
|
||||
} else {
|
||||
INIT_LOGE("CheckServiceKeyName, key name %s is not found. error.", child->string);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
static int ParseOneService(const cJSON *curItem, Service *service)
|
||||
{
|
||||
if (curItem == NULL || service == NULL) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
int ret = GetStringItem(curItem, "name", service->name, MAX_SERVICE_NAME);
|
||||
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get service name");
|
||||
ret = GetServiceArgs(curItem, "path", MAX_PATH_ARGS_CNT, &service->pathArgs);
|
||||
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get path for service %s", service->name);
|
||||
if ((service->pathArgs.count > 0) && IsForbidden(service->pathArgs.argv[0])) {
|
||||
INIT_LOGE("Service %s is forbidden.", service->name);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
ret = GetUid(cJSON_GetObjectItem(curItem, UID_STR_IN_CFG), &service->servPerm.uID);
|
||||
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get uid for service %s", service->name);
|
||||
ret = GetServiceGids(curItem, service);
|
||||
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get gid for service %s", service->name);
|
||||
|
||||
ret = GetServiceAttr(curItem, service, ONCE_STR_IN_CFG, SERVICE_ATTR_ONCE, NULL);
|
||||
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get once flag for service %s", service->name);
|
||||
ret = GetServiceAttr(curItem, service, IMPORTANT_STR_IN_CFG, SERVICE_ATTR_IMPORTANT, SetImportantValue);
|
||||
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get import flag for service %s", service->name);
|
||||
ret = GetServiceAttr(curItem, service, CRITICAL_STR_IN_CFG, SERVICE_ATTR_CRITICAL, NULL);
|
||||
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get critical flag for service %s", service->name);
|
||||
ret = GetServiceAttr(curItem, service, DISABLED_STR_IN_CFG, SERVICE_ATTR_DISABLED, NULL);
|
||||
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get disabled flag for service %s", service->name);
|
||||
ret = GetServiceAttr(curItem, service, CONSOLE_STR_IN_CFG, SERVICE_ATTR_CONSOLE, NULL);
|
||||
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get console for service %s", service->name);
|
||||
|
||||
ret = GetServiceArgs(curItem, "writepid", MAX_WRITEPID_FILES, &service->writePidArgs);
|
||||
INIT_CHECK_ONLY_ELOG(ret == 0, "No writepid arg for service %s", service->name);
|
||||
ret = GetServiceCaps(curItem, service);
|
||||
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get caps for service %s", service->name);
|
||||
ret = GetDynamicService(curItem, service);
|
||||
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get dynamic flag for service %s", service->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ParseAllServices(const cJSON *fileRoot)
|
||||
{
|
||||
int servArrSize = 0;
|
||||
cJSON *serviceArr = GetArrayItem(fileRoot, &servArrSize, SERVICES_ARR_NAME_IN_JSON);
|
||||
INIT_INFO_CHECK(serviceArr != NULL, return, "This config does not contain service array.");
|
||||
|
||||
INIT_ERROR_CHECK(servArrSize <= MAX_SERVICES_CNT_IN_FILE, return,
|
||||
"Too many services[cnt %d] detected, should not exceed %d.",
|
||||
servArrSize, MAX_SERVICES_CNT_IN_FILE);
|
||||
|
||||
Service tmpService = {};
|
||||
for (int i = 0; i < servArrSize; ++i) {
|
||||
cJSON *curItem = cJSON_GetArrayItem(serviceArr, i);
|
||||
int ret = GetStringItem(curItem, "name", tmpService.name, MAX_SERVICE_NAME);
|
||||
if (ret != 0) {
|
||||
INIT_LOGE("Failed to get service name %s", tmpService.name);
|
||||
continue;
|
||||
}
|
||||
if (CheckServiceKeyName(curItem) != SERVICE_SUCCESS) { // invalid service
|
||||
INIT_LOGE("Invalid service name %s", tmpService.name);
|
||||
continue;
|
||||
}
|
||||
Service *service = GetServiceByName(tmpService.name);
|
||||
if (service != NULL) {
|
||||
INIT_LOGE("Service name %s has been exist", tmpService.name);
|
||||
continue;
|
||||
}
|
||||
service = AddService();
|
||||
if (service == NULL) {
|
||||
INIT_LOGE("Failed to create service name %s", tmpService.name);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = ParseOneService(curItem, service);
|
||||
if (ret != SERVICE_SUCCESS) {
|
||||
ReleaseService(service);
|
||||
continue;
|
||||
}
|
||||
ret = ParseServiceSocket(curItem, service);
|
||||
if (ret != SERVICE_SUCCESS) {
|
||||
FreeServiceSocket(service->socketCfg);
|
||||
service->socketCfg = NULL;
|
||||
}
|
||||
ret = GetCmdLinesFromJson(cJSON_GetObjectItem(curItem, "onrestart"), &service->restartArg);
|
||||
if (ret != SERVICE_SUCCESS) {
|
||||
service->restartArg = NULL;
|
||||
}
|
||||
INIT_LOGD("service[%d] name=%s, uid=%d, critical=%d, disabled=%d",
|
||||
i, service->name, service->servPerm.uID,
|
||||
(service->attribute & SERVICE_ATTR_CRITICAL) ? 1 : 0,
|
||||
(service->attribute & SERVICE_ATTR_DISABLED) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
void StartServiceByName(const char *servName, bool checkDynamic)
|
||||
{
|
||||
Service *service = GetServiceByName(servName);
|
||||
INIT_ERROR_CHECK(service != NULL, return, "Cannot find service %s.", servName);
|
||||
|
||||
if (checkDynamic && (service->attribute & SERVICE_ATTR_DYNAMIC)) {
|
||||
INIT_LOGI("%s is dynamic service.", servName);
|
||||
return;
|
||||
}
|
||||
if (ServiceStart(service) != SERVICE_SUCCESS) {
|
||||
INIT_LOGE("Service %s start failed!", servName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void StopServiceByName(const char *servName)
|
||||
{
|
||||
Service *service = GetServiceByName(servName);
|
||||
INIT_ERROR_CHECK(service != NULL, return, "Cannot find service %s.", servName);
|
||||
|
||||
if (ServiceStop(service) != SERVICE_SUCCESS) {
|
||||
INIT_LOGE("Service %s start failed!", servName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void StopAllServices(int flags)
|
||||
{
|
||||
ListNode *node = g_serviceSpace.services.next;
|
||||
while (node != &g_serviceSpace.services) {
|
||||
Service *service = ListEntry(node, Service, node);
|
||||
service->attribute |= flags;
|
||||
int ret = ServiceStop(service);
|
||||
if (ret != SERVICE_SUCCESS) {
|
||||
INIT_LOGE("Service %s stop failed!", service->name);
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
||||
Service *GetServiceByPid(pid_t pid)
|
||||
{
|
||||
ListNode *node = g_serviceSpace.services.next;
|
||||
while (node != &g_serviceSpace.services) {
|
||||
Service *service = ListEntry(node, Service, node);
|
||||
if (service->pid == pid) {
|
||||
return service;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Service *GetServiceByName(const char *servName)
|
||||
{
|
||||
ListNode *node = g_serviceSpace.services.next;
|
||||
while (node != &g_serviceSpace.services) {
|
||||
Service *service = ListEntry(node, Service, node);
|
||||
if (strcmp(service->name, servName) == 0) {
|
||||
return service;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
Executable
+149
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "init_service_socket.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include "init_log.h"
|
||||
#include "init_service.h"
|
||||
#include "securec.h"
|
||||
|
||||
#define HOS_SOCKET_DIR "/dev/unix/socket"
|
||||
#define HOS_SOCKET_ENV_PREFIX "OHOS_SOCKET_"
|
||||
#define MAX_SOCKET_ENV_PREFIX_LEN 64
|
||||
#define MAX_SOCKET_FD_LEN 16
|
||||
|
||||
static int GetSocketAddr(struct sockaddr_un *addr, const char *name)
|
||||
{
|
||||
bzero(addr, sizeof(struct sockaddr_un));
|
||||
addr->sun_family = AF_UNIX;
|
||||
size_t addrLen = sizeof(addr->sun_path);
|
||||
int ret = snprintf_s(addr->sun_path, addrLen, addrLen - 1, HOS_SOCKET_DIR "/%s", name);
|
||||
INIT_ERROR_CHECK(ret >= 0, return -1, "Failed to format addr %s", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int CreateSocket(ServiceSocket *sockopt)
|
||||
{
|
||||
INIT_ERROR_CHECK(sockopt != NULL, return SERVICE_FAILURE, "Invalid socket opt");
|
||||
if (sockopt->sockFd >= 0) {
|
||||
close(sockopt->sockFd);
|
||||
sockopt->sockFd = -1;
|
||||
}
|
||||
sockopt->sockFd = socket(PF_UNIX, sockopt->type, 0);
|
||||
INIT_ERROR_CHECK(sockopt->sockFd >= 0, return -1, "socket fail %d ", errno);
|
||||
|
||||
struct sockaddr_un addr;
|
||||
int ret = GetSocketAddr(&addr, sockopt->name);
|
||||
INIT_ERROR_CHECK(ret == 0, return -1, "Failed to format addr %s", sockopt->name);
|
||||
|
||||
do {
|
||||
ret = -1;
|
||||
if (access(addr.sun_path, F_OK)) {
|
||||
INIT_LOGI("%s already exist, remove it", addr.sun_path);
|
||||
unlink(addr.sun_path);
|
||||
}
|
||||
if (sockopt->passcred) {
|
||||
int on = 1;
|
||||
if (setsockopt(sockopt->sockFd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bind(sockopt->sockFd, (struct sockaddr *)&addr, sizeof(addr))) {
|
||||
INIT_LOGE("Create socket for service %s failed: %d", sockopt->name, errno);
|
||||
break;
|
||||
}
|
||||
if (lchown(addr.sun_path, sockopt->uid, sockopt->gid)) {
|
||||
INIT_LOGE("lchown fail %d ", errno);
|
||||
break;
|
||||
}
|
||||
if (fchmodat(AT_FDCWD, addr.sun_path, sockopt->perm, AT_SYMLINK_NOFOLLOW)) {
|
||||
INIT_LOGE("fchmodat fail %d ", errno);
|
||||
break;
|
||||
}
|
||||
ret = 0;
|
||||
} while (0);
|
||||
if (ret != 0) {
|
||||
close(sockopt->sockFd);
|
||||
unlink(addr.sun_path);
|
||||
return -1;
|
||||
}
|
||||
INIT_LOGI("CreateSocket %s success", sockopt->name);
|
||||
return sockopt->sockFd;
|
||||
}
|
||||
|
||||
static int SetSocketEnv(int fd, const char *name)
|
||||
{
|
||||
INIT_ERROR_CHECK(name != NULL, return SERVICE_FAILURE, "Invalid name");
|
||||
char pubName[MAX_SOCKET_ENV_PREFIX_LEN] = { 0 };
|
||||
char val[MAX_SOCKET_FD_LEN] = { 0 };
|
||||
if (snprintf_s(pubName, sizeof(pubName), sizeof(pubName) - 1, HOS_SOCKET_ENV_PREFIX "%s", name) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (snprintf_s(val, sizeof(val), sizeof(val) - 1, "%d", fd) < 0) {
|
||||
return -1;
|
||||
}
|
||||
int ret = setenv(pubName, val, 1);
|
||||
if (ret < 0) {
|
||||
INIT_LOGE("setenv fail %d ", errno);
|
||||
return -1;
|
||||
}
|
||||
fcntl(fd, F_SETFD, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CreateServiceSocket(ServiceSocket *sockopt)
|
||||
{
|
||||
INIT_CHECK(sockopt != NULL, return 0);
|
||||
ServiceSocket *tmpSock = sockopt;
|
||||
while (tmpSock != NULL) {
|
||||
int fd = CreateSocket(tmpSock);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
int ret = SetSocketEnv(fd, tmpSock->name);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
tmpSock = tmpSock->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CloseServiceSocket(ServiceSocket *sockopt)
|
||||
{
|
||||
INIT_CHECK(sockopt != NULL, return);
|
||||
struct sockaddr_un addr;
|
||||
ServiceSocket *tmpSock = sockopt;
|
||||
while (tmpSock != NULL) {
|
||||
if (sockopt->sockFd >= 0) {
|
||||
close(sockopt->sockFd);
|
||||
sockopt->sockFd = -1;
|
||||
}
|
||||
if (GetSocketAddr(&addr, sockopt->name) == 0) {
|
||||
unlink(addr.sun_path);
|
||||
}
|
||||
tmpSock = tmpSock->next;
|
||||
}
|
||||
return;
|
||||
}
|
||||
Executable
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "init.h"
|
||||
#include "init_log.h"
|
||||
#include "init_jobs.h"
|
||||
#ifndef __LINUX__
|
||||
#include "init_stage.h"
|
||||
#endif
|
||||
#include "parameter.h"
|
||||
#include "securec.h"
|
||||
|
||||
static void PrintSysInfo(void)
|
||||
{
|
||||
const char *sysInfo = GetVersionId();
|
||||
if (sysInfo != NULL) {
|
||||
INIT_LOGE("%s", sysInfo);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void SystemInit(void)
|
||||
{
|
||||
SignalInit();
|
||||
}
|
||||
|
||||
void LogInit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SystemPrepare(void)
|
||||
{
|
||||
PrintSysInfo();
|
||||
}
|
||||
|
||||
void SystemConfig(void)
|
||||
{
|
||||
// read config
|
||||
ReadConfig();
|
||||
|
||||
// dump config
|
||||
#ifdef OHOS_SERVICE_DUMP
|
||||
DumpAllServices();
|
||||
#endif
|
||||
|
||||
// execute init
|
||||
DoJob("pre-init");
|
||||
#ifndef __LINUX__
|
||||
TriggerStage(EVENT1, EVENT1_WAITTIME, QS_STAGE1);
|
||||
#endif
|
||||
|
||||
DoJob("init");
|
||||
#ifndef __LINUX__
|
||||
TriggerStage(EVENT2, EVENT2_WAITTIME, QS_STAGE2);
|
||||
#endif
|
||||
|
||||
DoJob("post-init");
|
||||
#ifndef __LINUX__
|
||||
TriggerStage(EVENT3, EVENT3_WAITTIME, QS_STAGE3);
|
||||
InitStageFinished();
|
||||
#endif
|
||||
ReleaseAllJobs();
|
||||
}
|
||||
|
||||
void SystemRun(void)
|
||||
{
|
||||
while (1) {
|
||||
// pause only returns when a signal was caught and the signal-catching function returned.
|
||||
// pause only returns -1, no need to process the return value.
|
||||
(void)pause();
|
||||
}
|
||||
}
|
||||
Executable
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "init.h"
|
||||
#include "init_cmds.h"
|
||||
#include "init_log.h"
|
||||
#include "init_utils.h"
|
||||
#include "securec.h"
|
||||
|
||||
int GetParamValue(const char *symValue, unsigned int symLen, char *paramValue, unsigned int paramLen)
|
||||
{
|
||||
return (strncpy_s(paramValue, paramLen, symValue, symLen) == EOK) ? 0 : -1;
|
||||
}
|
||||
|
||||
static void DoExec(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(ctx);
|
||||
// format: exec /xxx/xxx/xxx xxx
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
INIT_LOGE("DoExec: failed to fork child process to exec \"%s\"", cmdContent);
|
||||
return;
|
||||
}
|
||||
if (pid == 0) {
|
||||
struct CmdArgs *subCtx = GetCmdArg(cmdContent, " ", SUPPORT_MAX_ARG_FOR_EXEC);
|
||||
if (subCtx == NULL || subCtx->argv[0] == NULL) {
|
||||
INIT_LOGE("DoExec: invalid arguments :%s", cmdContent);
|
||||
_exit(0x7f);
|
||||
}
|
||||
int ret = execve(subCtx->argv[0], subCtx->argv, NULL);
|
||||
if (ret == -1) {
|
||||
INIT_LOGE("DoExec: execute \"%s\" failed: %d.", cmdContent, errno);
|
||||
}
|
||||
FreeCmdArg(subCtx);
|
||||
_exit(0x7f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static const struct CmdTable g_cmdTable[] = { { "exec ", 1, 10, DoExec } };
|
||||
|
||||
const struct CmdTable *GetCmdTable(int *number)
|
||||
{
|
||||
*number = (int)ARRAY_LENGTH(g_cmdTable);
|
||||
return g_cmdTable;
|
||||
}
|
||||
Regular → Executable
+32
-55
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2020-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
|
||||
@@ -12,7 +12,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init_jobs.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -25,28 +24,31 @@
|
||||
|
||||
#define JOBS_ARR_NAME_IN_JSON "jobs"
|
||||
#define CMDS_ARR_NAME_IN_JSON "cmds"
|
||||
#define MAX_JOBS_COUNT 100
|
||||
#define MAX_JOBS_COUNT 100
|
||||
|
||||
static Job* g_jobs = NULL;
|
||||
static Job *g_jobs = NULL;
|
||||
static int g_jobCnt = 0;
|
||||
|
||||
void DumpAllJobs(void)
|
||||
{
|
||||
INIT_LOGD("Ready to dump all jobs:");
|
||||
INIT_LOGD("Start to dump all jobs...");
|
||||
for (int i = 0; i < g_jobCnt; i++) {
|
||||
INIT_LOGD("\tjob name: %s", g_jobs[i].name);
|
||||
if (g_jobs[i].cmdLines == NULL) {
|
||||
continue;
|
||||
}
|
||||
INIT_LOGD("\tlist all commands:");
|
||||
for (int j = 0; j < g_jobs[i].cmdLinesCnt; j++) {
|
||||
INIT_LOGD("\t\tcommand name : %s, command options: %s",
|
||||
g_jobs[i].cmdLines[j].name, g_jobs[i].cmdLines[j].cmdContent);
|
||||
for (int j = 0; j < g_jobs[i].cmdLines->cmdNum; j++) {
|
||||
CmdLine *cmd = &g_jobs[i].cmdLines->cmds[j];
|
||||
INIT_LOGD("\t\tcommand: %s %s", GetCmdKey(cmd->cmdIndex), cmd->cmdContent);
|
||||
}
|
||||
}
|
||||
INIT_LOGD("To dump all jobs finished");
|
||||
INIT_LOGD("Finish dump all jobs");
|
||||
}
|
||||
|
||||
static int GetJobName(const cJSON* jobItem, Job* resJob)
|
||||
static int GetJobName(const cJSON *jobItem, Job *resJob)
|
||||
{
|
||||
char* jobNameStr = cJSON_GetStringValue(cJSON_GetObjectItem(jobItem, "name"));
|
||||
char *jobNameStr = cJSON_GetStringValue(cJSON_GetObjectItem(jobItem, "name"));
|
||||
if (jobNameStr == NULL) {
|
||||
return 0;
|
||||
}
|
||||
@@ -59,7 +61,7 @@ static int GetJobName(const cJSON* jobItem, Job* resJob)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ParseJob(const cJSON* jobItem, Job* resJob)
|
||||
static void ParseJob(const cJSON *jobItem, Job *resJob)
|
||||
{
|
||||
if (!GetJobName(jobItem, resJob)) {
|
||||
INIT_LOGE("get JobName failed");
|
||||
@@ -67,52 +69,27 @@ static void ParseJob(const cJSON* jobItem, Job* resJob)
|
||||
return;
|
||||
}
|
||||
|
||||
cJSON* cmdsItem = cJSON_GetObjectItem(jobItem, CMDS_ARR_NAME_IN_JSON);
|
||||
cJSON *cmdsItem = cJSON_GetObjectItem(jobItem, CMDS_ARR_NAME_IN_JSON);
|
||||
if (!cJSON_IsArray(cmdsItem)) {
|
||||
INIT_LOGE("job %s is not an arrary", resJob->name);
|
||||
return;
|
||||
}
|
||||
|
||||
int cmdLinesCnt = cJSON_GetArraySize(cmdsItem);
|
||||
if (cmdLinesCnt <= 0) { // empty job, no cmd
|
||||
INIT_LOGE("empty job \"%s\"", resJob->name);
|
||||
int ret = GetCmdLinesFromJson(cmdsItem, &resJob->cmdLines);
|
||||
if (ret != 0) {
|
||||
INIT_LOGE("ParseJob, faild to get cmds for job!");
|
||||
return;
|
||||
}
|
||||
|
||||
INIT_LOGD("job = %s, cmdLineCnt = %d", resJob->name, cmdLinesCnt);
|
||||
if (cmdLinesCnt > MAX_CMD_CNT_IN_ONE_JOB) {
|
||||
INIT_LOGE("ParseAllJobs, too many cmds[cnt %d] in one job, it should not exceed %d.",
|
||||
cmdLinesCnt, MAX_CMD_CNT_IN_ONE_JOB);
|
||||
return;
|
||||
}
|
||||
|
||||
resJob->cmdLines = (CmdLine*)malloc(cmdLinesCnt * sizeof(CmdLine));
|
||||
if (resJob->cmdLines == NULL) {
|
||||
INIT_LOGE("allocate memory for command line failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (memset_s(resJob->cmdLines, cmdLinesCnt * sizeof(CmdLine), 0, cmdLinesCnt * sizeof(CmdLine)) != EOK) {
|
||||
free(resJob->cmdLines);
|
||||
resJob->cmdLines = NULL;
|
||||
return;
|
||||
}
|
||||
resJob->cmdLinesCnt = cmdLinesCnt;
|
||||
|
||||
for (int i = 0; i < cmdLinesCnt; ++i) {
|
||||
char* cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdsItem, i));
|
||||
ParseCmdLine(cmdLineStr, &(resJob->cmdLines[i]));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void ParseAllJobs(const cJSON* fileRoot)
|
||||
void ParseAllJobs(const cJSON *fileRoot)
|
||||
{
|
||||
if (fileRoot == NULL) {
|
||||
INIT_LOGE("ParseAllJobs, input fileRoot is NULL!");
|
||||
return;
|
||||
}
|
||||
|
||||
cJSON* jobArr = cJSON_GetObjectItemCaseSensitive(fileRoot, JOBS_ARR_NAME_IN_JSON);
|
||||
cJSON *jobArr = cJSON_GetObjectItemCaseSensitive(fileRoot, JOBS_ARR_NAME_IN_JSON);
|
||||
if (!cJSON_IsArray(jobArr)) {
|
||||
INIT_LOGE("ParseAllJobs, job item is not array!");
|
||||
return;
|
||||
@@ -125,13 +102,13 @@ void ParseAllJobs(const cJSON* fileRoot)
|
||||
return;
|
||||
}
|
||||
|
||||
Job* retJobs = (Job*)realloc(g_jobs, sizeof(Job) * (g_jobCnt + jobArrSize));
|
||||
Job *retJobs = (Job *)realloc(g_jobs, sizeof(Job) * (g_jobCnt + jobArrSize));
|
||||
if (retJobs == NULL) {
|
||||
INIT_LOGE("ParseAllJobs, malloc failed! job arrSize %d.", jobArrSize);
|
||||
return;
|
||||
}
|
||||
|
||||
Job* tmp = retJobs + g_jobCnt;
|
||||
Job *tmp = retJobs + g_jobCnt;
|
||||
if (memset_s(tmp, sizeof(Job) * jobArrSize, 0, sizeof(Job) * jobArrSize) != EOK) {
|
||||
INIT_LOGE("ParseAllJobs, memset_s failed.");
|
||||
free(retJobs);
|
||||
@@ -140,14 +117,14 @@ void ParseAllJobs(const cJSON* fileRoot)
|
||||
}
|
||||
|
||||
for (int i = 0; i < jobArrSize; ++i) {
|
||||
cJSON* jobItem = cJSON_GetArrayItem(jobArr, i);
|
||||
cJSON *jobItem = cJSON_GetArrayItem(jobArr, i);
|
||||
ParseJob(jobItem, &(tmp[i]));
|
||||
}
|
||||
g_jobs = retJobs;
|
||||
g_jobCnt += jobArrSize;
|
||||
}
|
||||
|
||||
void DoJob(const char* jobName)
|
||||
void DoJob(const char *jobName)
|
||||
{
|
||||
if (jobName == NULL) {
|
||||
INIT_LOGE("DoJob, input jobName NULL!");
|
||||
@@ -157,9 +134,12 @@ void DoJob(const char* jobName)
|
||||
INIT_LOGD("Call job with name %s", jobName);
|
||||
for (int i = 0; i < g_jobCnt; ++i) {
|
||||
if (strncmp(jobName, g_jobs[i].name, strlen(g_jobs[i].name)) == 0) {
|
||||
CmdLine* cmdLines = g_jobs[i].cmdLines;
|
||||
for (int j = 0; j < g_jobs[i].cmdLinesCnt; ++j) {
|
||||
DoCmd(&(cmdLines[j]));
|
||||
CmdLines *cmdLines = g_jobs[i].cmdLines;
|
||||
if (cmdLines == NULL) {
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < cmdLines->cmdNum; ++j) {
|
||||
DoCmdByIndex(cmdLines->cmds[j].cmdIndex, cmdLines->cmds[j].cmdContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -174,13 +154,10 @@ void ReleaseAllJobs(void)
|
||||
for (int i = 0; i < g_jobCnt; ++i) {
|
||||
if (g_jobs[i].cmdLines != NULL) {
|
||||
free(g_jobs[i].cmdLines);
|
||||
g_jobs[i].cmdLines = NULL;
|
||||
g_jobs[i].cmdLinesCnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
free(g_jobs);
|
||||
g_jobs = NULL;
|
||||
g_jobCnt = 0;
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/reboot.h>
|
||||
|
||||
#include "init.h"
|
||||
#include "init_log.h"
|
||||
|
||||
void ExecReboot(const char *value)
|
||||
{
|
||||
UNUSED(value);
|
||||
int ret = reboot(RB_AUTOBOOT);
|
||||
if (ret != 0) {
|
||||
INIT_LOGE("reboot failed! syscall ret %d, err %d.", ret, errno);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Executable
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "init_service.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "init.h"
|
||||
#include "init_log.h"
|
||||
#include "init_service_manager.h"
|
||||
#include "securec.h"
|
||||
|
||||
void NotifyServiceChange(const char *serviceName, const char *change)
|
||||
{
|
||||
UNUSED(serviceName);
|
||||
UNUSED(change);
|
||||
}
|
||||
|
||||
int IsForbidden(const char *fieldStr)
|
||||
{
|
||||
size_t fieldLen = strlen(fieldStr);
|
||||
size_t forbidStrLen = strlen(BIN_SH_NOT_ALLOWED);
|
||||
if (fieldLen == forbidStrLen) {
|
||||
if (strncmp(fieldStr, BIN_SH_NOT_ALLOWED, fieldLen) == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
} else if (fieldLen > forbidStrLen) {
|
||||
// "/bin/shxxxx" is valid but "/bin/sh xxxx" is invalid
|
||||
if (strncmp(fieldStr, BIN_SH_NOT_ALLOWED, forbidStrLen) == 0) {
|
||||
if (fieldStr[forbidStrLen] == ' ') {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int SetImportantValue(Service *service, const char *attrName, int value, int flag)
|
||||
{
|
||||
UNUSED(attrName);
|
||||
UNUSED(flag);
|
||||
INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Set service attr failed! null ptr.");
|
||||
if (value != 0) {
|
||||
service->attribute |= SERVICE_ATTR_IMPORTANT;
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
int ServiceExec(const Service *service)
|
||||
{
|
||||
INIT_ERROR_CHECK(service != NULL && service->pathArgs.count > 0,
|
||||
return SERVICE_FAILURE, "Exec service failed! null ptr.");
|
||||
INIT_LOGI("service->name is %s ", service->name);
|
||||
char *env[] = { "LD_LIBRARY_PATH=/storage/app/libs", NULL };
|
||||
if (execve(service->pathArgs.argv[0], service->pathArgs.argv, env) != 0) {
|
||||
INIT_LOGE("service %s execve failed! err %d.", service->name, errno);
|
||||
return errno;
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
Executable
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "init_adapter.h"
|
||||
#include "init_log.h"
|
||||
#include "init_service_manager.h"
|
||||
|
||||
void ReapService(Service *service)
|
||||
{
|
||||
if (service == NULL) {
|
||||
return;
|
||||
}
|
||||
if (service->attribute & SERVICE_ATTR_IMPORTANT) {
|
||||
// important process exit, need to reboot system
|
||||
service->pid = -1;
|
||||
StopAllServices(0);
|
||||
RebootSystem();
|
||||
}
|
||||
ServiceReap(service);
|
||||
}
|
||||
|
||||
static void SigHandler(int sig)
|
||||
{
|
||||
switch (sig) {
|
||||
case SIGCHLD: {
|
||||
pid_t sigPID;
|
||||
int procStat = 0;
|
||||
while (1) {
|
||||
sigPID = waitpid(-1, &procStat, WNOHANG);
|
||||
if (sigPID <= 0) {
|
||||
break;
|
||||
}
|
||||
CheckWaitPid(sigPID);
|
||||
ReapService(GetServiceByPid(sigPID));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SIGTERM: {
|
||||
StopAllServices(0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SignalInit(void)
|
||||
{
|
||||
struct sigaction act;
|
||||
act.sa_handler = SigHandler;
|
||||
act.sa_flags = SA_RESTART;
|
||||
(void)sigfillset(&act.sa_mask);
|
||||
|
||||
sigaction(SIGCHLD, &act, NULL);
|
||||
sigaction(SIGTERM, &act, NULL);
|
||||
}
|
||||
Regular → Executable
+23
-21
@@ -12,26 +12,28 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "init.h"
|
||||
#include "init_log.h"
|
||||
|
||||
#ifndef BASE_STARTUP_INITLITE_READ_CFG_H
|
||||
#define BASE_STARTUP_INITLITE_READ_CFG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
#define INIT_CONFIGURATION_FILE "/etc/init.cfg"
|
||||
#define MAX_PATH_ARGS_CNT 20
|
||||
#define MAX_ONE_ARG_LEN 200 // max length of one param/path
|
||||
|
||||
void InitReadCfg();
|
||||
void ParseInitCfg(const char *configFile);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
static const pid_t INIT_PROCESS_PID = 1;
|
||||
int main(int argc, char* const argv[])
|
||||
{
|
||||
int isSecondStage = 0;
|
||||
if (argc == 2 && (strcmp(argv[1], "--second-stage") == 0)) {
|
||||
isSecondStage = 1;
|
||||
}
|
||||
if (getpid() != INIT_PROCESS_PID) {
|
||||
INIT_LOGE("Process id error %d!", getpid());
|
||||
return 0;
|
||||
}
|
||||
LogInit();
|
||||
if (isSecondStage == 0) {
|
||||
SystemPrepare();
|
||||
}
|
||||
SystemInit();
|
||||
SystemExecuteRcs();
|
||||
SystemConfig();
|
||||
SystemRun();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // BASE_STARTUP_INITLITE_READ_CFG_H
|
||||
Regular → Executable
+3
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2020-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
|
||||
@@ -12,14 +12,15 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "device.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/major.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
#include "init_log.h"
|
||||
|
||||
#define DEFAULT_RW_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
|
||||
@@ -62,9 +63,6 @@ void MountBasicFs(void)
|
||||
|
||||
void CreateDeviceNode(void)
|
||||
{
|
||||
if (mknod("/dev/kmsg", S_IFCHR | DEFAULT_NO_AUTHORITY_MODE, makedev(MEM_MAJOR, DEV_KMSG_MINOR)) != 0) {
|
||||
INIT_LOGE("Create /dev/kmsg device node failed. %s", strerror(errno));
|
||||
}
|
||||
if (mknod("/dev/null", S_IFCHR | DEFAULT_RW_MODE, makedev(MEM_MAJOR, DEV_NULL_MINOR)) != 0) {
|
||||
INIT_LOGE("Create /dev/null device node failed. %s", strerror(errno));
|
||||
}
|
||||
Executable
+143
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "init.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/major.h>
|
||||
|
||||
#include "device.h"
|
||||
#include "init_log.h"
|
||||
#include "init_mount.h"
|
||||
#include "init_param.h"
|
||||
#include "init_utils.h"
|
||||
#include "securec.h"
|
||||
#include "switch_root.h"
|
||||
|
||||
void SystemInit(void)
|
||||
{
|
||||
SignalInit();
|
||||
MakeDirRecursive("/dev/unix/socket", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
||||
}
|
||||
|
||||
void LogInit(void)
|
||||
{
|
||||
CloseStdio();
|
||||
int ret = mknod("/dev/kmsg", S_IFCHR | S_IWUSR | S_IRUSR,
|
||||
makedev(MEM_MAJOR, DEV_KMSG_MINOR));
|
||||
if (ret == 0) {
|
||||
OpenLogDevice();
|
||||
}
|
||||
}
|
||||
|
||||
static pid_t StartUeventd(void)
|
||||
{
|
||||
char *const argv[] = {
|
||||
"/bin/ueventd",
|
||||
NULL,
|
||||
};
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
INIT_LOGE("Failed to fork child process");
|
||||
}
|
||||
if (pid == 0) {
|
||||
if (execv(argv[0], argv) != 0) {
|
||||
INIT_LOGE("service %s execve failed! err %d.", argv[0], errno);
|
||||
}
|
||||
_exit(0x7f); // 0x7f: user specified
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
|
||||
static void StartInitSecondStage(void)
|
||||
{
|
||||
pid_t ueventPid = StartUeventd();
|
||||
if (ueventPid < 0) {
|
||||
INIT_LOGE("Failed to start ueventd");
|
||||
abort();
|
||||
}
|
||||
if (MountRequriedPartitions() < 0) {
|
||||
// If mount required partitions failure.
|
||||
// There is no necessary to continue.
|
||||
// Just abort
|
||||
INIT_LOGE("Mount requried partitions failed");
|
||||
abort();
|
||||
}
|
||||
// Kill ueventd, because init second stage will start it again.
|
||||
(void)kill(ueventPid, SIGKILL);
|
||||
// The init process in ramdisk has done its job.
|
||||
// It's ready to switch to system partition.
|
||||
// The system partition mounted in first stage to /usr
|
||||
// Because the directory /system is in use. we cannot use it.
|
||||
// After switch root. /usr will become new root.
|
||||
SwitchRoot("/usr");
|
||||
// Execute init second stage
|
||||
char *const args[] = {
|
||||
"/bin/init",
|
||||
"--second-stage",
|
||||
NULL,
|
||||
};
|
||||
if (execv("/bin/init", args) != 0) {
|
||||
INIT_LOGE("Failed to exec \"/bin/init\", err = %d", errno);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void SystemPrepare(void)
|
||||
{
|
||||
MountBasicFs();
|
||||
// Make sure init log always output to /dev/kmsg.
|
||||
EnableDevKmsg();
|
||||
CreateDeviceNode();
|
||||
// Only ohos normal system support
|
||||
// two stages of init.
|
||||
// If we are in updater mode, only one stage of init,
|
||||
if (InUpdaterMode() == 0) {
|
||||
StartInitSecondStage();
|
||||
}
|
||||
}
|
||||
|
||||
void SystemConfig(void)
|
||||
{
|
||||
InitParamService();
|
||||
// parse parameters
|
||||
LoadDefaultParams("/system/etc/param/ohos_const", LOAD_PARAM_NORMAL);
|
||||
LoadDefaultParams("/vendor/etc/param", LOAD_PARAM_NORMAL);
|
||||
LoadDefaultParams("/system/etc/param", LOAD_PARAM_ONLY_ADD);
|
||||
|
||||
// read config
|
||||
ReadConfig();
|
||||
INIT_LOGI("Parse init config file done.");
|
||||
|
||||
// dump config
|
||||
#ifdef OHOS_SERVICE_DUMP
|
||||
DumpAllServices();
|
||||
DumpParametersAndTriggers();
|
||||
#endif
|
||||
|
||||
// execute init
|
||||
PostTrigger(EVENT_TRIGGER_BOOT, "pre-init", strlen("pre-init"));
|
||||
PostTrigger(EVENT_TRIGGER_BOOT, "init", strlen("init"));
|
||||
PostTrigger(EVENT_TRIGGER_BOOT, "post-init", strlen("post-init"));
|
||||
}
|
||||
|
||||
void SystemRun(void)
|
||||
{
|
||||
StartParamService();
|
||||
}
|
||||
Executable
+322
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "init_cmds.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/module.h>
|
||||
#include <net/if.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "init.h"
|
||||
#include "init_jobs.h"
|
||||
#include "init_log.h"
|
||||
#include "init_param.h"
|
||||
#include "init_service_manager.h"
|
||||
#include "init_utils.h"
|
||||
#include "fs_manager/fs_manager.h"
|
||||
#include "securec.h"
|
||||
|
||||
int GetParamValue(const char *symValue, unsigned int symLen, char *paramValue, unsigned int paramLen)
|
||||
{
|
||||
if ((symValue == NULL) || (paramValue == NULL) || (paramLen == 0)) {
|
||||
return -1;
|
||||
}
|
||||
char tmpName[PARAM_NAME_LEN_MAX] = { 0 };
|
||||
int ret = 0;
|
||||
uint32_t curr = 0;
|
||||
char *start = (char *)symValue;
|
||||
char *end = (char *)symValue + symLen;
|
||||
do {
|
||||
char *begin = strchr(start, '$');
|
||||
if (begin == NULL || begin >= end) { // not has '$' copy the original string
|
||||
ret = strncpy_s(paramValue + curr, paramLen - curr, start, symLen);
|
||||
INIT_ERROR_CHECK(ret == EOK, return -1, "Failed to copy start %s", start);
|
||||
break;
|
||||
} else {
|
||||
ret = memcpy_s(paramValue + curr, paramLen - curr, start, begin - start);
|
||||
INIT_ERROR_CHECK(ret == 0, return -1, "Failed to copy first value %s", symValue);
|
||||
curr += begin - start;
|
||||
}
|
||||
while (*begin != '{') {
|
||||
begin++;
|
||||
}
|
||||
begin++;
|
||||
char *left = strchr(begin, '}');
|
||||
if (left == NULL) {
|
||||
return -1;
|
||||
}
|
||||
// copy param name
|
||||
ret = strncpy_s(tmpName, PARAM_NAME_LEN_MAX, begin, left - begin);
|
||||
INIT_ERROR_CHECK(ret == EOK, return -1, "Invalid param name %s", symValue);
|
||||
uint32_t valueLen = paramLen - curr;
|
||||
ret = SystemReadParam(tmpName, paramValue + curr, &valueLen);
|
||||
INIT_ERROR_CHECK(ret == 0, return -1, "Failed to get param %s", tmpName);
|
||||
curr += valueLen;
|
||||
left++;
|
||||
if ((unsigned int)(left - symValue) >= symLen) {
|
||||
break;
|
||||
}
|
||||
start = left;
|
||||
} while (1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void DoIfup(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
struct ifreq interface;
|
||||
if (strncpy_s(interface.ifr_name, IFNAMSIZ - 1, ctx->argv[0], strlen(ctx->argv[0])) != EOK) {
|
||||
INIT_LOGE("DoIfup failed to copy interface name");
|
||||
return;
|
||||
}
|
||||
|
||||
INIT_LOGD("interface name: %s", interface.ifr_name);
|
||||
int fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
INIT_LOGE("DoIfup failed to create socket, err = %d", errno);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ioctl(fd, SIOCGIFFLAGS, &interface) >= 0) {
|
||||
interface.ifr_flags |= IFF_UP;
|
||||
if (ioctl(fd, SIOCSIFFLAGS, &interface) < 0) {
|
||||
INIT_LOGE("DoIfup failed to do ioctl with command \"SIOCSIFFLAGS\", err = %d", errno);
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
// format insmod <ko name> [-f] [options]
|
||||
static void DoInsmod(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
int index = 0;
|
||||
int flags = 0;
|
||||
char *fileName = NULL;
|
||||
if (ctx->argc > index) {
|
||||
fileName = ctx->argv[index];
|
||||
index++;
|
||||
}
|
||||
INIT_ERROR_CHECK(fileName != NULL, return, "Can not find file name from param %s", cmdContent);
|
||||
INIT_LOGD("Install mode %s ", fileName);
|
||||
char *realPath = GetRealPath(fileName);
|
||||
INIT_ERROR_CHECK(realPath != NULL, return, "Can not get real file name from param %s", cmdContent);
|
||||
if (ctx->argc > 1 && ctx->argv[1] != NULL && strcmp(ctx->argv[1], "-f") == 0) { // [-f]
|
||||
flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS;
|
||||
index++;
|
||||
}
|
||||
char *options = BuildStringFromCmdArg(ctx, index); // [options]
|
||||
int fd = open(realPath, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
|
||||
if (fd >= 0) {
|
||||
int rc = syscall(__NR_finit_module, fd, options, flags);
|
||||
if (rc == -1) {
|
||||
INIT_LOGE("Failed to install mode for %s failed options %s err: %d", realPath, options, errno);
|
||||
}
|
||||
}
|
||||
if (options != NULL) {
|
||||
free(options);
|
||||
}
|
||||
if (fd >= 0) {
|
||||
close(fd);
|
||||
}
|
||||
free(realPath);
|
||||
return;
|
||||
}
|
||||
|
||||
static void DoSetParam(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
INIT_LOGD("set param name: %s, value %s ", ctx->argv[0], ctx->argv[1]);
|
||||
SystemWriteParam(ctx->argv[0], ctx->argv[1]);
|
||||
}
|
||||
|
||||
static void DoLoadPersistParams(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(ctx);
|
||||
INIT_LOGD("load persist params : %s", cmdContent);
|
||||
LoadPersistParams();
|
||||
}
|
||||
|
||||
static void DoTriggerCmd(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(ctx);
|
||||
INIT_LOGD("DoTrigger :%s", cmdContent);
|
||||
DoTriggerExec(cmdContent);
|
||||
}
|
||||
|
||||
static void DoLoadDefaultParams(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
int mode = 0;
|
||||
if (ctx->argc > 1 && strcmp(ctx->argv[1], "onlyadd") == 0) {
|
||||
mode = LOAD_PARAM_ONLY_ADD;
|
||||
}
|
||||
INIT_LOGD("DoLoadDefaultParams args : %s %d", cmdContent, mode);
|
||||
LoadDefaultParams(ctx->argv[0], mode);
|
||||
}
|
||||
|
||||
static void DoExec(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
UNUSED(ctx);
|
||||
// format: exec /xxx/xxx/xxx xxx
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
INIT_LOGE("DoExec: failed to fork child process to exec \"%s\"", cmdContent);
|
||||
return;
|
||||
}
|
||||
if (pid == 0) {
|
||||
const struct CmdArgs *subCtx = GetCmdArg(cmdContent, " ", SUPPORT_MAX_ARG_FOR_EXEC);
|
||||
if (subCtx == NULL || subCtx->argv[0] == NULL) {
|
||||
INIT_LOGE("DoExec: invalid arguments :%s", cmdContent);
|
||||
_exit(0x7f);
|
||||
}
|
||||
int ret = execv(subCtx->argv[0], subCtx->argv);
|
||||
if (ret == -1) {
|
||||
INIT_LOGE("DoExec: execute \"%s\" failed: %d.", cmdContent, errno);
|
||||
}
|
||||
FreeCmdArg((struct CmdArgs *)subCtx);
|
||||
_exit(0x7f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void DoSymlink(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
// format: symlink /xxx/xxx/xxx /xxx/xxx/xxx
|
||||
int ret = symlink(ctx->argv[0], ctx->argv[1]);
|
||||
if (ret != 0 && errno != EEXIST) {
|
||||
INIT_LOGE("DoSymlink: link %s to %s failed: %d", ctx->argv[0], ctx->argv[1], errno);
|
||||
}
|
||||
}
|
||||
|
||||
static mode_t GetDeviceMode(const char *deviceStr)
|
||||
{
|
||||
switch (*deviceStr) {
|
||||
case 'b':
|
||||
case 'B':
|
||||
return S_IFBLK;
|
||||
case 'c':
|
||||
case 'C':
|
||||
return S_IFCHR;
|
||||
case 'f':
|
||||
case 'F':
|
||||
return S_IFIFO;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void DoMakeNode(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
// format: mknod path b 0644 1 9
|
||||
const int deviceTypePos = 1;
|
||||
const int authorityPos = 2;
|
||||
const int majorDevicePos = 3;
|
||||
const int minorDevicePos = 4;
|
||||
const int decimal = 10;
|
||||
const int octal = 8;
|
||||
if (!access(ctx->argv[1], F_OK)) {
|
||||
INIT_LOGE("DoMakeNode failed, path has not sexisted");
|
||||
return;
|
||||
}
|
||||
mode_t deviceMode = GetDeviceMode(ctx->argv[deviceTypePos]);
|
||||
errno = 0;
|
||||
unsigned int major = strtoul(ctx->argv[majorDevicePos], NULL, decimal);
|
||||
INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[majorDevicePos]);
|
||||
unsigned int minor = strtoul(ctx->argv[minorDevicePos], NULL, decimal);
|
||||
INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[minorDevicePos]);
|
||||
mode_t authority = strtoul(ctx->argv[authorityPos], NULL, octal);
|
||||
INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[authorityPos]);
|
||||
int ret = mknod(ctx->argv[0], deviceMode | authority, makedev(major, minor));
|
||||
if (ret != 0) {
|
||||
INIT_LOGE("DoMakeNode: path: %s failed: %d", ctx->argv[0], errno);
|
||||
}
|
||||
}
|
||||
|
||||
static void DoMakeDevice(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
// format: makedev major minor
|
||||
const int decimal = 10;
|
||||
errno = 0;
|
||||
unsigned int major = strtoul(ctx->argv[0], NULL, decimal);
|
||||
INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[0]);
|
||||
unsigned int minor = strtoul(ctx->argv[1], NULL, decimal);
|
||||
INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[1]);
|
||||
dev_t deviceId = makedev(major, minor);
|
||||
if (deviceId < 0) {
|
||||
INIT_LOGE("DoMakedevice \" %s \" failed :%d ", cmdContent, errno);
|
||||
}
|
||||
}
|
||||
|
||||
static void DoMountFstabFile(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
INIT_LOGI("Mount partitions from fstab file \" %s \"", ctx->argv[0]);
|
||||
int rc = MountAllWithFstabFile(ctx->argv[0], 0);
|
||||
if (rc < 0) {
|
||||
INIT_LOGE("Run command mount_fstab failed");
|
||||
} else {
|
||||
INIT_LOGI("Mount partitions from fstab done");
|
||||
}
|
||||
}
|
||||
|
||||
static void DoUmountFstabFile(const struct CmdArgs *ctx, const char *cmdContent)
|
||||
{
|
||||
UNUSED(cmdContent);
|
||||
INIT_LOGI("Umount partitions from fstab file \" %s \"", ctx->argv[0]);
|
||||
int rc = UmountAllWithFstabFile(ctx->argv[0]);
|
||||
if (rc < 0) {
|
||||
INIT_LOGE("Run command umount_fstab failed");
|
||||
} else {
|
||||
INIT_LOGI("Umount partitions from fstab done");
|
||||
}
|
||||
}
|
||||
|
||||
static const struct CmdTable CMD_TABLE[] = {
|
||||
{ "exec ", 1, 10, DoExec },
|
||||
{ "mknode ", 1, 5, DoMakeNode },
|
||||
{ "makedev ", 2, 2, DoMakeDevice },
|
||||
{ "symlink ", 2, 2, DoSymlink },
|
||||
{ "trigger ", 1, 1, DoTriggerCmd },
|
||||
{ "insmod ", 1, 10, DoInsmod },
|
||||
{ "setparam ", 2, 2, DoSetParam },
|
||||
{ "load_persist_params ", 1, 1, DoLoadPersistParams },
|
||||
{ "load_param ", 1, 2, DoLoadDefaultParams },
|
||||
{ "ifup ", 1, 1, DoIfup },
|
||||
{ "mount_fstab ", 1, 1, DoMountFstabFile },
|
||||
{ "umount_fstab ", 1, 1, DoUmountFstabFile },
|
||||
};
|
||||
|
||||
const struct CmdTable *GetCmdTable(int *number)
|
||||
{
|
||||
*number = (int)ARRAY_LENGTH(CMD_TABLE);
|
||||
return CMD_TABLE;
|
||||
}
|
||||
Regular → Executable
+7
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2020-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
|
||||
@@ -13,9 +13,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef INIT_REBOOT_H
|
||||
#define INIT_REBOOT_H
|
||||
#include "init_jobs.h"
|
||||
#include "init_param.h"
|
||||
|
||||
void DoReboot(const char *value);
|
||||
|
||||
#endif
|
||||
void ParseAllJobs(const cJSON *fileRoot)
|
||||
{
|
||||
ParseTriggerConfig(fileRoot);
|
||||
}
|
||||
Executable
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 "device.h"
|
||||
#include "fs_manager/fs_manager.h"
|
||||
#include "init.h"
|
||||
#include "init_cmds.h"
|
||||
#include "init_log.h"
|
||||
#include "securec.h"
|
||||
|
||||
// This function will malloc memory.
|
||||
// Do not forget to free it after used.
|
||||
static char *GetExpandFileName(const char *fileName)
|
||||
{
|
||||
if (fileName == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
size_t expandSize = strlen(fileName) + PARAM_VALUE_LEN_MAX + 1;
|
||||
char *expandName = (char *)calloc(sizeof(char), expandSize);
|
||||
if (expandName == NULL) {
|
||||
INIT_LOGE("Failed to allocate memory for file name \" %s \"", fileName);
|
||||
return NULL;
|
||||
}
|
||||
int ret = GetParamValue(fileName, strlen(fileName), expandName, expandSize);
|
||||
INIT_ERROR_CHECK(ret == 0, free(expandName);
|
||||
return NULL, "Failed to get value for %s", fileName);
|
||||
return expandName;
|
||||
}
|
||||
|
||||
int MountRequriedPartitions(void)
|
||||
{
|
||||
const char *fstabFiles[] = {"/etc/fstab.required", NULL};
|
||||
int i = 0;
|
||||
int rc = -1;
|
||||
while (fstabFiles[i] != NULL) {
|
||||
char *fstabFile = GetExpandFileName(fstabFiles[i]);
|
||||
if (fstabFile != NULL) {
|
||||
if (access(fstabFile, F_OK) == 0) {
|
||||
INIT_LOGI("Mount required partition from %s", fstabFile);
|
||||
rc = MountAllWithFstabFile(fstabFile, 1);
|
||||
} else {
|
||||
INIT_LOGE("Cannot access fstab file \" %s \"", fstabFile);
|
||||
}
|
||||
free(fstabFile);
|
||||
fstabFile = NULL;
|
||||
}
|
||||
if (rc == 0) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
Regular → Executable
+4
-6
@@ -12,10 +12,8 @@
|
||||
* 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(const cJSON *root);
|
||||
|
||||
#endif
|
||||
#ifndef BASE_STARTUP_INITLITE_MOUNT_H
|
||||
#define BASE_STARTUP_INITLITE_MOUNT_H
|
||||
int MountRequriedPartitions(void);
|
||||
#endif
|
||||
Executable
+202
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/reboot.h>
|
||||
|
||||
#include "init_log.h"
|
||||
#include "init_service.h"
|
||||
#include "init_service_manager.h"
|
||||
#include "init_utils.h"
|
||||
#include "securec.h"
|
||||
|
||||
#define MAX_VALUE_LENGTH 500
|
||||
#define MAX_COMMAND_SIZE 20
|
||||
#define MAX_UPDATE_SIZE 100
|
||||
|
||||
struct RBMiscUpdateMessage {
|
||||
char command[MAX_COMMAND_SIZE];
|
||||
char update[MAX_UPDATE_SIZE];
|
||||
};
|
||||
|
||||
static int RBMiscWriteUpdaterMessage(const char *path, const struct RBMiscUpdateMessage *boot)
|
||||
{
|
||||
char *realPath = GetRealPath(path);
|
||||
if (realPath == NULL) {
|
||||
return -1;
|
||||
}
|
||||
int ret = 0;
|
||||
FILE *fp = fopen(realPath, "rb+");
|
||||
if (fp != NULL) {
|
||||
size_t writeLen = fwrite(boot, sizeof(struct RBMiscUpdateMessage), 1, fp);
|
||||
if (writeLen != 1) {
|
||||
INIT_LOGE("Failed to write misc for reboot");
|
||||
ret = -1;
|
||||
}
|
||||
} else {
|
||||
ret = -1;
|
||||
INIT_LOGE("Failed to open %s", path);
|
||||
}
|
||||
free(realPath);
|
||||
realPath = NULL;
|
||||
(void)fclose(fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int RBMiscReadUpdaterMessage(const char *path, struct RBMiscUpdateMessage *boot)
|
||||
{
|
||||
char *realPath = GetRealPath(path);
|
||||
if (realPath == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
FILE *fp = fopen(realPath, "rb");
|
||||
if (fp != NULL) {
|
||||
size_t readLen = fread(boot, 1, sizeof(struct RBMiscUpdateMessage), fp);
|
||||
if (readLen <= 0) {
|
||||
ret = -1;
|
||||
INIT_LOGE("Failed to read misc for reboot");
|
||||
}
|
||||
} else {
|
||||
ret = -1;
|
||||
INIT_LOGE("Failed to open %s", path);
|
||||
}
|
||||
free(realPath);
|
||||
realPath = NULL;
|
||||
(void)fclose(fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int GetMountStatusForMountPoint(const char *mountPoint)
|
||||
{
|
||||
const int bufferMaxSize = 512;
|
||||
char buffer[bufferMaxSize];
|
||||
size_t n;
|
||||
const char *mountFile = "/proc/mounts";
|
||||
FILE *fp = fopen(mountFile, "r");
|
||||
if (fp == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (fgets(buffer, sizeof(buffer) - 1, fp) != NULL) {
|
||||
n = strlen(buffer);
|
||||
if (buffer[n - 1] == '\n') {
|
||||
buffer[n - 1] = '\0';
|
||||
}
|
||||
if (strstr(buffer, mountPoint) != NULL) {
|
||||
(void)fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
(void)fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int CheckAndRebootToUpdater(const char *valueData, const char *cmd, const char *cmdExt, const char *boot)
|
||||
{
|
||||
// "updater" or "updater:"
|
||||
const char *miscFile = "/dev/block/platform/soc/10100000.himci.eMMC/by-name/misc";
|
||||
struct RBMiscUpdateMessage msg;
|
||||
int ret = RBMiscReadUpdaterMessage(miscFile, &msg);
|
||||
INIT_ERROR_CHECK(ret == 0, return -1, "Failed to get misc info for %s.", cmd);
|
||||
|
||||
if (boot != NULL) {
|
||||
ret = snprintf_s(msg.command, MAX_COMMAND_SIZE, MAX_COMMAND_SIZE - 1, "%s", boot);
|
||||
INIT_ERROR_CHECK(ret > 0, return -1, "Failed to format cmd for %s.", cmd);
|
||||
msg.command[MAX_COMMAND_SIZE - 1] = 0;
|
||||
} else {
|
||||
ret = memset_s(msg.command, MAX_COMMAND_SIZE, 0, MAX_COMMAND_SIZE);
|
||||
INIT_ERROR_CHECK(ret == 0, return -1, "Failed to format cmd for %s.", cmd);
|
||||
}
|
||||
|
||||
if ((cmdExt != NULL) && (valueData != NULL) && (strncmp(valueData, cmdExt, strlen(cmdExt)) == 0)) {
|
||||
const char *p = valueData + strlen(cmdExt);
|
||||
ret = snprintf_s(msg.update, MAX_UPDATE_SIZE, MAX_UPDATE_SIZE - 1, "%s", p);
|
||||
INIT_ERROR_CHECK(ret > 0, return -1, "Failed to format param for %s.", cmd);
|
||||
msg.update[MAX_UPDATE_SIZE - 1] = 0;
|
||||
}
|
||||
|
||||
if (RBMiscWriteUpdaterMessage(miscFile, &msg) == 0) {
|
||||
return reboot(RB_AUTOBOOT);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int CheckRebootParam(const char *valueData)
|
||||
{
|
||||
if (valueData == NULL) {
|
||||
return 0;
|
||||
}
|
||||
static const char *cmdParams[] = {
|
||||
"shutdown", "updater", "updater:", "flash", "flash:", "NoArgument", "bootloader"
|
||||
};
|
||||
size_t i = 0;
|
||||
for (; i < ARRAY_LENGTH(cmdParams); i++) {
|
||||
if (strncmp(valueData, cmdParams[i], strlen(cmdParams[i])) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= ARRAY_LENGTH(cmdParams)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ExecReboot(const char *value)
|
||||
{
|
||||
INIT_ERROR_CHECK(value != NULL && strlen(value) <= MAX_VALUE_LENGTH, return, "Invalid arg");
|
||||
const char *valueData = NULL;
|
||||
if (strncmp(value, "reboot,", strlen("reboot,")) == 0) {
|
||||
valueData = value + strlen("reboot,");
|
||||
} else if (strcmp(value, "reboot") != 0) {
|
||||
INIT_LOGE("Reboot value = %s, must started with reboot", value);
|
||||
return;
|
||||
}
|
||||
if (CheckRebootParam(valueData) != 0) {
|
||||
INIT_LOGE("Invalid arg %s for reboot.", value);
|
||||
return;
|
||||
}
|
||||
|
||||
StopAllServices(SERVICE_ATTR_INVALID);
|
||||
sync();
|
||||
if (GetMountStatusForMountPoint("/vendor") != 0 && umount("/vendor") != 0) {
|
||||
INIT_LOGE("Failed to umount vendor. errno = %d.", errno);
|
||||
}
|
||||
if (GetMountStatusForMountPoint("/data") != 0) {
|
||||
if (umount("/data") != 0 && umount2("/data", MNT_FORCE) != 0) {
|
||||
INIT_LOGE("Failed umount data. errno = %d.", errno);
|
||||
}
|
||||
} else {
|
||||
INIT_LOGE("Failed to get mount point \"/data\"");
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
if (valueData == NULL) {
|
||||
ret = CheckAndRebootToUpdater(NULL, "reboot", NULL, NULL);
|
||||
} else if (strcmp(valueData, "shutdown") == 0) {
|
||||
ret = reboot(RB_POWER_OFF);
|
||||
} else if (strcmp(valueData, "bootloader") == 0) {
|
||||
ret = reboot(RB_POWER_OFF);
|
||||
} else if (strncmp(valueData, "updater", strlen("updater")) == 0) {
|
||||
ret = CheckAndRebootToUpdater(valueData, "updater", "updater:", "boot_updater");
|
||||
} else if (strncmp(valueData, "flash", strlen("flash")) == 0) {
|
||||
ret = CheckAndRebootToUpdater(valueData, "flash", "flash:", "boot_flash");
|
||||
}
|
||||
INIT_LOGI("Reboot %s %s.", value, (ret == 0) ? "success" : "fail");
|
||||
return;
|
||||
}
|
||||
Executable
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "init_service.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include "init.h"
|
||||
#include "init_log.h"
|
||||
#include "init_param.h"
|
||||
#include "securec.h"
|
||||
|
||||
#define MIN_IMPORTANT_LEVEL (-20)
|
||||
#define MAX_IMPORTANT_LEVEL 19
|
||||
|
||||
void NotifyServiceChange(const char *serviceName, const char *change)
|
||||
{
|
||||
char paramName[PARAM_NAME_LEN_MAX] = { 0 };
|
||||
if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.svc.%s", serviceName) < 0) {
|
||||
INIT_LOGE("snprintf_s paramName error %d ", errno);
|
||||
}
|
||||
SystemWriteParam(paramName, change);
|
||||
}
|
||||
|
||||
int IsForbidden(const char *fieldStr)
|
||||
{
|
||||
UNUSED(fieldStr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SetImportantValue(Service *service, const char *attrName, int value, int flag)
|
||||
{
|
||||
UNUSED(attrName);
|
||||
UNUSED(flag);
|
||||
INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Set service attr failed! null ptr.");
|
||||
if (value >= MIN_IMPORTANT_LEVEL && value <= MAX_IMPORTANT_LEVEL) { // -20~19
|
||||
service->attribute |= SERVICE_ATTR_IMPORTANT;
|
||||
service->importance = value;
|
||||
} else {
|
||||
INIT_LOGE("Importance level = %d, is not between -20 and 19, error", value);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
int ServiceExec(const Service *service)
|
||||
{
|
||||
INIT_ERROR_CHECK(service != NULL && service->pathArgs.count > 0,
|
||||
return SERVICE_FAILURE, "Exec service failed! null ptr.");
|
||||
if (service->importance != 0) {
|
||||
if (setpriority(PRIO_PROCESS, 0, service->importance) != 0) {
|
||||
INIT_LOGE("setpriority failed for %s, importance = %d", service->name, service->importance);
|
||||
_exit(0x7f); // 0x7f: user specified
|
||||
}
|
||||
}
|
||||
// L2 Can not be reset env
|
||||
if (execv(service->pathArgs.argv[0], service->pathArgs.argv) != 0) {
|
||||
INIT_LOGE("service %s execve failed! err %d.", service->name, errno);
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
Regular → Executable
+10
-61
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Copyright (c) 2020-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
|
||||
@@ -12,45 +12,17 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init_signal_handler.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/wait.h>
|
||||
#ifdef __LINUX__
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#endif /* __LINUX__ */
|
||||
|
||||
#include "init_adapter.h"
|
||||
#include "init_log.h"
|
||||
#include "init_service_manager.h"
|
||||
|
||||
#ifndef OHOS_LITE
|
||||
#include "uv.h"
|
||||
#endif
|
||||
|
||||
#ifdef __LINUX__
|
||||
static pid_t g_waitPid = -1;
|
||||
static sem_t* g_waitSem = NULL;
|
||||
|
||||
void SignalRegWaitSem(pid_t waitPid, sem_t* waitSem)
|
||||
{
|
||||
g_waitPid = waitPid;
|
||||
g_waitSem = waitSem;
|
||||
}
|
||||
|
||||
static void CheckWaitPid(pid_t sigPID)
|
||||
{
|
||||
if (g_waitPid == sigPID && g_waitSem != NULL) {
|
||||
if (sem_post(g_waitSem) != 0) {
|
||||
INIT_LOGE("CheckWaitPid, sem_post failed, errno %d.", errno);
|
||||
}
|
||||
g_waitPid = -1;
|
||||
g_waitSem = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* __LINUX__ */
|
||||
uv_signal_t g_sigchldHandler;
|
||||
uv_signal_t g_sigtermHandler;
|
||||
|
||||
static void SigHandler(int sig)
|
||||
{
|
||||
@@ -63,29 +35,22 @@ static void SigHandler(int sig)
|
||||
if (sigPID <= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef OHOS_LITE
|
||||
// check child process exit status
|
||||
if (WIFSIGNALED(procStat)) {
|
||||
INIT_LOGE("Child process %d exit with signal: %d", sigPID, WTERMSIG(procStat));
|
||||
}
|
||||
|
||||
if (WIFEXITED(procStat)) {
|
||||
INIT_LOGE("Child process %d exit with code : %d", sigPID, WEXITSTATUS((unsigned int)procStat));
|
||||
INIT_LOGE("Child process %d exit with code : %d", sigPID, WEXITSTATUS(procStat));
|
||||
}
|
||||
#endif
|
||||
|
||||
INIT_LOGI("SigHandler, SIGCHLD received, sigPID = %d.", sigPID);
|
||||
#ifdef __LINUX__
|
||||
CheckWaitPid(sigPID);
|
||||
#endif /* __LINUX__ */
|
||||
ReapServiceByPID((int)sigPID);
|
||||
ServiceReap(GetServiceByPid(sigPID));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SIGTERM: {
|
||||
INIT_LOGI("SigHandler, SIGTERM received.");
|
||||
StopAllServices();
|
||||
StopAllServices(0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -94,27 +59,12 @@ static void SigHandler(int sig)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OHOS_LITE
|
||||
void SignalInitModule()
|
||||
{
|
||||
struct sigaction act;
|
||||
act.sa_handler = SigHandler;
|
||||
act.sa_flags = SA_RESTART;
|
||||
(void)sigfillset(&act.sa_mask);
|
||||
|
||||
sigaction(SIGCHLD, &act, NULL);
|
||||
sigaction(SIGTERM, &act, NULL);
|
||||
}
|
||||
#else // L2 or above, use signal event in libuv
|
||||
uv_signal_t g_sigchldHandler;
|
||||
uv_signal_t g_sigtermHandler;
|
||||
|
||||
static void UVSignalHandler(uv_signal_t* handle, int signum)
|
||||
static void UVSignalHandler(uv_signal_t *handle, int signum)
|
||||
{
|
||||
SigHandler(signum);
|
||||
}
|
||||
|
||||
void SignalInitModule()
|
||||
void SignalInit(void)
|
||||
{
|
||||
int ret = uv_signal_init(uv_default_loop(), &g_sigchldHandler);
|
||||
int ret1 = uv_signal_init(uv_default_loop(), &g_sigtermHandler);
|
||||
@@ -129,5 +79,4 @@ void SignalInitModule()
|
||||
if (uv_signal_start(&g_sigtermHandler, UVSignalHandler, SIGTERM) != 0) {
|
||||
INIT_LOGW("start SIGTERM handler failed");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Executable
+163
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* 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 "switch_root.h"
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include "init_log.h"
|
||||
#include "init_utils.h"
|
||||
#include "fs_manager/fs_manager.h"
|
||||
#include "securec.h"
|
||||
|
||||
static void FreeOldRoot(DIR *dir, dev_t dev)
|
||||
{
|
||||
if (dir == NULL) {
|
||||
return;
|
||||
}
|
||||
int dfd = dirfd(dir);
|
||||
bool isDir = false;
|
||||
struct dirent *de = NULL;
|
||||
while ((de = readdir(dir)) != NULL) {
|
||||
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (de->d_type == DT_DIR || de->d_type == DT_UNKNOWN) {
|
||||
struct stat st = {};
|
||||
if (fstatat(dfd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
|
||||
INIT_LOGE("Failed to get stat of %s", de->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (st.st_dev != dev) {
|
||||
continue; // Not the same device, ignore.
|
||||
}
|
||||
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
int fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
|
||||
isDir = true;
|
||||
if (fd >= 0) {
|
||||
DIR *subDir = fdopendir(fd);
|
||||
if (subDir != NULL) {
|
||||
FreeOldRoot(subDir, dev);
|
||||
closedir(subDir);
|
||||
} else {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (unlinkat(dfd, de->d_name, isDir ? AT_REMOVEDIR : 0) < 0) {
|
||||
INIT_LOGE("Failed to unlink %s, err = %d", de->d_name, errno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int MountToNewTarget(const char *target)
|
||||
{
|
||||
if (target == NULL || *target == '\0') {
|
||||
return -1;
|
||||
}
|
||||
Fstab *fstab = ReadFstabFromFile("/proc/mounts", true);
|
||||
if (fstab == NULL) {
|
||||
INIT_LOGE("Fatal error. Read mounts info from \" /proc/mounts \" failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (FstabItem *item = fstab->head; item != NULL; item = item->next) {
|
||||
const char *mountPoint = item->mountPoint;
|
||||
if (mountPoint == NULL || strcmp(mountPoint, "/") == 0 ||
|
||||
strcmp(mountPoint, target) == 0) {
|
||||
continue;
|
||||
}
|
||||
char newMountPoint[PATH_MAX] = {0};
|
||||
if (snprintf_s(newMountPoint, PATH_MAX, PATH_MAX - 1, "%s%s", target, mountPoint) == -1) {
|
||||
INIT_LOGW("Cannot build new mount point for old mount point \" %s \"", mountPoint);
|
||||
// Just ignore this one or return error?
|
||||
continue;
|
||||
}
|
||||
INIT_LOGI("new mount point is: %s", newMountPoint);
|
||||
if (mount(mountPoint, newMountPoint, NULL, MS_MOVE, NULL) < 0) {
|
||||
INIT_LOGE("Failed to mount moving %s to %s, err = %d", mountPoint, newMountPoint, errno);
|
||||
// If one mount entry cannot move to new mountpoint, umount it.
|
||||
umount2(mountPoint, MNT_FORCE);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ReleaseFstab(fstab);
|
||||
fstab = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Switch root from ramdisk to system
|
||||
int SwitchRoot(const char *newRoot)
|
||||
{
|
||||
if (newRoot == NULL || *newRoot == '\0') {
|
||||
errno = EINVAL;
|
||||
INIT_LOGE("Fatal error. Try to switch to new root with invalid new mount point");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct stat oldRootStat = {};
|
||||
if (stat("/", &oldRootStat) != 0) {
|
||||
INIT_LOGE("Failed to get old root \"/\" stat");
|
||||
return -1;
|
||||
}
|
||||
DIR *oldRoot = opendir("/");
|
||||
if (oldRoot == NULL) {
|
||||
INIT_LOGE("Failed to open root dir \"/\"");
|
||||
return -1;
|
||||
}
|
||||
struct stat newRootStat = {};
|
||||
if (stat(newRoot, &newRootStat) != 0) {
|
||||
INIT_LOGE("Failed to get new root \" %s \" stat", newRoot);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (oldRootStat.st_dev == newRootStat.st_dev) {
|
||||
INIT_LOGW("Try to switch root in same device, skip switching root");
|
||||
return 0;
|
||||
}
|
||||
if (MountToNewTarget(newRoot) < 0) {
|
||||
INIT_LOGE("Failed to move mount to new root \" %s \" stat", newRoot);
|
||||
return -1;
|
||||
}
|
||||
// OK, we've done move mount.
|
||||
// Now mount new root.
|
||||
if (chdir(newRoot) < 0) {
|
||||
INIT_LOGE("Failed to change directory to %s, err = %d", newRoot, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount(newRoot, "/", NULL, MS_MOVE, NULL) < 0) {
|
||||
INIT_LOGE("Failed to mount moving %s to %s, err = %d", newRoot, "/", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (chroot(".") < 0) {
|
||||
INIT_LOGE("Failed to change root directory");
|
||||
return -1;
|
||||
}
|
||||
FreeOldRoot(oldRoot, oldRootStat.st_dev);
|
||||
closedir(oldRoot);
|
||||
oldRoot = NULL;
|
||||
return 0;
|
||||
}
|
||||
Regular → Executable
Regular → Executable
+4
-12
@@ -14,7 +14,6 @@
|
||||
*/
|
||||
|
||||
#include "init_log.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
@@ -34,22 +33,15 @@
|
||||
static InitLogLevel g_logLevel = INIT_INFO;
|
||||
static const char *LOG_LEVEL_STR[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" };
|
||||
|
||||
void SetLogLevel(InitLogLevel logLevel)
|
||||
void SetInitLogLevel(InitLogLevel logLevel)
|
||||
{
|
||||
g_logLevel = logLevel;
|
||||
}
|
||||
|
||||
#ifdef OHOS_LITE
|
||||
static LogLevel g_hiLogLevel = LOG_INFO;
|
||||
|
||||
void SetHiLogLevel(LogLevel logLevel)
|
||||
void InitToHiLog(InitLogLevel logLevel, const char *fmt, ...)
|
||||
{
|
||||
g_hiLogLevel = logLevel;
|
||||
}
|
||||
|
||||
void InitToHiLog(LogLevel logLevel, const char *fmt, ...)
|
||||
{
|
||||
if (logLevel < g_hiLogLevel) {
|
||||
if (logLevel < g_logLevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -84,7 +76,7 @@ void EnableDevKmsg(void)
|
||||
if (fd < 0) {
|
||||
return;
|
||||
}
|
||||
const char *kmsgStatus = "on";
|
||||
char *kmsgStatus = "on";
|
||||
write(fd, kmsgStatus, strlen(kmsgStatus) + 1);
|
||||
close(fd);
|
||||
fd = -1;
|
||||
|
||||
Regular → Executable
+16
-18
@@ -19,13 +19,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#ifdef OHOS_LITE
|
||||
#include "hilog/log.h"
|
||||
#else
|
||||
#ifdef INIT_AGENT
|
||||
#include "hilog/log.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
@@ -41,6 +34,8 @@ typedef enum InitLogLevel {
|
||||
INIT_FATAL
|
||||
} InitLogLevel;
|
||||
|
||||
void SetInitLogLevel(InitLogLevel logLevel);
|
||||
|
||||
#ifdef LABEL
|
||||
#define INIT_LOG_TAG LABEL
|
||||
#endif
|
||||
@@ -50,22 +45,22 @@ typedef enum InitLogLevel {
|
||||
#endif
|
||||
|
||||
#ifdef OHOS_LITE
|
||||
#include "hilog/log.h"
|
||||
|
||||
#undef LOG_DOMAIN
|
||||
#define LOG_DOMAIN 0xD000719
|
||||
|
||||
#define INIT_LOGD(fmt, ...) InitToHiLog(LOG_DEBUG, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
#define INIT_LOGI(fmt, ...) InitToHiLog(LOG_INFO, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
#define INIT_LOGW(fmt, ...) InitToHiLog(LOG_WARN, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
#define INIT_LOGE(fmt, ...) InitToHiLog(LOG_ERROR, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
#define INIT_LOGF(fmt, ...) InitToHiLog(LOG_FATAL, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
#define INIT_LOGD(fmt, ...) InitToHiLog(INIT_DEBUG, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
#define INIT_LOGI(fmt, ...) InitToHiLog(INIT_INFO, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
#define INIT_LOGW(fmt, ...) InitToHiLog(INIT_WARN, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
#define INIT_LOGE(fmt, ...) InitToHiLog(INIT_ERROR, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
#define INIT_LOGF(fmt, ...) InitToHiLog(INIT_FATAL, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
|
||||
#define STARTUP_LOGD(LABEL, fmt, ...) InitToHiLog(LABEL, LOG_DEBUG, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
#define STARTUP_LOGI(LABEL, fmt, ...) InitToHiLog(LABEL, LOG_INFO, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
#define STARTUP_LOGE(LABEL, fmt, ...) InitToHiLog(LABEL, LOG_ERROR, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
#define STARTUP_LOGD(LABEL, fmt, ...) InitToHiLog(LABEL, INIT_DEBUG, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
#define STARTUP_LOGI(LABEL, fmt, ...) InitToHiLog(INIT_INFO, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
#define STARTUP_LOGE(LABEL, fmt, ...) InitToHiLog(INIT_ERROR, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
|
||||
|
||||
void InitToHiLog(LogLevel logLevel, const char *fmt, ...);
|
||||
void SetHiLogLevel(LogLevel logLevel);
|
||||
void InitToHiLog(InitLogLevel logLevel, const char *fmt, ...);
|
||||
|
||||
#else
|
||||
#define FILE_NAME (strrchr((__FILE__), '/') ? strrchr((__FILE__), '/') + 1 : (__FILE__))
|
||||
@@ -80,7 +75,11 @@ void SetHiLogLevel(LogLevel logLevel);
|
||||
#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
|
||||
#ifndef LABEL
|
||||
#define LABEL "ParamAgent"
|
||||
#endif
|
||||
|
||||
#include "hilog/log.h"
|
||||
#define PARAM_AGENT_LOG_PATH "/data/init_agent/init_agent.log"
|
||||
|
||||
#define STARTUP_LOGD(LABEL, fmt, ...) \
|
||||
@@ -107,7 +106,6 @@ void SetHiLogLevel(LogLevel logLevel);
|
||||
#endif
|
||||
|
||||
void InitLog(InitLogLevel logLevel, const char *fileName, int line, const char *kLevel, const char *fmt, ...);
|
||||
void SetLogLevel(InitLogLevel logLevel);
|
||||
void OpenLogDevice(void);
|
||||
void EnableDevKmsg(void);
|
||||
#endif
|
||||
|
||||
Regular → Executable
+29
-7
@@ -14,6 +14,7 @@ import("//build/ohos.gni")
|
||||
|
||||
declare_args() {
|
||||
param_security = "dac"
|
||||
param_test = "false"
|
||||
}
|
||||
|
||||
ohos_prebuilt_etc("param_watcher.rc") {
|
||||
@@ -28,7 +29,8 @@ ohos_prebuilt_etc("param_watcher.rc") {
|
||||
|
||||
ohos_static_library("param_service") {
|
||||
sources = [
|
||||
"//base/startup/init_lite/services/src/list.c",
|
||||
"//base/startup/init_lite/services/utils/init_utils.c",
|
||||
"//base/startup/init_lite/services/utils/list.c",
|
||||
"adapter/param_libuvadp.c",
|
||||
"adapter/param_persistadp.c",
|
||||
"manager/param_manager.c",
|
||||
@@ -47,6 +49,7 @@ ohos_static_library("param_service") {
|
||||
"adapter",
|
||||
"//base/startup/init_lite/services/include/param",
|
||||
"//base/startup/init_lite/services/include",
|
||||
"//base/startup/init_lite/services/init/include",
|
||||
"//base/startup/init_lite/services/log",
|
||||
"//third_party/libuv/include",
|
||||
"//third_party/cJSON",
|
||||
@@ -54,6 +57,10 @@ ohos_static_library("param_service") {
|
||||
|
||||
defines = [ "PARAM_SUPPORT_SAVE_PERSIST" ]
|
||||
|
||||
if (param_test == "true") {
|
||||
defines += [ "PARAM_TEST" ]
|
||||
}
|
||||
|
||||
if (param_security == "selinux") {
|
||||
sources += [ "adapter/param_selinux.c" ]
|
||||
defines += [ "PARAM_SUPPORT_SELINUX" ]
|
||||
@@ -72,6 +79,7 @@ ohos_static_library("param_service") {
|
||||
|
||||
ohos_shared_library("param_client") {
|
||||
sources = [
|
||||
"//base/startup/init_lite/services/utils/init_utils.c",
|
||||
"client/param_request.c",
|
||||
"manager/param_manager.c",
|
||||
"manager/param_message.c",
|
||||
@@ -98,11 +106,19 @@ ohos_shared_library("param_client") {
|
||||
defines += [ "PARAM_SUPPORT_DAC" ]
|
||||
}
|
||||
|
||||
if (param_test == "true") {
|
||||
defines += [ "PARAM_TEST" ]
|
||||
}
|
||||
|
||||
deps = [
|
||||
"//base/startup/init_lite/services/log:agent_log",
|
||||
"//third_party/bounds_checking_function:libsec_static",
|
||||
]
|
||||
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
|
||||
install_images = [
|
||||
"system",
|
||||
"updater",
|
||||
]
|
||||
part_name = "init"
|
||||
}
|
||||
|
||||
@@ -197,19 +213,25 @@ ohos_executable("param") {
|
||||
"//base/update/updateservice/interfaces/innerkits/include",
|
||||
]
|
||||
|
||||
defines = [
|
||||
"PARAM_TEST",
|
||||
"INIT_AGENT",
|
||||
]
|
||||
defines = [ "INIT_AGENT" ]
|
||||
|
||||
deps = [
|
||||
"//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",
|
||||
]
|
||||
|
||||
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
|
||||
|
||||
if (param_test == "true") {
|
||||
defines += [ "PARAM_TEST" ]
|
||||
deps += [ "//base/startup/init_lite/services/param:param_watcheragent" ]
|
||||
} else {
|
||||
install_images = [
|
||||
"system",
|
||||
"updater",
|
||||
]
|
||||
}
|
||||
install_enable = true
|
||||
part_name = "init"
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "init_utils.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)
|
||||
@@ -170,6 +170,7 @@ static int GetParamSecurityLabel(SecurityLabelFunc label, const char *path, void
|
||||
if ((stat(path, &st) == 0) && !S_ISDIR(st.st_mode)) {
|
||||
return ProcessParamFile(path, &cxt);
|
||||
}
|
||||
PARAM_LOGD("GetParamSecurityLabel %s ", path);
|
||||
return ReadFileInDir(path, ".para.dac", ProcessParamFile, &cxt);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "param_libuvadp.h"
|
||||
#include <sys/wait.h>
|
||||
|
||||
#define LABEL "Libuvadp"
|
||||
static LibuvWorkSpace libuv = { NULL };
|
||||
static const uint32_t RECV_BUFFER_MAX = 5 * 1024;
|
||||
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#include "param_persist.h"
|
||||
#include "param_utils.h"
|
||||
|
||||
#define LABEL "PERSIST_ADP"
|
||||
|
||||
typedef struct {
|
||||
void *context;
|
||||
PersistParamGetPtr persistParamGet;
|
||||
@@ -59,6 +57,12 @@ static int LoadPersistParam(PersistParamGetPtr persistParamGet, void *context)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SavePersistParam(const char *name, const char *value)
|
||||
{
|
||||
PARAM_LOGD("SavePersistParam %s=%s", name, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int BatchSavePersistParamBegin(PERSIST_SAVE_HANDLE *handle)
|
||||
{
|
||||
FILE *fp = fopen(PARAM_PERSIST_SAVE_TMP_PATH, "w");
|
||||
@@ -88,7 +92,7 @@ static void BatchSavePersistParamEnd(PERSIST_SAVE_HANDLE handle)
|
||||
int RegisterPersistParamOps(PersistParamOps *ops)
|
||||
{
|
||||
PARAM_CHECK(ops != NULL, return -1, "Invalid ops");
|
||||
ops->save = NULL;
|
||||
ops->save = SavePersistParam;
|
||||
ops->load = LoadPersistParam;
|
||||
ops->batchSaveBegin = BatchSavePersistParamBegin;
|
||||
ops->batchSave = BatchSavePersistParam;
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
|
||||
#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;
|
||||
|
||||
Regular → Executable
+10
-4
@@ -12,8 +12,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "param_request.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stddef.h>
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define INIT_PROCESS_PID 1
|
||||
#define LABEL "Client"
|
||||
|
||||
static const uint32_t RECV_BUFFER_MAX = 5 * 1024;
|
||||
|
||||
static atomic_uint g_requestId = ATOMIC_VAR_INIT(1);
|
||||
@@ -114,7 +114,7 @@ static int StartRequest(int *fd, ParamMessage *request, int timeout)
|
||||
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);
|
||||
ret = ConntectServer(clientFd, CLIENT_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));
|
||||
@@ -291,6 +291,12 @@ int SystemTraversalParameter(
|
||||
void SystemDumpParameters(int verbose)
|
||||
{
|
||||
InitParamClient();
|
||||
// check default dac
|
||||
ParamHandle handle = 0;
|
||||
int ret = ReadParamWithCheck(&g_clientSpace.paramSpace, "#", DAC_READ, &handle);
|
||||
if (ret != PARAM_CODE_NOT_FOUND && ret != 0) {
|
||||
PARAM_CHECK(ret == 0, return, "Forbid to dump parameters");
|
||||
}
|
||||
DumpParameters(&g_clientSpace.paramSpace, verbose);
|
||||
}
|
||||
|
||||
@@ -308,7 +314,7 @@ int WatchParamCheck(const char *keyprefix)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef STARTUP_INIT_TEST
|
||||
#if (defined STARTUP_INIT_TEST || defined PARAM_TEST)
|
||||
ParamWorkSpace *GetClientParamWorkSpace(void)
|
||||
{
|
||||
return &g_clientSpace.paramSpace;
|
||||
|
||||
@@ -32,10 +32,10 @@
|
||||
#define WAIT_TIMEOUT_INDEX 2
|
||||
|
||||
struct CmdArgs {
|
||||
char name[8];
|
||||
char name[8]; // cmd name length
|
||||
int minArg;
|
||||
void (*DoFuncion)(int argc, char *argv[], int start);
|
||||
char help[128];
|
||||
char help[128]; // cmd help length
|
||||
};
|
||||
|
||||
static void ShowParam(ParamHandle handle, void *cookie)
|
||||
@@ -100,17 +100,89 @@ static void ExeuteCmdParamWait(int argc, char *argv[], int start)
|
||||
if (argc > (start + WAIT_TIMEOUT_INDEX)) {
|
||||
timeout = atol(argv[start + WAIT_TIMEOUT_INDEX]);
|
||||
}
|
||||
SystemWaitParameter(argv[start], value, timeout);
|
||||
int ret = SystemWaitParameter(argv[start], value, timeout);
|
||||
if (ret == 0) {
|
||||
printf("Param wait success ");
|
||||
} else {
|
||||
printf("Param wait fail");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PARAM_TEST
|
||||
static void ExeuteCmdParamRead(int argc, char *argv[], int start)
|
||||
{
|
||||
SystemSetParameter("test.randrom.test.start", "1");
|
||||
char buffer[PARAM_NAME_LEN_MAX] = {0};
|
||||
printf("SystemGetParameter start \n");
|
||||
srand((unsigned)time(NULL));
|
||||
while (1) {
|
||||
int wait = rand() / READ_DURATION + READ_DURATION; // 100ms
|
||||
uint32_t size = PARAM_NAME_LEN_MAX;
|
||||
int ret = SystemGetParameter(argv[start], buffer, &size);
|
||||
if (ret == 0) {
|
||||
printf("SystemGetParameter value %s %d \n", buffer, wait);
|
||||
} else {
|
||||
printf("SystemGetParameter fail %d \n", wait);
|
||||
}
|
||||
usleep(wait);
|
||||
}
|
||||
}
|
||||
|
||||
static void HandleParamChange(const char *key, const char *value, void *context)
|
||||
{
|
||||
if (key == NULL || value == NULL) {
|
||||
return;
|
||||
}
|
||||
UNUSED(context);
|
||||
printf("Receive parameter change %s %s \n", key, value);
|
||||
}
|
||||
|
||||
static void ExeuteCmdParamWatch(int argc, char *argv[], int start)
|
||||
{
|
||||
if (argc <= start) {
|
||||
return;
|
||||
}
|
||||
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 },
|
||||
};
|
||||
{ "set", 4, ExeuteCmdParamSet, USAGE_INFO_PARAM_SET }, // set param count
|
||||
{ "get", 2, ExeuteCmdParamGet, USAGE_INFO_PARAM_GET }, // get param count
|
||||
{ "wait", 3, ExeuteCmdParamWait, USAGE_INFO_PARAM_WAIT }, // wait param count
|
||||
{ "dump", 2, ExeuteCmdParamDump, USAGE_INFO_PARAM_DUMP }, // dump param count
|
||||
#ifdef PARAM_TEST
|
||||
{ "read", 2, ExeuteCmdParamRead, USAGE_INFO_PARAM_READ }, // read param count
|
||||
{ "watch", 2, ExeuteCmdParamWatch, USAGE_INFO_PARAM_WATCH }, // watch param count
|
||||
#endif
|
||||
};
|
||||
#ifdef PARAM_TEST
|
||||
ParamWorkSpace *space = GetClientParamWorkSpace();
|
||||
if (space != NULL && space->securityLabel != NULL) {
|
||||
const int testUid = 1000;
|
||||
space->securityLabel->cred.uid = testUid;
|
||||
space->securityLabel->cred.gid = testUid;
|
||||
}
|
||||
#endif
|
||||
if ((strcmp(argv[0], "./paramset") == 0) || (strcmp(argv[0], "paramset") == 0)) {
|
||||
if (argc == (MIN_ARGC + 1)) {
|
||||
ExeuteCmdParamSet(argc, argv, 1);
|
||||
} else {
|
||||
printf("param set key value \n");
|
||||
}
|
||||
return 0;
|
||||
} else if ((strcmp(argv[0], "./paramget") == 0) || (strcmp(argv[0], "paramget") == 0)) {
|
||||
ExeuteCmdParamSet(argc, argv, 1);
|
||||
return 0;
|
||||
}
|
||||
if (argc < MIN_ARGC) {
|
||||
printf("usage: \n");
|
||||
for (size_t i = 0; i < sizeof(paramCmds) / sizeof(paramCmds[0]); i++) {
|
||||
|
||||
Regular → Executable
@@ -40,8 +40,12 @@ typedef struct {
|
||||
|
||||
#ifdef PARAM_SUPPORT_SAVE_PERSIST
|
||||
int RegisterPersistParamOps(PersistParamOps *ops);
|
||||
#ifdef STARTUP_INIT_TEST
|
||||
#define PARAM_MUST_SAVE_PARAM_DIFF 10 // 10s
|
||||
#else
|
||||
#define PARAM_MUST_SAVE_PARAM_DIFF 1
|
||||
#endif
|
||||
#else
|
||||
#define PARAM_MUST_SAVE_PARAM_DIFF UINT32_MAX
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
|
||||
Regular → Executable
+1
@@ -16,6 +16,7 @@
|
||||
|
||||
#ifndef BASE_STARTUP_PARAM_REQUEST_H
|
||||
#define BASE_STARTUP_PARAM_REQUEST_H
|
||||
#include <stdatomic.h>
|
||||
#include "param_manager.h"
|
||||
#include "sys_param.h"
|
||||
#ifdef __cplusplus
|
||||
|
||||
Regular → Executable
Regular → Executable
@@ -48,16 +48,17 @@ typedef enum {
|
||||
#define OHOS_SERVICE_CTRL_PREFIX "ohos.servicectrl."
|
||||
#define OHOS_BOOT "ohos.boot."
|
||||
|
||||
#define CLIENT_PIPE_NAME "/dev/unix/socket/paramservice"
|
||||
#define CLIENT_PARAM_STORAGE_PATH "/dev/__parameters__/param_storage"
|
||||
|
||||
#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_DEFAULT_PATH "/data/init_ut"
|
||||
#define PIPE_NAME PARAM_DEFAULT_PATH"/param/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
|
||||
@@ -66,9 +67,10 @@ typedef enum {
|
||||
#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"
|
||||
#endif
|
||||
|
||||
#define GROUP_FILE_PATH "/etc/group"
|
||||
#define USER_FILE_PATH "/etc/passwd"
|
||||
#endif
|
||||
|
||||
#define WORKSPACE_FLAGS_INIT 0x01
|
||||
#define WORKSPACE_FLAGS_LOADED 0x02
|
||||
@@ -79,6 +81,10 @@ typedef enum {
|
||||
#define PARAM_CLEAR_FLAG(node, flag) ((node) &= ~(flag))
|
||||
#define PARAM_TEST_FLAG(node, flag) (((node) & (flag)) == (flag))
|
||||
|
||||
#ifndef LABEL
|
||||
#define LABEL "Parameter"
|
||||
#endif
|
||||
|
||||
#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__)
|
||||
@@ -110,8 +116,6 @@ typedef struct {
|
||||
#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
|
||||
|
||||
Regular → Executable
Regular → Executable
Regular → Executable
+14
-8
@@ -14,9 +14,9 @@
|
||||
*/
|
||||
|
||||
#include "param_manager.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#define LABEL "Manager"
|
||||
#if !defined PARAM_SUPPORT_SELINUX && !defined PARAM_SUPPORT_DAC
|
||||
static ParamSecurityLabel g_defaultSecurityLabel;
|
||||
#endif
|
||||
@@ -64,7 +64,11 @@ int InitParamWorkSpace(ParamWorkSpace *workSpace, int onlyRead)
|
||||
ret = paramSecurityOps->securityCheckFilePermission(workSpace->securityLabel, PARAM_STORAGE_PATH, op);
|
||||
PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "No permission to read file %s", PARAM_STORAGE_PATH);
|
||||
}
|
||||
ret = InitWorkSpace(PARAM_STORAGE_PATH, &workSpace->paramSpace, onlyRead);
|
||||
if (onlyRead) {
|
||||
ret = InitWorkSpace(CLIENT_PARAM_STORAGE_PATH, &workSpace->paramSpace, onlyRead);
|
||||
} else {
|
||||
ret = InitWorkSpace(PARAM_STORAGE_PATH, &workSpace->paramSpace, onlyRead);
|
||||
}
|
||||
PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "Failed to init workspace");
|
||||
PARAM_SET_FLAG(workSpace->flags, WORKSPACE_FLAGS_INIT);
|
||||
return ret;
|
||||
@@ -272,12 +276,14 @@ static void DumpWorkSpace(const ParamWorkSpace *workSpace, int verbose)
|
||||
{
|
||||
printf("workSpace information \n");
|
||||
printf(" map file: %s \n", workSpace->paramSpace.fileName);
|
||||
printf(" total size: %d \n", workSpace->paramSpace.area->dataSize);
|
||||
printf(" first offset: %d \n", workSpace->paramSpace.area->firstNode);
|
||||
printf(" current offset: %d \n", workSpace->paramSpace.area->currOffset);
|
||||
printf(" total node: %d \n", workSpace->paramSpace.area->trieNodeCount);
|
||||
printf(" total param node: %d \n", workSpace->paramSpace.area->paramNodeCount);
|
||||
printf(" total security node: %d\n", workSpace->paramSpace.area->securityNodeCount);
|
||||
if (workSpace->paramSpace.area != NULL) {
|
||||
printf(" total size: %d \n", workSpace->paramSpace.area->dataSize);
|
||||
printf(" first offset: %d \n", workSpace->paramSpace.area->firstNode);
|
||||
printf(" current offset: %d \n", workSpace->paramSpace.area->currOffset);
|
||||
printf(" total node: %d \n", workSpace->paramSpace.area->trieNodeCount);
|
||||
printf(" total param node: %d \n", workSpace->paramSpace.area->paramNodeCount);
|
||||
printf(" total security node: %d\n", workSpace->paramSpace.area->securityNodeCount);
|
||||
}
|
||||
printf(" node info: \n");
|
||||
TraversalTrieNode(&workSpace->paramSpace, NULL, DumpTrieDataNodeTraversal, (void *)&verbose);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "param_message.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
@@ -21,7 +22,6 @@
|
||||
#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);
|
||||
|
||||
Regular → Executable
-2
@@ -27,8 +27,6 @@
|
||||
#include "param_utils.h"
|
||||
#include "sys_param.h"
|
||||
|
||||
#define LABEL "Manager"
|
||||
|
||||
static int InitWorkSpace_(WorkSpace *workSpace, int mode, int prot, uint32_t spaceSize, int readOnly)
|
||||
{
|
||||
PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid workSpace");
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define LABEL "PARAM_UTILS"
|
||||
void CheckAndCreateDir(const char *fileName)
|
||||
{
|
||||
if (fileName == NULL || *fileName == '\0') {
|
||||
@@ -39,45 +38,6 @@ void CheckAndCreateDir(const char *fileName)
|
||||
free(path);
|
||||
}
|
||||
|
||||
int ReadFileInDir(const char *dirPath, const char *includeExt,
|
||||
int (*processFile)(const char *fileName, void *context), void *context)
|
||||
{
|
||||
if (dirPath == NULL || processFile == NULL) {
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
free(fileName);
|
||||
closedir(pDir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *ReadFileData(const char *fileName)
|
||||
{
|
||||
if (fileName == NULL) {
|
||||
@@ -86,7 +46,7 @@ char *ReadFileData(const char *fileName)
|
||||
char *buffer = NULL;
|
||||
int fd = -1;
|
||||
do {
|
||||
fd = open(fileName, O_RDONLY);
|
||||
fd = open(fileName, O_RDONLY); // 阶段早,不能使用realpath
|
||||
PARAM_CHECK(fd >= 0, break, "Failed to read file %s", fileName);
|
||||
|
||||
buffer = (char *)malloc(MAX_DATA_BUFFER);
|
||||
|
||||
Regular → Executable
+6
-5
@@ -12,8 +12,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "param_persist.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
@@ -24,8 +24,6 @@
|
||||
#include "param_trie.h"
|
||||
#include "sys_param.h"
|
||||
|
||||
#define LABEL "Manager"
|
||||
|
||||
static ParamPersistWorkSpace g_persistWorkSpace = { 0, NULL, 0, { NULL, NULL, NULL, NULL, NULL } };
|
||||
|
||||
static int AddPersistParam(const char *name, const char *value, void *context)
|
||||
@@ -110,10 +108,12 @@ int LoadPersistParam(ParamWorkSpace *workSpace)
|
||||
PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid workSpace");
|
||||
int ret = InitPersistParamWorkSpace(workSpace);
|
||||
PARAM_CHECK(ret == 0, return ret, "Failed to init persist param");
|
||||
#ifndef STARTUP_INIT_TEST
|
||||
if (PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED)) {
|
||||
PARAM_LOGE("Persist param has been loaded");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (g_persistWorkSpace.persistParamOps.load != NULL) {
|
||||
ret = g_persistWorkSpace.persistParamOps.load(AddPersistParam, &workSpace->paramSpace);
|
||||
PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED);
|
||||
@@ -124,10 +124,11 @@ int LoadPersistParam(ParamWorkSpace *workSpace)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void TimerCallbackForSave(ParamTaskPtr timer, void *context)
|
||||
PARAM_STATIC void TimerCallbackForSave(ParamTaskPtr timer, void *context)
|
||||
{
|
||||
UNUSED(context);
|
||||
ParamTaskClose(timer);
|
||||
UNUSED(timer);
|
||||
ParamTaskClose(g_persistWorkSpace.saveTimer);
|
||||
g_persistWorkSpace.saveTimer = NULL;
|
||||
if (!PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_UPDATE)) {
|
||||
return;
|
||||
|
||||
Regular → Executable
+114
-15
@@ -25,12 +25,12 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "init_param.h"
|
||||
#include "init_utils.h"
|
||||
#include "param_message.h"
|
||||
#include "param_manager.h"
|
||||
#include "param_request.h"
|
||||
#include "trigger_manager.h"
|
||||
|
||||
#define LABEL "ParamServer"
|
||||
static ParamWorkSpace g_paramWorkSpace = { 0, {}, NULL, {}, NULL, NULL };
|
||||
|
||||
static void OnClose(ParamTaskPtr client)
|
||||
@@ -133,6 +133,8 @@ PARAM_STATIC int AddSecurityLabel(const ParamAuditData *auditData, void *context
|
||||
#ifdef STARTUP_INIT_TEST
|
||||
ParamSecruityNode *label = (ParamSecruityNode *)GetTrieNode(&workSpace->paramSpace, node->labelIndex);
|
||||
label->mode = auditData->dacData.mode;
|
||||
label->uid = auditData->dacData.uid;
|
||||
label->gid = auditData->dacData.gid;
|
||||
#endif
|
||||
PARAM_LOGE("Error, repeate to add label for name %s", auditData->name);
|
||||
}
|
||||
@@ -155,7 +157,7 @@ static char *GetServiceCtrlName(const char *name, const char *value)
|
||||
};
|
||||
char *key = NULL;
|
||||
if (strcmp("sys.powerctrl", name) == 0) {
|
||||
for (size_t i = 0; i < sizeof(powerCtrlArg) / sizeof(powerCtrlArg[0]); i++) {
|
||||
for (size_t i = 0; i < ARRAY_LENGTH(powerCtrlArg); i++) {
|
||||
if (strncmp(value, powerCtrlArg[i][0], strlen(powerCtrlArg[i][0])) == 0) {
|
||||
uint32_t keySize = strlen(powerCtrlArg[i][1]) + strlen(OHOS_SERVICE_CTRL_PREFIX) + 1;
|
||||
key = (char *)malloc(keySize + 1);
|
||||
@@ -167,7 +169,7 @@ static char *GetServiceCtrlName(const char *name, const char *value)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < sizeof(ctrlParam) / sizeof(ctrlParam[0]); i++) {
|
||||
for (size_t i = 0; i < ARRAY_LENGTH(ctrlParam); i++) {
|
||||
if (strcmp(name, ctrlParam[i]) == 0) {
|
||||
uint32_t keySize = strlen(value) + strlen(OHOS_SERVICE_CTRL_PREFIX) + 1;
|
||||
key = (char *)malloc(keySize + 1);
|
||||
@@ -225,14 +227,15 @@ static int SystemSetParam(const char *name, const char *value, const ParamSecuri
|
||||
free(key);
|
||||
}
|
||||
PARAM_CHECK(ret == 0, return ret, "Forbit to set parameter %s", name);
|
||||
uint32_t dataIndex = 0;
|
||||
ret = WriteParam(&g_paramWorkSpace.paramSpace, name, value, &dataIndex, 0);
|
||||
PARAM_CHECK(ret == 0, return ret, "Failed to set param %d name %s %s", ret, name, value);
|
||||
ret = WritePersistParam(&g_paramWorkSpace, name, value);
|
||||
PARAM_CHECK(ret == 0, return ret, "Failed to set persist param name %s", name);
|
||||
|
||||
if (serviceCtrl) {
|
||||
PostParamTrigger(EVENT_TRIGGER_PARAM, name, value);
|
||||
} else {
|
||||
uint32_t dataIndex = 0;
|
||||
ret = WriteParam(&g_paramWorkSpace.paramSpace, name, value, &dataIndex, 0);
|
||||
PARAM_CHECK(ret == 0, return ret, "Failed to set param %d name %s %s", ret, name, value);
|
||||
ret = WritePersistParam(&g_paramWorkSpace, name, value);
|
||||
PARAM_CHECK(ret == 0, return ret, "Failed to set persist param name %s", name);
|
||||
CheckAndSendTrigger(&g_paramWorkSpace, dataIndex, name, value);
|
||||
}
|
||||
return ret;
|
||||
@@ -508,6 +511,97 @@ static void TimerCallback(ParamTaskPtr timer, void *context)
|
||||
}
|
||||
}
|
||||
|
||||
static int GetParamValueFromBuffer(const char *name, const char *buffer, char *value, int length)
|
||||
{
|
||||
char *endData = (char *)buffer + strlen(buffer);
|
||||
size_t bootLen = strlen(OHOS_BOOT);
|
||||
char *tmp = strstr(buffer, name + bootLen);
|
||||
do {
|
||||
if (tmp == NULL) {
|
||||
return -1;
|
||||
}
|
||||
tmp = tmp + strlen(name) - bootLen;
|
||||
while (tmp < endData && *tmp == ' ') {
|
||||
tmp++;
|
||||
}
|
||||
if (*tmp == '=') {
|
||||
break;
|
||||
}
|
||||
tmp = strstr(tmp + 1, name + bootLen);
|
||||
} while (tmp < endData);
|
||||
tmp++;
|
||||
size_t i = 0;
|
||||
size_t endIndex = 0;
|
||||
while (tmp < endData && *tmp == ' ') {
|
||||
tmp++;
|
||||
}
|
||||
for (; i < (size_t)length; tmp++) {
|
||||
if (tmp >= endData) {
|
||||
endIndex = i;
|
||||
break;
|
||||
}
|
||||
if (*tmp == ' ') {
|
||||
endIndex = i;
|
||||
}
|
||||
if (*tmp == '=') {
|
||||
if (endIndex != 0) { // for root=uuid=xxxx
|
||||
break;
|
||||
}
|
||||
i = 0;
|
||||
endIndex = 0;
|
||||
continue;
|
||||
}
|
||||
value[i++] = *tmp;
|
||||
}
|
||||
if (i >= (size_t)length) {
|
||||
return -1;
|
||||
}
|
||||
value[endIndex] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LoadParamFromCmdLine(void)
|
||||
{
|
||||
static const char *cmdLines[] = {
|
||||
OHOS_BOOT"hardware",
|
||||
#ifdef STARTUP_INIT_TEST
|
||||
OHOS_BOOT"mem",
|
||||
OHOS_BOOT"console",
|
||||
OHOS_BOOT"mmz",
|
||||
OHOS_BOOT"androidboot.selinux",
|
||||
OHOS_BOOT"init",
|
||||
OHOS_BOOT"root",
|
||||
OHOS_BOOT"uuid",
|
||||
OHOS_BOOT"aaaaa",
|
||||
OHOS_BOOT"rootfstype",
|
||||
OHOS_BOOT"blkdevparts",
|
||||
#endif
|
||||
};
|
||||
char *data = ReadFileData(PARAM_CMD_LINE);
|
||||
PARAM_CHECK(data != NULL, return -1, "Failed to read file %s", PARAM_CMD_LINE);
|
||||
char *value = malloc(PARAM_CONST_VALUE_LEN_MAX);
|
||||
PARAM_CHECK(value != NULL, free(data);
|
||||
return -1, "Failed to read file %s", PARAM_CMD_LINE);
|
||||
|
||||
for (size_t i = 0; i < ARRAY_LENGTH(cmdLines); i++) {
|
||||
int ret = GetParamValueFromBuffer(cmdLines[i], data, value, PARAM_CONST_VALUE_LEN_MAX);
|
||||
if (ret == 0) {
|
||||
PARAM_LOGD("Add param from cmdline %s %s", cmdLines[i], value);
|
||||
ret = CheckParamName(cmdLines[i], 0);
|
||||
PARAM_CHECK(ret == 0, return -1, "Invalid name %s", cmdLines[i]);
|
||||
uint32_t dataIndex = 0;
|
||||
ret = WriteParam(&g_paramWorkSpace.paramSpace, cmdLines[i], value, &dataIndex, 0);
|
||||
PARAM_CHECK(ret == 0, return -1, "Failed to write param %s %s", cmdLines[i], value);
|
||||
} else {
|
||||
PARAM_LOGE("Can not find arrt %s", cmdLines[i]);
|
||||
}
|
||||
}
|
||||
PARAM_LOGD("Parse cmdline finish %s", PARAM_CMD_LINE);
|
||||
free(data);
|
||||
free(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SystemWriteParam(const char *name, const char *value)
|
||||
{
|
||||
PARAM_CHECK(name != NULL && value != NULL, return -1, "The name is null");
|
||||
@@ -525,12 +619,6 @@ int SystemReadParam(const char *name, char *value, unsigned int *len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SystemTraversalParam(void (*traversalParameter)(ParamHandle handle, void *cookie), void *cookie)
|
||||
{
|
||||
PARAM_CHECK(traversalParameter != NULL, return -1, "The param is null");
|
||||
return TraversalParam(&g_paramWorkSpace, traversalParameter, cookie);
|
||||
}
|
||||
|
||||
int LoadPersistParams(void)
|
||||
{
|
||||
return LoadPersistParam(&g_paramWorkSpace);
|
||||
@@ -540,7 +628,7 @@ static int ProcessParamFile(const char *fileName, void *context)
|
||||
{
|
||||
static const char *exclude[] = {"ctl.", "selinux.restorecon_recursive"};
|
||||
uint32_t mode = *(int *)context;
|
||||
return LoadDefaultParam_(fileName, mode, exclude, sizeof(exclude) / sizeof(exclude[0]));
|
||||
return LoadDefaultParam_(fileName, mode, exclude, ARRAY_LENGTH(exclude));
|
||||
}
|
||||
|
||||
int LoadDefaultParams(const char *fileName, uint32_t mode)
|
||||
@@ -602,6 +690,9 @@ void InitParamService(void)
|
||||
auditData.dacData.mode = DAC_ALL_PERMISSION;
|
||||
ret = AddSecurityLabel(&auditData, (void *)&g_paramWorkSpace);
|
||||
PARAM_CHECK(ret == 0, return, "Failed to add default dac label");
|
||||
|
||||
// 读取cmdline的参数
|
||||
LoadParamFromCmdLine();
|
||||
}
|
||||
|
||||
static void OnPidDelete(pid_t pid)
|
||||
@@ -628,3 +719,11 @@ ParamWorkSpace *GetParamWorkSpace(void)
|
||||
{
|
||||
return &g_paramWorkSpace;
|
||||
}
|
||||
|
||||
void DumpParametersAndTriggers(void)
|
||||
{
|
||||
DumpParameters(&g_paramWorkSpace, 1);
|
||||
if (GetTriggerWorkSpace() != NULL) {
|
||||
DumpTrigger(GetTriggerWorkSpace());
|
||||
}
|
||||
}
|
||||
Regular → Executable
-1
@@ -20,7 +20,6 @@
|
||||
#include "trigger_manager.h"
|
||||
|
||||
#define MAX_CALC_PARAM 100
|
||||
#define LABEL "Trigger"
|
||||
// 申请整块能存作为计算的节点
|
||||
int CalculatorInit(LogicCalculator *calculator, int dataNumber, int dataUnit, int needCondition)
|
||||
{
|
||||
|
||||
Regular → Executable
+4
-4
@@ -27,7 +27,6 @@
|
||||
#include "param_manager.h"
|
||||
#include "trigger_checker.h"
|
||||
|
||||
#define LABEL "Trigger"
|
||||
int AddCommand(TriggerNode *trigger, uint32_t cmdKeyIndex, const char *content)
|
||||
{
|
||||
PARAM_CHECK(trigger != NULL, return -1, "trigger is null");
|
||||
@@ -44,15 +43,14 @@ int AddCommand(TriggerNode *trigger, uint32_t cmdKeyIndex, const char *content)
|
||||
int ret = memcpy_s(node->content, size, content, strlen(content));
|
||||
node->content[strlen(content)] = '\0';
|
||||
PARAM_CHECK(ret == EOK, free(node);
|
||||
return -1, "Failed to copy command");
|
||||
return 0, "Failed to copy command");
|
||||
}
|
||||
// 插入队列
|
||||
if (trigger->firstCmd == NULL) {
|
||||
trigger->firstCmd = node;
|
||||
trigger->lastCmd = node;
|
||||
} else {
|
||||
PARAM_CHECK(trigger->lastCmd != NULL, free(node);
|
||||
return -1, "Invalid last cmd");
|
||||
PARAM_CHECK(trigger->lastCmd != NULL, return 0, "Invalid last cmd");
|
||||
trigger->lastCmd->next = node;
|
||||
trigger->lastCmd = node;
|
||||
}
|
||||
@@ -257,6 +255,8 @@ static int CheckParamTriggerMatch(TriggerWorkSpace *workSpace, LogicCalculator *
|
||||
static int CheckOtherTriggerMatch(TriggerWorkSpace *workSpace, LogicCalculator *calculator,
|
||||
TriggerNode *trigger, const char *content, uint32_t contentSize)
|
||||
{
|
||||
UNUSED(content);
|
||||
UNUSED(contentSize);
|
||||
const char *condition = GetTriggerCondition(workSpace, trigger);
|
||||
return ComputeCondition(calculator, condition);
|
||||
}
|
||||
|
||||
Regular → Executable
+60
-22
@@ -12,20 +12,58 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <time.h>
|
||||
#include "init_cmds.h"
|
||||
#include "init_param.h"
|
||||
#include "init_service_manager.h"
|
||||
#include "init_utils.h"
|
||||
#include "param_manager.h"
|
||||
#include "param_utils.h"
|
||||
#include "trigger_checker.h"
|
||||
#include "trigger_manager.h"
|
||||
|
||||
#define LABEL "Trigger"
|
||||
#define MAX_TRIGGER_COUNT_RUN_ONCE 20
|
||||
static TriggerWorkSpace g_triggerWorkSpace = {};
|
||||
|
||||
#ifdef PARAM_TEST
|
||||
#define MAX_COUNT 1000
|
||||
#define READ_DURATION 100000
|
||||
#define TEST_PARAM_NAME "test.random.read.001"
|
||||
static void AddTestTrigger(const TriggerWorkSpace *workSpace)
|
||||
{
|
||||
TriggerHeader *header = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM];
|
||||
TriggerNode *trigger = AddTrigger(header, "param:test.randrom.test.start=1", "test.randrom.test.start=1", 0);
|
||||
PARAM_CHECK(trigger != NULL, return, "Failed to create test trigger");
|
||||
int cmdKeyIndex = 0;
|
||||
GetMatchCmd("setparam ", &cmdKeyIndex);
|
||||
int ret = AddCommand(trigger, (uint32_t)CMD_INDEX_FOR_PARA_TEST, NULL);
|
||||
PARAM_CHECK(ret == 0, return, "Failed to add command");
|
||||
}
|
||||
|
||||
static void TestTimerCallback(ParamTaskPtr timer, void *context)
|
||||
{
|
||||
srand((unsigned)time(NULL));
|
||||
char buffer[32] = { 0 };
|
||||
static int index = 0;
|
||||
index++;
|
||||
if (index >= MAX_COUNT) {
|
||||
ParamTaskClose(timer);
|
||||
}
|
||||
static uint32_t value = 0;
|
||||
int count = 0;
|
||||
while (count < MAX_COUNT) {
|
||||
int wait = rand() / READ_DURATION + READ_DURATION; // 100ms
|
||||
sprintf_s(buffer, sizeof(buffer), "%u", value);
|
||||
PARAM_LOGI("set param name: %s, value %s", TEST_PARAM_NAME, buffer);
|
||||
SystemWriteParam(TEST_PARAM_NAME, buffer);
|
||||
usleep(wait);
|
||||
count++;
|
||||
value++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void DoTriggerExec(const char *triggerName)
|
||||
{
|
||||
PARAM_CHECK(triggerName != NULL, return, "Invalid param");
|
||||
@@ -45,17 +83,16 @@ static void DoCmdExec(const TriggerNode *trigger, const CommandNode *cmd, const
|
||||
extData->excuteCmd(extData, cmd->cmdKeyIndex, content);
|
||||
}
|
||||
return;
|
||||
}
|
||||
const char *cmdName = GetCmdKey(cmd->cmdKeyIndex);
|
||||
if (cmdName == NULL) {
|
||||
return;
|
||||
}
|
||||
if (strncmp(cmdName, TRIGGER_CMD, strlen(TRIGGER_CMD)) == 0) {
|
||||
DoTriggerExec(cmd->content);
|
||||
#ifdef PARAM_TEST
|
||||
} else if (cmd->cmdKeyIndex == CMD_INDEX_FOR_PARA_TEST) {
|
||||
ParamTaskPtr timer = NULL;
|
||||
ParamTimerCreate(&timer, TestTimerCallback, NULL);
|
||||
ParamTimerStart(timer, READ_DURATION, MAX_COUNT);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
#ifndef STARTUP_INIT_TEST
|
||||
DoCmdByName(cmdName, cmd->content);
|
||||
DoCmdByIndex(cmd->cmdKeyIndex, cmd->content);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -162,7 +199,7 @@ static const char *GetCmdInfo(const char *content, uint32_t contentSize, char **
|
||||
static const char *ctrlCmds[][2] = {
|
||||
{"reboot", "reboot "}
|
||||
};
|
||||
uint32_t index = 0;
|
||||
int index = 0;
|
||||
for (size_t i = 0; i < sizeof(ctrlCmds) / sizeof(ctrlCmds[0]); i++) {
|
||||
if (strncmp(content, ctrlCmds[i][0], strlen(ctrlCmds[i][0])) == 0) {
|
||||
*cmdParam = (char *)content;
|
||||
@@ -231,7 +268,7 @@ static int GetTriggerType(const char *type)
|
||||
"pre-init", "boot", "early-init", "init", "early-init", "late-init", "post-init",
|
||||
"early-fs", "post-fs", "late-fs", "post-fs-data"
|
||||
};
|
||||
for (size_t i = 0; i < sizeof(triggerTypeStr) / sizeof(char *); i++) {
|
||||
for (size_t i = 0; i < ARRAY_LENGTH(triggerTypeStr); i++) {
|
||||
if (strcmp(triggerTypeStr[i], type) == 0) {
|
||||
return TRIGGER_BOOT;
|
||||
}
|
||||
@@ -267,7 +304,7 @@ static int ParseTrigger_(const TriggerWorkSpace *workSpace, const cJSON *trigger
|
||||
PARAM_CHECK(cmdLinesCnt > 0, return -1, "Command array size must positive %s", name);
|
||||
|
||||
int ret;
|
||||
uint32_t cmdKeyIndex = 0;
|
||||
int cmdKeyIndex = 0;
|
||||
for (int i = 0; (i < cmdLinesCnt) && (i < TRIGGER_MAX_CMD); ++i) {
|
||||
char *cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdItems, i));
|
||||
PARAM_CHECK(cmdLineStr != NULL, continue, "Command is null");
|
||||
@@ -277,9 +314,9 @@ static int ParseTrigger_(const TriggerWorkSpace *workSpace, const cJSON *trigger
|
||||
PARAM_CHECK(matchCmd != NULL, continue, "Command not support %s", cmdLineStr);
|
||||
size_t matchLen = strlen(matchCmd);
|
||||
if (matchLen == cmdLineLen) {
|
||||
ret = AddCommand(trigger, cmdKeyIndex, NULL);
|
||||
ret = AddCommand(trigger, (uint32_t)cmdKeyIndex, NULL);
|
||||
} else {
|
||||
ret = AddCommand(trigger, cmdKeyIndex, cmdLineStr + matchLen);
|
||||
ret = AddCommand(trigger, (uint32_t)cmdKeyIndex, cmdLineStr + matchLen);
|
||||
}
|
||||
PARAM_CHECK(ret == 0, continue, "Failed to add command %s", cmdLineStr);
|
||||
}
|
||||
@@ -299,6 +336,10 @@ int ParseTriggerConfig(const cJSON *fileRoot)
|
||||
cJSON *item = cJSON_GetArrayItem(triggers, i);
|
||||
ParseTrigger_(&g_triggerWorkSpace, item);
|
||||
}
|
||||
#ifdef PARAM_TEST
|
||||
// for test
|
||||
AddTestTrigger(&g_triggerWorkSpace);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -312,15 +353,12 @@ int InitTriggerWorkSpace(void)
|
||||
PARAM_CHECK(g_triggerWorkSpace.eventHandle != NULL, return -1, "Failed to event handle");
|
||||
|
||||
// executeQueue
|
||||
g_triggerWorkSpace.executeQueue.executeQueue = malloc(TRIGGER_EXECUTE_QUEUE * sizeof(TriggerNode *));
|
||||
g_triggerWorkSpace.executeQueue.executeQueue = calloc(1, TRIGGER_EXECUTE_QUEUE * sizeof(TriggerNode *));
|
||||
PARAM_CHECK(g_triggerWorkSpace.executeQueue.executeQueue != NULL,
|
||||
return -1, "Failed to alloc memory for executeQueue");
|
||||
g_triggerWorkSpace.executeQueue.queueCount = TRIGGER_EXECUTE_QUEUE;
|
||||
g_triggerWorkSpace.executeQueue.startIndex = 0;
|
||||
g_triggerWorkSpace.executeQueue.endIndex = 0;
|
||||
PARAM_CHECK(g_triggerWorkSpace.executeQueue.executeQueue != NULL,
|
||||
return -1, "Failed to alloc memory for executeQueue");
|
||||
int ret = memset_s(g_triggerWorkSpace.executeQueue.executeQueue,
|
||||
TRIGGER_EXECUTE_QUEUE * sizeof(TriggerNode *), 0, TRIGGER_EXECUTE_QUEUE * sizeof(TriggerNode *));
|
||||
PARAM_CHECK(ret == EOK, return -1, "Failed to memset for executeQueue");
|
||||
|
||||
// normal trigger
|
||||
for (size_t i = 0; i < sizeof(g_triggerWorkSpace.triggerHead) / sizeof(g_triggerWorkSpace.triggerHead[0]); i++) {
|
||||
|
||||
@@ -88,7 +88,7 @@ WatcherManagerKits::ParamWatcherKitPtr WatcherManagerKits::GetParamWatcher(const
|
||||
void WatcherManagerKits::SetParamWatcher(const std::string &keyPrefix, ParamWatcherKitPtr watcher)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (watchers_.find(keyPrefix) != watchers_.end()) {
|
||||
if (watchers_.find(keyPrefix) == watchers_.end()) {
|
||||
watchers_[keyPrefix] = watcher;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace init_param {
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
#ifndef LABEL
|
||||
#define LABEL "Watcher"
|
||||
#define LABEL "ParameterWatcher"
|
||||
#endif
|
||||
|
||||
#define WATCHER_LOGI(fmt, ...) STARTUP_LOGI(LABEL, fmt, ##__VA_ARGS__)
|
||||
|
||||
@@ -32,9 +32,9 @@ const static int32_t INVALID_SOCKET = -1;
|
||||
uint32_t WatcherManager::AddWatcher(const std::string &keyPrefix, const sptr<IWatcher> &watcher)
|
||||
{
|
||||
WATCHER_CHECK(watcher != nullptr, return 0, "Invalid remove watcher for %s", keyPrefix.c_str());
|
||||
if (watcherId_ == 0) {
|
||||
watcherId_++;
|
||||
}
|
||||
watcherId_++;
|
||||
WATCHER_LOGD("AddWatcher begin %s", keyPrefix.c_str());
|
||||
|
||||
ParamWatcherPtr paramWather = std::make_shared<ParamWatcher>(watcherId_, watcher);
|
||||
WATCHER_CHECK(paramWather != nullptr, return 0, "Failed to create watcher for %s", keyPrefix.c_str());
|
||||
WatcherGroupPtr group = GetWatcherGroup(keyPrefix);
|
||||
@@ -44,6 +44,7 @@ uint32_t WatcherManager::AddWatcher(const std::string &keyPrefix, const sptr<IWa
|
||||
WATCHER_CHECK(group != nullptr, return 0, "Failed to create group for %s", keyPrefix.c_str());
|
||||
AddWatcherGroup(keyPrefix, group);
|
||||
|
||||
WATCHER_LOGD("AddWatcher 222 begin %s", keyPrefix.c_str());
|
||||
if (group->Emptry()) {
|
||||
StartLoop();
|
||||
SendMessage(group, MSG_ADD_WATCHER);
|
||||
@@ -76,19 +77,19 @@ int WatcherManager::SendMessage(WatcherGroupPtr group, int type)
|
||||
PARAM_CHECK(request != NULL, return PARAM_CODE_ERROR, "Failed to malloc for watch");
|
||||
request->id.watcherId = group->GetGroupId();
|
||||
request->msgSize = sizeof(ParamMessage);
|
||||
do {
|
||||
int fd = GetServerFd(false);
|
||||
if (fd != INVALID_SOCKET) {
|
||||
ssize_t sendLen = send(serverFd_, (char *)request, request->msgSize, 0);
|
||||
if (sendLen > 0) {
|
||||
PARAM_LOGD("SendMessage key: %s %d success", group->GetKeyPrefix().c_str(), type);
|
||||
break;
|
||||
}
|
||||
|
||||
WATCHER_LOGD("SendMessage %s", group->GetKeyPrefix().c_str());
|
||||
int fd = GetServerFd(false);
|
||||
if (fd != INVALID_SOCKET) {
|
||||
ssize_t sendLen = send(serverFd_, (char *)request, request->msgSize, 0);
|
||||
if (sendLen > 0) {
|
||||
PARAM_LOGD("SendMessage key: %s %d success", group->GetKeyPrefix().c_str(), type);
|
||||
} else {
|
||||
PARAM_LOGD("SendMessage key: %s %d fail", group->GetKeyPrefix().c_str(), type);
|
||||
}
|
||||
// fail, try again
|
||||
PARAM_LOGE("Failed to connect server %s, try again", PIPE_NAME);
|
||||
fd = GetServerFd(true);
|
||||
} while (1);
|
||||
} else {
|
||||
PARAM_LOGD("SendMessage key: %s %d fail", group->GetKeyPrefix().c_str(), type);
|
||||
}
|
||||
free(request);
|
||||
return 0;
|
||||
}
|
||||
@@ -97,6 +98,7 @@ void WatcherManager::ProcessWatcherMessage(const std::vector<char> &buffer, uint
|
||||
{
|
||||
ParamMessage *msg = (ParamMessage *)buffer.data();
|
||||
PARAM_CHECK(msg != NULL, return, "Invalid msg");
|
||||
PARAM_LOGD("ProcessWatcherMessage %d", msg->type);
|
||||
uint32_t offset = 0;
|
||||
if (msg->type != MSG_NOTIFY_PARAM) {
|
||||
return;
|
||||
@@ -123,18 +125,22 @@ WatcherManager::WatcherGroupPtr WatcherManager::GetWatcherGroup(uint32_t groupId
|
||||
|
||||
WatcherManager::WatcherGroupPtr WatcherManager::GetWatcherGroup(const std::string &keyPrefix)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(watcherMutex_);
|
||||
if (groupMap_.find(keyPrefix) == groupMap_.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return GetWatcherGroup(groupMap_[keyPrefix]);
|
||||
uint32_t groupId = groupMap_[keyPrefix];
|
||||
if (watcherGroups_.find(groupId) != watcherGroups_.end()) {
|
||||
return watcherGroups_[groupId];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void WatcherManager::AddWatcherGroup(const std::string &keyPrefix, WatcherGroupPtr group)
|
||||
{
|
||||
uint32_t groupId = group->GetGroupId();
|
||||
groupMap_[keyPrefix] = groupId;
|
||||
|
||||
std::lock_guard<std::mutex> lock(watcherMutex_);
|
||||
groupMap_[keyPrefix] = groupId;
|
||||
if (watcherGroups_.find(groupId) != watcherGroups_.end()) {
|
||||
return;
|
||||
}
|
||||
@@ -143,9 +149,9 @@ void WatcherManager::AddWatcherGroup(const std::string &keyPrefix, WatcherGroupP
|
||||
|
||||
void WatcherManager::DelWatcherGroup(WatcherGroupPtr group)
|
||||
{
|
||||
groupMap_[group->GetKeyPrefix()] = 0;
|
||||
std::lock_guard<std::mutex> lock(watcherMutex_);
|
||||
watcherGroups_[group->GetGroupId()] = nullptr;
|
||||
groupMap_.erase(group->GetKeyPrefix());
|
||||
watcherGroups_.erase(group->GetGroupId());
|
||||
}
|
||||
|
||||
void WatcherManager::WatcherGroup::AddWatcher(const ParamWatcherPtr &watcher)
|
||||
@@ -156,7 +162,7 @@ void WatcherManager::WatcherGroup::AddWatcher(const ParamWatcherPtr &watcher)
|
||||
void WatcherManager::WatcherGroup::DelWatcher(uint32_t watcherId)
|
||||
{
|
||||
if (watchers_.find(watcherId) != watchers_.end()) {
|
||||
watchers_[watcherId] = nullptr;
|
||||
watchers_.erase(watcherId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,6 +197,7 @@ void WatcherManager::SendLocalChange(const std::string &keyPrefix, ParamWatcherP
|
||||
ParamWatcherPtr watcher;
|
||||
std::string keyPrefix;
|
||||
};
|
||||
PARAM_LOGD("SendLocalChange key %s ", keyPrefix.c_str());
|
||||
std::vector<char> buffer(PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX);
|
||||
struct Context context = {buffer.data(), watcher, keyPrefix};
|
||||
// walk watcher
|
||||
@@ -211,7 +218,7 @@ void WatcherManager::RunLoop()
|
||||
{
|
||||
const int32_t RECV_BUFFER_MAX = 5 * 1024;
|
||||
std::vector<char> buffer(RECV_BUFFER_MAX, 0);
|
||||
while (!stop) {
|
||||
while (!stop_) {
|
||||
int fd = GetServerFd(false);
|
||||
ssize_t recvLen = recv(fd, buffer.data(), RECV_BUFFER_MAX, 0);
|
||||
if (recvLen <= 0) {
|
||||
@@ -222,6 +229,9 @@ void WatcherManager::RunLoop()
|
||||
PARAM_LOGE("Failed to recv msg from server errno %d", errno);
|
||||
}
|
||||
PARAM_LOGD("Recv msg from server");
|
||||
if (stop_) {
|
||||
break;
|
||||
}
|
||||
if (recvLen >= (ssize_t)sizeof(ParamMessage)) {
|
||||
ProcessWatcherMessage(buffer, recvLen);
|
||||
}
|
||||
@@ -240,6 +250,7 @@ void WatcherManager::StartLoop()
|
||||
int WatcherManager::GetServerFd(bool retry)
|
||||
{
|
||||
const int32_t sleepTime = 2000;
|
||||
const int32_t maxRetry = 10;
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (retry && serverFd_ != INVALID_SOCKET) {
|
||||
close(serverFd_);
|
||||
@@ -251,9 +262,10 @@ int WatcherManager::GetServerFd(bool retry)
|
||||
struct timeval time {};
|
||||
time.tv_sec = 1;
|
||||
time.tv_usec = 0;
|
||||
int32_t retryCount = 0;
|
||||
do {
|
||||
serverFd_ = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
int ret = ConntectServer(serverFd_, PIPE_NAME);
|
||||
int ret = ConntectServer(serverFd_, CLIENT_PIPE_NAME);
|
||||
if (ret != 0) {
|
||||
close(serverFd_);
|
||||
serverFd_ = INVALID_SOCKET;
|
||||
@@ -262,7 +274,9 @@ int WatcherManager::GetServerFd(bool retry)
|
||||
(void)setsockopt(serverFd_, SOL_SOCKET, SO_RCVTIMEO, &time, sizeof(struct timeval));
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
retryCount++;
|
||||
} while (retryCount < maxRetry);
|
||||
PARAM_LOGD("SendMessage retryCount %d", retryCount);
|
||||
return serverFd_;
|
||||
}
|
||||
|
||||
@@ -276,10 +290,10 @@ void WatcherManager::OnStart()
|
||||
return;
|
||||
}
|
||||
|
||||
void WatcherManager::OnStop()
|
||||
void WatcherManager::StopLoop()
|
||||
{
|
||||
PARAM_LOGI("WatcherManager OnStop");
|
||||
stop = true;
|
||||
PARAM_LOGI("WatcherManager StopLoop");
|
||||
stop_ = true;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
close(serverFd_);
|
||||
@@ -291,5 +305,10 @@ void WatcherManager::OnStop()
|
||||
pRecvThread_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void WatcherManager::OnStop()
|
||||
{
|
||||
StopLoop();
|
||||
}
|
||||
} // namespace init_param
|
||||
} // namespace OHOS
|
||||
|
||||
@@ -90,6 +90,7 @@ public:
|
||||
|
||||
uint32_t AddWatcher(const std::string &keyPrefix, const sptr<IWatcher> &watcher) override;
|
||||
int32_t DelWatcher(const std::string &keyPrefix, uint32_t watcherId) override;
|
||||
void StopLoop();
|
||||
protected:
|
||||
void OnStart() override;
|
||||
void OnStop() override;
|
||||
@@ -111,7 +112,7 @@ private:
|
||||
std::mutex watcherMutex_;
|
||||
int serverFd_ { -1 };
|
||||
std::thread *pRecvThread_ { nullptr };
|
||||
std::atomic<bool> stop { false };
|
||||
std::atomic<bool> stop_ { false };
|
||||
std::map<std::string, uint32_t> groupMap_ {};
|
||||
std::map<uint32_t, WatcherGroupPtr> watcherGroups_ {};
|
||||
};
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init_capability.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#if defined OHOS_LITE && !defined __LINUX__
|
||||
#include <sys/capability.h>
|
||||
#else
|
||||
#include <linux/capability.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "init_log.h"
|
||||
#include "init_perms.h"
|
||||
#include "init_utils.h"
|
||||
|
||||
#define MAX_CAPS_CNT_FOR_ONE_SERVICE 100
|
||||
|
||||
struct CapStrCapNum {
|
||||
char *capStr;
|
||||
int CapNum;
|
||||
};
|
||||
|
||||
static const struct CapStrCapNum g_capStrCapNum[] = {
|
||||
{"CHOWN", CAP_CHOWN},
|
||||
{"DAC_OVERRIDE", CAP_DAC_OVERRIDE},
|
||||
{"DAC_READ_SEARCH", CAP_DAC_READ_SEARCH},
|
||||
{"FOWNER", CAP_FOWNER},
|
||||
{"FSETID", CAP_FSETID},
|
||||
{"KILL", CAP_KILL},
|
||||
{"SETGID", CAP_SETGID},
|
||||
{"SETUID", CAP_SETUID},
|
||||
{"SETPCAP", CAP_SETPCAP},
|
||||
{"LINUX_IMMUTABLE", CAP_LINUX_IMMUTABLE},
|
||||
{"NET_BIND_SERVICE", CAP_NET_BIND_SERVICE},
|
||||
{"NET_BROADCAST", CAP_NET_BROADCAST},
|
||||
{"NET_ADMIN", CAP_NET_ADMIN},
|
||||
{"NET_RAW", CAP_NET_RAW},
|
||||
{"IPC_LOCK", CAP_IPC_LOCK},
|
||||
{"IPC_OWNER", CAP_IPC_OWNER},
|
||||
{"SYS_MODULE", CAP_SYS_MODULE},
|
||||
{"SYS_RAWIO", CAP_SYS_RAWIO},
|
||||
{"SYS_CHROOT", CAP_SYS_CHROOT},
|
||||
{"SYS_PTRACE", CAP_SYS_PTRACE},
|
||||
{"SYS_PACCT", CAP_SYS_PACCT},
|
||||
{"SYS_ADMIN", CAP_SYS_ADMIN},
|
||||
{"SYS_BOOT", CAP_SYS_BOOT},
|
||||
{"SYS_NICE", CAP_SYS_NICE},
|
||||
{"SYS_RESOURCE", CAP_SYS_RESOURCE},
|
||||
{"SYS_TIME", CAP_SYS_TIME},
|
||||
{"SYS_TTY_CONFIG", CAP_SYS_TTY_CONFIG},
|
||||
{"MKNOD", CAP_MKNOD},
|
||||
{"LEASE", CAP_LEASE},
|
||||
{"AUDIT_WRITE", CAP_AUDIT_WRITE},
|
||||
{"AUDIT_CONTROL", CAP_AUDIT_CONTROL},
|
||||
{"SETFCAP", CAP_SETFCAP},
|
||||
{"MAC_OVERRIDE", CAP_MAC_OVERRIDE},
|
||||
{"MAC_ADMIN", CAP_MAC_ADMIN},
|
||||
{"SYSLOG", CAP_SYSLOG},
|
||||
{"WAKE_ALARM", CAP_WAKE_ALARM},
|
||||
{"BLOCK_SUSPEND", CAP_BLOCK_SUSPEND},
|
||||
{"AUDIT_READ", CAP_AUDIT_READ},
|
||||
};
|
||||
|
||||
static int GetServiceStringCaps(const cJSON* filedJ, Service* curServ) // string form
|
||||
{
|
||||
unsigned int i = 0;
|
||||
for (; i < curServ->servPerm.capsCnt; ++i) {
|
||||
if (cJSON_GetArrayItem(filedJ, i) == NULL || !cJSON_GetStringValue(cJSON_GetArrayItem(filedJ, i))
|
||||
|| strlen(cJSON_GetStringValue(cJSON_GetArrayItem(filedJ, i))) <= 0) { // check all errors
|
||||
INIT_LOGE("service=%s, parse item[%d] as string, error.", curServ->name, i);
|
||||
break;
|
||||
}
|
||||
char* fieldStr = cJSON_GetStringValue(cJSON_GetArrayItem(filedJ, i));
|
||||
if (fieldStr == NULL) {
|
||||
INIT_LOGE("fieldStr is NULL");
|
||||
break;
|
||||
}
|
||||
int mapSize = ARRAY_LENGTH(g_capStrCapNum); // search
|
||||
int j = 0;
|
||||
for (; j < mapSize; j++) {
|
||||
if (!strcmp(fieldStr, g_capStrCapNum[j].capStr)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j < mapSize) {
|
||||
curServ->servPerm.caps[i] = g_capStrCapNum[j].CapNum;
|
||||
} else {
|
||||
INIT_LOGE("service=%s, CapbilityName=%s, error.", curServ->name, fieldStr);
|
||||
break;
|
||||
}
|
||||
if (curServ->servPerm.caps[i] > CAP_LAST_CAP && curServ->servPerm.caps[i] != FULL_CAP) {
|
||||
// resources will be released by function: ReleaseServiceMem
|
||||
INIT_LOGE("service=%s, cap = %d, error.", curServ->name, curServ->servPerm.caps[i]);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
}
|
||||
int ret = ((i == curServ->servPerm.capsCnt) ? SERVICE_SUCCESS : SERVICE_FAILURE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int GetServiceCaps(const cJSON* curArrItem, Service* curServ)
|
||||
{
|
||||
if (curServ == NULL || curArrItem == NULL) {
|
||||
INIT_LOGE("GetServiceCaps failed, curServ or curArrItem is NULL.");
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->servPerm.capsCnt = 0;
|
||||
curServ->servPerm.caps = NULL;
|
||||
cJSON* filedJ = cJSON_GetObjectItem(curArrItem, "caps");
|
||||
if (filedJ == NULL) {
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
if (!cJSON_IsArray(filedJ)) {
|
||||
INIT_LOGE("service=%s, caps is not a list, error.", curServ->name);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
// caps array does not exist, means do not need any capability
|
||||
int capsCnt = cJSON_GetArraySize(filedJ);
|
||||
if (capsCnt <= 0) {
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
if (capsCnt > MAX_CAPS_CNT_FOR_ONE_SERVICE) {
|
||||
INIT_LOGE("service=%s, too many caps[cnt %d] for one service, max is %d.",
|
||||
curServ->name, capsCnt, MAX_CAPS_CNT_FOR_ONE_SERVICE);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->servPerm.caps = (unsigned int*)malloc(sizeof(unsigned int) * capsCnt);
|
||||
if (curServ->servPerm.caps == NULL) {
|
||||
INIT_LOGE("GetServiceCaps, service=%s, malloc error.", curServ->name);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->servPerm.capsCnt = capsCnt;
|
||||
int i = 0;
|
||||
for (; i < capsCnt; ++i) { // number form
|
||||
cJSON* capJ = cJSON_GetArrayItem(filedJ, i);
|
||||
if (!cJSON_IsNumber(capJ) || cJSON_GetNumberValue(capJ) < 0) {
|
||||
// resources will be released by function: ReleaseServiceMem
|
||||
break;
|
||||
}
|
||||
curServ->servPerm.caps[i] = (unsigned int)cJSON_GetNumberValue(capJ);
|
||||
if (curServ->servPerm.caps[i] > CAP_LAST_CAP && curServ->servPerm.caps[i] != FULL_CAP) {
|
||||
// resources will be released by function: ReleaseServiceMem
|
||||
INIT_LOGE("service=%s, caps = %d, error.", curServ->name, curServ->servPerm.caps[i]);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
}
|
||||
if (i == capsCnt) {
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
int ret = GetServiceStringCaps(filedJ, curServ);
|
||||
return ret;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init_import.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include "cJSON.h"
|
||||
#include "init_cmds.h"
|
||||
#include "init_log.h"
|
||||
#include "init_read_cfg.h"
|
||||
#include "securec.h"
|
||||
|
||||
#ifndef OHOS_LITE
|
||||
static int ExtractCfgFile(char **cfgFile, const char *content)
|
||||
{
|
||||
if ((!cfgFile) || (!content)) {
|
||||
return -1;
|
||||
}
|
||||
size_t cfgFileLen = strlen(content) + MAX_PARAM_VALUE_LEN + 1;
|
||||
if (cfgFileLen <= 0) {
|
||||
return -1;
|
||||
}
|
||||
if ((*cfgFile = malloc(cfgFileLen)) == NULL) {
|
||||
INIT_LOGW("Failed to allocate memory to import cfg file. err = %d", errno);
|
||||
return -1;
|
||||
}
|
||||
return GetParamValue(content, *cfgFile, cfgFileLen);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ParseAllImports(const cJSON *root)
|
||||
{
|
||||
cJSON *importAttr = cJSON_GetObjectItemCaseSensitive(root, "import");
|
||||
char *cfgFile = NULL;
|
||||
if (!cJSON_IsArray(importAttr)) {
|
||||
return;
|
||||
}
|
||||
int importAttrSize = cJSON_GetArraySize(importAttr);
|
||||
|
||||
for (int i = 0; i < importAttrSize; i++) {
|
||||
cJSON *importItem = cJSON_GetArrayItem(importAttr, i);
|
||||
if (!cJSON_IsString(importItem)) {
|
||||
INIT_LOGE("Invalid type of import item. should be string");
|
||||
return;
|
||||
}
|
||||
char *importContent = cJSON_GetStringValue(importItem);
|
||||
if (importContent == NULL) {
|
||||
INIT_LOGE("cannot get import config file");
|
||||
return;
|
||||
}
|
||||
// Only OHOS L2 support parameter.
|
||||
#ifndef OHOS_LITE
|
||||
if (ExtractCfgFile(&cfgFile, importContent) < 0) {
|
||||
INIT_LOGW("Failed to import from %s", importContent);
|
||||
if (cfgFile != NULL) {
|
||||
free(cfgFile);
|
||||
cfgFile = NULL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
cfgFile = importContent;
|
||||
#endif
|
||||
INIT_LOGI("Import %s...", cfgFile);
|
||||
ParseInitCfg(cfgFile);
|
||||
// Do not forget to free memory.
|
||||
free(cfgFile);
|
||||
cfgFile = NULL;
|
||||
}
|
||||
INIT_LOGD("parse import file done");
|
||||
return;
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init_read_cfg.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <linux/capability.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "init_import.h"
|
||||
#include "init_jobs.h"
|
||||
#include "init_log.h"
|
||||
#include "init_perms.h"
|
||||
#include "init_service_manager.h"
|
||||
#include "init_utils.h"
|
||||
|
||||
#ifndef OHOS_LITE
|
||||
#include "init_param.h"
|
||||
#endif
|
||||
#include "securec.h"
|
||||
#ifndef __LINUX__
|
||||
#ifdef OHOS_LITE
|
||||
#include "init_stage.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define FILE_NAME_MAX_SIZE 100
|
||||
static void ParseInitCfgContents(const cJSON *root)
|
||||
{
|
||||
if (root == NULL) {
|
||||
INIT_LOGE("ParseInitCfgContents root is NULL");
|
||||
return;
|
||||
}
|
||||
// parse services
|
||||
ParseAllServices(root);
|
||||
#ifdef OHOS_LITE
|
||||
// parse jobs
|
||||
ParseAllJobs(root);
|
||||
#else
|
||||
ParseTriggerConfig(root);
|
||||
#endif
|
||||
|
||||
// parse imports
|
||||
ParseAllImports(root);
|
||||
}
|
||||
|
||||
void ParseInitCfg(const char *configFile)
|
||||
{
|
||||
if (configFile == NULL || *configFile == '\0') {
|
||||
INIT_LOGE("Invalid config file");
|
||||
return;
|
||||
}
|
||||
|
||||
char *fileBuf = ReadFileToBuf(configFile);
|
||||
if (fileBuf == NULL) {
|
||||
INIT_LOGE("Read %s failed", configFile);
|
||||
return;
|
||||
}
|
||||
cJSON* fileRoot = cJSON_Parse(fileBuf);
|
||||
free(fileBuf);
|
||||
fileBuf = NULL;
|
||||
|
||||
if (fileRoot == NULL) {
|
||||
INIT_LOGE("InitReadCfg, parse failed! please check file %s format.", configFile);
|
||||
return;
|
||||
}
|
||||
ParseInitCfgContents(fileRoot);
|
||||
// Release JSON object
|
||||
cJSON_Delete(fileRoot);
|
||||
return;
|
||||
}
|
||||
|
||||
static void ReadCfgs(const char *dirPath)
|
||||
{
|
||||
DIR *pDir = opendir(dirPath);
|
||||
if (pDir == NULL) {
|
||||
INIT_LOGE("ParseCfgs open cfg dir :%s failed.%d", dirPath, errno);
|
||||
return;
|
||||
}
|
||||
struct dirent *dp;
|
||||
while ((dp = readdir(pDir)) != NULL) {
|
||||
char fileName[FILE_NAME_MAX_SIZE];
|
||||
if (snprintf_s(fileName, FILE_NAME_MAX_SIZE, FILE_NAME_MAX_SIZE - 1, "%s/%s", dirPath, dp->d_name) == -1) {
|
||||
INIT_LOGE("ParseCfgs snprintf_s failed.");
|
||||
closedir(pDir);
|
||||
return;
|
||||
}
|
||||
struct stat st;
|
||||
if (stat(fileName, &st) == 0) {
|
||||
if (strstr(dp->d_name, ".cfg") == NULL) {
|
||||
continue;
|
||||
}
|
||||
INIT_LOGI("ReadCfgs :%s from %s success.", fileName, dirPath);
|
||||
ParseInitCfg(fileName);
|
||||
}
|
||||
}
|
||||
closedir(pDir);
|
||||
return;
|
||||
}
|
||||
|
||||
static void ParseOtherCfgs()
|
||||
{
|
||||
ReadCfgs("/system/etc/init");
|
||||
return;
|
||||
}
|
||||
|
||||
void InitReadCfg()
|
||||
{
|
||||
#ifndef OHOS_LITE
|
||||
InitParamService();
|
||||
LoadDefaultParams("/system/etc/param/ohos_const", LOAD_PARAM_NORMAL);
|
||||
LoadDefaultParams("/vendor/etc/param", LOAD_PARAM_NORMAL);
|
||||
LoadDefaultParams("/system/etc/param", LOAD_PARAM_ONLY_ADD);
|
||||
#endif
|
||||
ParseInitCfg(INIT_CONFIGURATION_FILE);
|
||||
ParseOtherCfgs();
|
||||
INIT_LOGI("Parse init config file done.");
|
||||
#ifdef OHOS_SERVICE_DUMP
|
||||
DumpAllServices();
|
||||
#endif
|
||||
|
||||
#ifdef OHOS_LITE
|
||||
// do jobs
|
||||
DoJob("pre-init");
|
||||
#ifndef __LINUX__
|
||||
TriggerStage(EVENT1, EVENT1_WAITTIME, QS_STAGE1);
|
||||
#endif
|
||||
|
||||
DoJob("init");
|
||||
#ifndef __LINUX__
|
||||
TriggerStage(EVENT2, EVENT2_WAITTIME, QS_STAGE2);
|
||||
#endif
|
||||
|
||||
DoJob("post-init");
|
||||
#ifndef __LINUX__
|
||||
TriggerStage(EVENT3, EVENT3_WAITTIME, QS_STAGE3);
|
||||
|
||||
InitStageFinished();
|
||||
#endif
|
||||
ReleaseAllJobs();
|
||||
#else
|
||||
PostTrigger(EVENT_TRIGGER_BOOT, "pre-init", strlen("pre-init"));
|
||||
|
||||
PostTrigger(EVENT_TRIGGER_BOOT, "init", strlen("init"));
|
||||
|
||||
PostTrigger(EVENT_TRIGGER_BOOT, "post-init", strlen("post-init"));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,216 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init_reboot.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <unistd.h>
|
||||
#include "init_log.h"
|
||||
#include "init_service.h"
|
||||
#include "init_service_manager.h"
|
||||
#include "init_utils.h"
|
||||
#include "securec.h"
|
||||
|
||||
#define MAX_VALUE_LENGTH 500
|
||||
#define MAX_COMMAND_SIZE 20
|
||||
#define MAX_UPDATE_SIZE 100
|
||||
|
||||
struct RBMiscUpdateMessage {
|
||||
char command[MAX_COMMAND_SIZE];
|
||||
char update[MAX_UPDATE_SIZE];
|
||||
};
|
||||
|
||||
static bool RBMiscWriteUpdaterMessage(const char *path, const struct RBMiscUpdateMessage *boot)
|
||||
{
|
||||
if (path == NULL || boot == NULL) {
|
||||
INIT_LOGE("path or boot is NULL.");
|
||||
return false;
|
||||
}
|
||||
|
||||
char realPath[PATH_MAX] = {0};
|
||||
if (Realpath(path, realPath, sizeof(realPath)) == NULL) {
|
||||
return false;
|
||||
}
|
||||
FILE *fp = fopen(realPath, "rb+");
|
||||
if (fp == NULL) {
|
||||
INIT_LOGE("open %s failed", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t ret = fwrite(boot, sizeof(struct RBMiscUpdateMessage), 1, fp);
|
||||
if (ret < 0) {
|
||||
INIT_LOGE("write to misc failed");
|
||||
(void)fclose(fp);
|
||||
return false;
|
||||
}
|
||||
(void)fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool RBMiscReadUpdaterMessage(const char *path, struct RBMiscUpdateMessage *boot)
|
||||
{
|
||||
if (path == NULL || boot == NULL) {
|
||||
INIT_LOGE("path or boot is NULL.");
|
||||
return false;
|
||||
}
|
||||
char realPath[PATH_MAX] = {0};
|
||||
if (Realpath(path, realPath, sizeof(realPath)) == NULL) {
|
||||
return false;
|
||||
}
|
||||
FILE *fp = fopen(realPath, "rb");
|
||||
if (fp == NULL) {
|
||||
INIT_LOGE("open %s failed", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t ret = fread(boot, 1, sizeof(struct RBMiscUpdateMessage), fp);
|
||||
if (ret <= 0) {
|
||||
INIT_LOGE("read to misc failed");
|
||||
(void)fclose(fp);
|
||||
return false;
|
||||
}
|
||||
(void)fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int GetMountStatusForMountPoint(const char *mountPoint)
|
||||
{
|
||||
const int bufferMaxSize = 512;
|
||||
char buffer[bufferMaxSize];
|
||||
size_t n;
|
||||
const char *mountFile = "/proc/mounts";
|
||||
FILE *fp = fopen(mountFile, "r");
|
||||
if (fp == NULL) {
|
||||
INIT_LOGE("DoReboot %s can't open.", mountPoint);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (fgets(buffer, sizeof(buffer) - 1, fp) != NULL) {
|
||||
n = strlen(buffer);
|
||||
if (buffer[n - 1] == '\n') {
|
||||
buffer[n - 1] = '\0';
|
||||
}
|
||||
if (strstr(buffer, mountPoint) != NULL) {
|
||||
(void)fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Cannot find it from system.
|
||||
(void)fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int CheckAndRebootToUpdater(const char *valueData, const char *cmd, const char *cmdExt, const char *boot)
|
||||
{
|
||||
// "updater" or "updater:"
|
||||
const char *miscFile = "/dev/block/platform/soc/10100000.himci.eMMC/by-name/misc";
|
||||
struct RBMiscUpdateMessage msg;
|
||||
bool bRet = RBMiscReadUpdaterMessage(miscFile, &msg);
|
||||
INIT_ERROR_CHECK(bRet, return -1, "Failed to get misc info for %s.", cmd);
|
||||
|
||||
int ret = snprintf_s(msg.command, MAX_COMMAND_SIZE, MAX_COMMAND_SIZE - 1, "%s", boot);
|
||||
INIT_ERROR_CHECK(ret > 0, return -1, "Failed to format cmd for %s.", cmd);
|
||||
msg.command[MAX_COMMAND_SIZE - 1] = 0;
|
||||
|
||||
if (strncmp(valueData, cmdExt, strlen(cmdExt)) == 0) {
|
||||
const char *p = valueData + strlen(cmdExt);
|
||||
ret = snprintf_s(msg.update, MAX_UPDATE_SIZE, MAX_UPDATE_SIZE - 1, "%s", p);
|
||||
INIT_ERROR_CHECK(ret > 0, return -1, "Failed to format param for %s.", cmd);
|
||||
msg.update[MAX_UPDATE_SIZE - 1] = 0;
|
||||
}
|
||||
|
||||
if (RBMiscWriteUpdaterMessage(miscFile, &msg)) {
|
||||
return reboot(RB_AUTOBOOT);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int CheckRebootValue(const char *valueData)
|
||||
{
|
||||
if (valueData == NULL) {
|
||||
return 0;
|
||||
}
|
||||
static const char *g_cmdParams[] = {
|
||||
"shutdown", "updater", "updater:", "flashing", "flashing:", "NoArgument", "bootloader"
|
||||
};
|
||||
size_t i = 0;
|
||||
for (; i < ARRAY_LENGTH(g_cmdParams); i++) {
|
||||
if (strncmp(valueData, g_cmdParams[i], strlen(g_cmdParams[i])) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= ARRAY_LENGTH(g_cmdParams)) {
|
||||
INIT_LOGE("DoReboot valueData = %s, parameters error.", valueData);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DoReboot(const char *value)
|
||||
{
|
||||
#ifndef OHOS_LITE
|
||||
if (value == NULL || strlen(value) > MAX_VALUE_LENGTH) {
|
||||
INIT_LOGE("DoReboot value = NULL");
|
||||
return;
|
||||
}
|
||||
const char *valueData = NULL;
|
||||
if (strncmp(value, "reboot,", strlen("reboot,")) == 0) {
|
||||
valueData = value + strlen("reboot,");
|
||||
} else if (strcmp(value, "reboot") != 0) {
|
||||
INIT_LOGE("Reboot value = %s, must started with reboot", value);
|
||||
return;
|
||||
}
|
||||
if (valueData != NULL) {
|
||||
if (CheckRebootValue(valueData) < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
StopAllServicesBeforeReboot();
|
||||
sync();
|
||||
if (GetMountStatusForMountPoint("/vendor") != 0 && umount("/vendor") != 0) {
|
||||
INIT_LOGE("DoReboot umount vendor failed! errno = %d.", errno);
|
||||
}
|
||||
if (GetMountStatusForMountPoint("/data") != 0 && umount("/data") != 0) {
|
||||
INIT_LOGE("DoReboot umount data failed! errno = %d.", errno);
|
||||
}
|
||||
int ret = 0;
|
||||
if (valueData == NULL) {
|
||||
ret = reboot(RB_AUTOBOOT);
|
||||
} else if (strcmp(valueData, "shutdown") == 0) {
|
||||
ret = reboot(RB_POWER_OFF);
|
||||
} else if (strcmp(valueData, "bootloader") == 0) {
|
||||
ret = reboot(RB_POWER_OFF);
|
||||
} else if (strncmp(valueData, "updater", strlen("updater")) == 0) {
|
||||
ret = CheckAndRebootToUpdater(valueData, "updater", "updater:", "boot_updater");
|
||||
} else if (strncmp(valueData, "flashing", strlen("flashing")) == 0) {
|
||||
ret = CheckAndRebootToUpdater(valueData, "flashing", "flashing:", "boot_flashing");
|
||||
}
|
||||
INIT_LOGI("DoReboot value = %s %s.", value, (ret == 0) ? "success" : "fail");
|
||||
#else
|
||||
int ret = reboot(RB_AUTOBOOT);
|
||||
if (ret != 0) {
|
||||
INIT_LOGE("reboot failed! syscall ret %d, err %d.", ret, errno);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@@ -1,876 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init_service_manager.h"
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "cJSON.h"
|
||||
#include "init_adapter.h"
|
||||
#include "init_jobs.h"
|
||||
#include "init_log.h"
|
||||
#include "init_perms.h"
|
||||
#include "init_read_cfg.h"
|
||||
#include "init_capability.h"
|
||||
#include "init_service_socket.h"
|
||||
#include "init_utils.h"
|
||||
#include "securec.h"
|
||||
|
||||
#define MIN_IMPORTANT_LEVEL (-20)
|
||||
#define MAX_IMPORTANT_LEVEL 19
|
||||
|
||||
// All serivce processes that init will fork+exec.
|
||||
static Service* g_services = NULL;
|
||||
static int g_servicesCnt = 0;
|
||||
|
||||
#ifdef OHOS_SERVICE_DUMP
|
||||
void DumpAllServices(void)
|
||||
{
|
||||
if (g_services == NULL) {
|
||||
return;
|
||||
}
|
||||
INIT_LOGD("Ready to dump all services:");
|
||||
INIT_LOGD("total service number: %d", g_servicesCnt);
|
||||
for (int i = 0; i < g_servicesCnt; i++) {
|
||||
INIT_LOGD("\tservice name: [%s]", g_services[i].name);
|
||||
INIT_LOGD("\tpath :");
|
||||
for (int j = 0; j < g_services[i].pathArgsCnt; j++) {
|
||||
if (g_services[i].pathArgs[j] != NULL) {
|
||||
INIT_LOGD(" %s", g_services[i].pathArgs[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
INIT_LOGD("Dump all services finished");
|
||||
}
|
||||
#endif
|
||||
|
||||
void RegisterServices(Service *services, int servicesCnt)
|
||||
{
|
||||
if (services == NULL) {
|
||||
return;
|
||||
}
|
||||
g_services = services;
|
||||
g_servicesCnt += servicesCnt;
|
||||
}
|
||||
|
||||
static void ReleaseServiceMem(Service *curServ)
|
||||
{
|
||||
if (curServ == NULL) {
|
||||
return;
|
||||
}
|
||||
if (curServ->pathArgs != NULL) {
|
||||
for (int i = 0; i < curServ->pathArgsCnt; ++i) {
|
||||
if (curServ->pathArgs[i] != NULL) {
|
||||
free(curServ->pathArgs[i]);
|
||||
curServ->pathArgs[i] = NULL;
|
||||
}
|
||||
}
|
||||
free(curServ->pathArgs);
|
||||
curServ->pathArgs = NULL;
|
||||
}
|
||||
curServ->pathArgsCnt = 0;
|
||||
|
||||
if (curServ->servPerm.caps != NULL) {
|
||||
free(curServ->servPerm.caps);
|
||||
curServ->servPerm.caps = NULL;
|
||||
}
|
||||
curServ->servPerm.capsCnt = 0;
|
||||
for (int i = 0; i < MAX_WRITEPID_FILES; i++) {
|
||||
if (curServ->writepidFiles[i] != NULL) {
|
||||
free(curServ->writepidFiles[i]);
|
||||
curServ->writepidFiles[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (curServ->servPerm.gIDArray != NULL) {
|
||||
free(curServ->servPerm.gIDArray);
|
||||
curServ->servPerm.gIDArray = NULL;
|
||||
}
|
||||
curServ->servPerm.gIDCnt = 0;
|
||||
}
|
||||
|
||||
static int GetServiceName(const cJSON *curArrItem, Service *curServ)
|
||||
{
|
||||
char* fieldStr = cJSON_GetStringValue(cJSON_GetObjectItem(curArrItem, "name"));
|
||||
if (fieldStr == NULL) {
|
||||
INIT_LOGE("GetServiceName cJSON_GetStringValue error");
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
size_t strLen = strlen(fieldStr);
|
||||
if (strLen == 0 || strLen > MAX_SERVICE_NAME) {
|
||||
INIT_LOGE("GetServiceName strLen = %d, error", strLen);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
if (memcpy_s(curServ->name, MAX_SERVICE_NAME, fieldStr, strLen) != EOK) {
|
||||
INIT_LOGE("GetServiceName memcpy_s error");
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->name[strLen] = '\0';
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef OHOS_LITE
|
||||
static int IsForbidden(const char *fieldStr)
|
||||
{
|
||||
size_t fieldLen = strlen(fieldStr);
|
||||
size_t forbidStrLen = strlen(BIN_SH_NOT_ALLOWED);
|
||||
if (fieldLen == forbidStrLen) {
|
||||
if (strncmp(fieldStr, BIN_SH_NOT_ALLOWED, fieldLen) == 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
} else if (fieldLen > forbidStrLen) {
|
||||
// "/bin/shxxxx" is valid but "/bin/sh xxxx" is invalid
|
||||
if (strncmp(fieldStr, BIN_SH_NOT_ALLOWED, forbidStrLen) == 0) {
|
||||
if (fieldStr[forbidStrLen] == ' ') {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static int IsForbidden(const char *fieldStr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static cJSON* GetArrItem(const cJSON *fileRoot, int *arrSize, const char *arrName)
|
||||
{
|
||||
cJSON* arrItem = cJSON_GetObjectItemCaseSensitive(fileRoot, arrName);
|
||||
if (!cJSON_IsArray(arrItem)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*arrSize = cJSON_GetArraySize(arrItem);
|
||||
if (*arrSize <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
return arrItem;
|
||||
}
|
||||
|
||||
static int GetWritepidStrings(const cJSON *curArrItem, Service *curServ) // writepid
|
||||
{
|
||||
int writepidCnt = 0;
|
||||
cJSON *filedJ = GetArrItem(curArrItem, &writepidCnt, "writepid");
|
||||
if ((writepidCnt <= 0) || (filedJ == NULL)) { // not item is ok.
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
if (writepidCnt > MAX_WRITEPID_FILES) {
|
||||
INIT_LOGE("GetWritepidStrings, too many writepid[cnt %d] for one service, should not exceed %d.",
|
||||
writepidCnt, MAX_WRITEPID_FILES);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
for (int i = 0; i < writepidCnt; ++i) {
|
||||
cJSON *item = cJSON_GetArrayItem(filedJ, i);
|
||||
if (item == NULL) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
char *fieldStr = cJSON_GetStringValue(item);
|
||||
if ((fieldStr == NULL) || (fieldStr[0] == '\0')) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
size_t strLen = strlen(fieldStr);
|
||||
curServ->writepidFiles[i] = (char *)malloc(sizeof(char) * strLen + 1);
|
||||
if (curServ->writepidFiles[i] == NULL) {
|
||||
INIT_LOGE("GetWritepidStrings, malloc item[%d] error.", i);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
if (memcpy_s(curServ->writepidFiles[i], strLen + 1, fieldStr, strLen) != EOK) {
|
||||
INIT_LOGE("GetWritepidStrings, memcpy_s error.");
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->writepidFiles[i][strLen] = '\0';
|
||||
}
|
||||
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
static int GetGidOneItem(const cJSON *curArrItem, Service *curServ) // gid one item
|
||||
{
|
||||
cJSON *filedJ = cJSON_GetObjectItem(curArrItem, GID_STR_IN_CFG);
|
||||
if (filedJ == NULL) {
|
||||
return SERVICE_SUCCESS; // not found
|
||||
}
|
||||
curServ->servPerm.gIDCnt = 1;
|
||||
curServ->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t));
|
||||
if (curServ->servPerm.gIDArray == NULL) {
|
||||
INIT_LOGE("GetGidOneItem, can't malloc, error.");
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
if (cJSON_IsString(filedJ)) {
|
||||
char *fieldStr = cJSON_GetStringValue(filedJ);
|
||||
if (fieldStr == NULL) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
gid_t gID = DecodeUid(fieldStr);
|
||||
if (gID == (gid_t)(-1)) {
|
||||
INIT_LOGE("GetGidOneItem, DecodeUid %s error.", fieldStr);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->servPerm.gIDArray[0] = gID;
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
if (cJSON_IsNumber(filedJ)) {
|
||||
int value = (int)cJSON_GetNumberValue(filedJ);
|
||||
if (value < 0) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
gid_t gID = value;
|
||||
curServ->servPerm.gIDArray[0] = gID;
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
INIT_LOGE("GetGidOneItem, this gid is neither a string nor a number, error.");
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
static int GetGidArray(const cJSON *curArrItem, Service *curServ) // gid array
|
||||
{
|
||||
int gIDCnt = 0;
|
||||
cJSON *filedJ = GetArrItem(curArrItem, &gIDCnt, GID_STR_IN_CFG); // "gid" must have 1 item.
|
||||
if ((gIDCnt <= 0) || (filedJ == NULL)) { // not a array, but maybe a item?
|
||||
return GetGidOneItem(curArrItem, curServ);
|
||||
}
|
||||
if (gIDCnt > NGROUPS_MAX + 1) {
|
||||
INIT_LOGE("GetGidArray, too many gids[cnt %d] for one service, should not exceed %d.",
|
||||
gIDCnt, NGROUPS_MAX + 1);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->servPerm.gIDArray = (gid_t *)calloc(sizeof(gid_t), gIDCnt);
|
||||
if (curServ->servPerm.gIDArray == NULL) {
|
||||
INIT_LOGE("GetGidArray malloc error");
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->servPerm.gIDCnt = gIDCnt;
|
||||
int i = 0;
|
||||
for (; i < gIDCnt; ++i) {
|
||||
cJSON *item = cJSON_GetArrayItem(filedJ, i);
|
||||
if (item == NULL) {
|
||||
break;
|
||||
}
|
||||
char *fieldStr = cJSON_GetStringValue(item);
|
||||
if ((fieldStr == NULL) || (fieldStr[0] == '\0')) {
|
||||
break;
|
||||
}
|
||||
gid_t gID = DecodeUid(fieldStr);
|
||||
if ((gID) == (gid_t)(-1)) {
|
||||
INIT_LOGE("GetGidArray, DecodeUid item[%d] error.", i);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->servPerm.gIDArray[i] = gID;
|
||||
}
|
||||
INIT_CHECK_RETURN_VALUE(i != gIDCnt, SERVICE_SUCCESS);
|
||||
for (i = 0; i < gIDCnt; ++i) {
|
||||
cJSON *item = cJSON_GetArrayItem(filedJ, i);
|
||||
if (item == NULL) {
|
||||
break;
|
||||
}
|
||||
if (!cJSON_IsNumber(item)) {
|
||||
break;
|
||||
}
|
||||
int value = (int)cJSON_GetNumberValue(item);
|
||||
if (value < 0) {
|
||||
break;
|
||||
}
|
||||
gid_t gID = value;
|
||||
curServ->servPerm.gIDArray[i] = gID;
|
||||
}
|
||||
return (((i == gIDCnt) ? SERVICE_SUCCESS : SERVICE_FAILURE));
|
||||
}
|
||||
|
||||
static int GetServicePathAndArgs(const cJSON *curArrItem, Service *curServ)
|
||||
{
|
||||
cJSON* pathItem = cJSON_GetObjectItem(curArrItem, "path");
|
||||
if (!cJSON_IsArray(pathItem)) {
|
||||
INIT_LOGE("Path item not found or not a array");
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
int arrSize = cJSON_GetArraySize(pathItem);
|
||||
if (arrSize <= 0 || arrSize > MAX_PATH_ARGS_CNT) { // array size invalid
|
||||
INIT_LOGE("Array size = %d is wrong", arrSize);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
curServ->pathArgs = (char **)malloc((arrSize + 1) * sizeof(char *));
|
||||
if (curServ->pathArgs == NULL) {
|
||||
INIT_LOGE("Current path is null.");
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
for (int i = 0; i < arrSize + 1; ++i) {
|
||||
curServ->pathArgs[i] = NULL;
|
||||
}
|
||||
curServ->pathArgsCnt = arrSize + 1;
|
||||
|
||||
for (int i = 0; i < arrSize; ++i) {
|
||||
char* curParam = cJSON_GetStringValue(cJSON_GetArrayItem(pathItem, i));
|
||||
if (curParam == NULL || strlen(curParam) > MAX_ONE_ARG_LEN) {
|
||||
// resources will be released by function: ReleaseServiceMem
|
||||
if (curParam == NULL) {
|
||||
INIT_LOGE("Current param is null.");
|
||||
} else {
|
||||
INIT_LOGE("Length of current param is too long.");
|
||||
}
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
if (i == 0 && IsForbidden(curParam)) {
|
||||
// resources will be released by function: ReleaseServiceMem
|
||||
INIT_LOGE("Service %s is forbidden.", curServ->name);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
size_t paramLen = strlen(curParam);
|
||||
curServ->pathArgs[i] = (char*)malloc(paramLen + 1);
|
||||
if (curServ->pathArgs[i] == NULL) {
|
||||
// resources will be released by function: ReleaseServiceMem
|
||||
INIT_LOGE("Service %s path is null.", curServ->name);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
if (memcpy_s(curServ->pathArgs[i], paramLen + 1, curParam, paramLen) != EOK) {
|
||||
// resources will be released by function: ReleaseServiceMem
|
||||
INIT_LOGE("memcpy_s failed.");
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->pathArgs[i][paramLen] = '\0';
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
static int GetImportantValue(int value, Service *curServ)
|
||||
{
|
||||
#ifdef OHOS_LITE
|
||||
if (value != 0) {
|
||||
curServ->attribute |= SERVICE_ATTR_IMPORTANT;
|
||||
}
|
||||
#else
|
||||
if (value >= MIN_IMPORTANT_LEVEL && value <= MAX_IMPORTANT_LEVEL) { // -20~19
|
||||
curServ->importance = value;
|
||||
} else {
|
||||
INIT_LOGE("Importance level = %d, is not between -20 and 19, error", value);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
#endif
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
static int GetServiceNumber(const cJSON *curArrItem, Service *curServ, const char *targetField)
|
||||
{
|
||||
cJSON* filedJ = cJSON_GetObjectItem(curArrItem, targetField);
|
||||
if (filedJ == NULL && (strncmp(targetField, CRITICAL_STR_IN_CFG, strlen(CRITICAL_STR_IN_CFG)) == 0
|
||||
|| strncmp(targetField, DISABLED_STR_IN_CFG, strlen(DISABLED_STR_IN_CFG)) == 0
|
||||
|| strncmp(targetField, ONCE_STR_IN_CFG, strlen(ONCE_STR_IN_CFG)) == 0
|
||||
|| strncmp(targetField, IMPORTANT_STR_IN_CFG, strlen(IMPORTANT_STR_IN_CFG)) == 0
|
||||
|| strncmp(targetField, CONSOLE_STR_IN_CFG, strlen(CONSOLE_STR_IN_CFG)) == 0)) {
|
||||
return SERVICE_SUCCESS; // not found "critical","disabled","once","importance","console" item is ok
|
||||
}
|
||||
|
||||
if (!cJSON_IsNumber(filedJ)) {
|
||||
INIT_LOGE("%s is null or is not a number, service name is %s", targetField, curServ->name);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
int value = (int)cJSON_GetNumberValue(filedJ);
|
||||
// importance value allow < 0
|
||||
if (strncmp(targetField, IMPORTANT_STR_IN_CFG, strlen(IMPORTANT_STR_IN_CFG)) != 0) {
|
||||
if (value < 0) {
|
||||
INIT_LOGE("Service %s value = %d is wrong", curServ->name, value);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(targetField, ONCE_STR_IN_CFG, strlen(ONCE_STR_IN_CFG)) == 0) {
|
||||
if (value != 0) {
|
||||
curServ->attribute |= SERVICE_ATTR_ONCE;
|
||||
}
|
||||
} else if (strncmp(targetField, IMPORTANT_STR_IN_CFG, strlen(IMPORTANT_STR_IN_CFG)) == 0) {
|
||||
INIT_CHECK_RETURN_VALUE(GetImportantValue(value, curServ) == SERVICE_SUCCESS, SERVICE_FAILURE);
|
||||
} else if (strncmp(targetField, CRITICAL_STR_IN_CFG, strlen(CRITICAL_STR_IN_CFG)) == 0) { // set critical
|
||||
curServ->attribute &= ~SERVICE_ATTR_CRITICAL;
|
||||
if (value == 1) {
|
||||
curServ->attribute |= SERVICE_ATTR_CRITICAL;
|
||||
}
|
||||
} else if (strncmp(targetField, DISABLED_STR_IN_CFG, strlen(DISABLED_STR_IN_CFG)) == 0) { // set disabled
|
||||
curServ->attribute &= ~SERVICE_ATTR_DISABLED;
|
||||
if (value == 1) {
|
||||
curServ->attribute |= SERVICE_ATTR_DISABLED;
|
||||
}
|
||||
} else if (strncmp(targetField, CONSOLE_STR_IN_CFG, strlen(CONSOLE_STR_IN_CFG)) == 0) { // set console
|
||||
curServ->attribute &= ~SERVICE_ATTR_CONSOLE;
|
||||
if (value == 1) {
|
||||
curServ->attribute |= SERVICE_ATTR_CONSOLE;
|
||||
}
|
||||
} else {
|
||||
INIT_LOGE("Item = %s, not expected, error.service name is %s", targetField, curServ->name);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
static int GetUidStringNumber(const cJSON *curArrItem, Service *curServ)
|
||||
{
|
||||
cJSON *filedJ = cJSON_GetObjectItem(curArrItem, UID_STR_IN_CFG);
|
||||
if (filedJ == NULL) {
|
||||
return SERVICE_SUCCESS; // uID not found, but ok.
|
||||
}
|
||||
|
||||
if (cJSON_IsString(filedJ)) {
|
||||
char *fieldStr = cJSON_GetStringValue(filedJ);
|
||||
if (fieldStr == NULL) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
uid_t uID = DecodeUid(fieldStr);
|
||||
if (uID == (uid_t)-1) {
|
||||
INIT_LOGE("Decode uid %s error.", fieldStr);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->servPerm.uID = uID;
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
if (cJSON_IsNumber(filedJ)) {
|
||||
int uID = (int)cJSON_GetNumberValue(filedJ);
|
||||
if (uID < 0) {
|
||||
INIT_LOGE("Uid = %d error.", uID);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->servPerm.uID = uID;
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
INIT_LOGE("This uid is neither a string nor a number, error.");
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
static int ParseServiceSocket(char **opt, const int optNum, struct ServiceSocket *sockopt)
|
||||
{
|
||||
if (optNum != SOCK_OPT_NUMS) {
|
||||
return -1;
|
||||
}
|
||||
if (opt[SERVICE_SOCK_TYPE] == NULL) {
|
||||
return -1;
|
||||
}
|
||||
sockopt->type =
|
||||
((strncmp(opt[SERVICE_SOCK_TYPE], "stream", strlen(opt[SERVICE_SOCK_TYPE])) == 0) ? SOCK_STREAM :
|
||||
((strncmp(opt[SERVICE_SOCK_TYPE], "dgram", strlen(opt[SERVICE_SOCK_TYPE])) == 0) ? SOCK_DGRAM : SOCK_SEQPACKET));
|
||||
|
||||
if (opt[SERVICE_SOCK_PERM] == NULL) {
|
||||
return -1;
|
||||
}
|
||||
sockopt->perm = strtoul(opt[SERVICE_SOCK_PERM], 0, OCTAL_BASE);
|
||||
if (opt[SERVICE_SOCK_UID] == NULL) {
|
||||
return -1;
|
||||
}
|
||||
uid_t uid = DecodeUid(opt[SERVICE_SOCK_UID]);
|
||||
if (uid == (uid_t)-1) {
|
||||
return -1;
|
||||
}
|
||||
sockopt->uid = uid;
|
||||
if (opt[SERVICE_SOCK_GID] == NULL) {
|
||||
return -1;
|
||||
}
|
||||
gid_t gid = DecodeUid(opt[SERVICE_SOCK_GID]);
|
||||
if (gid == (gid_t)-1) {
|
||||
return -1;
|
||||
}
|
||||
sockopt->gid = gid;
|
||||
if (opt[SERVICE_SOCK_SETOPT] == NULL) {
|
||||
return -1;
|
||||
}
|
||||
sockopt->passcred = ((strncmp(opt[SERVICE_SOCK_SETOPT], "passcred",
|
||||
strlen(opt[SERVICE_SOCK_SETOPT])) == 0) ? true : false);
|
||||
if (opt[SERVICE_SOCK_NAME] == NULL) {
|
||||
return -1;
|
||||
}
|
||||
sockopt->name = (char *)calloc(MAX_SOCK_NAME_LEN, sizeof(char));
|
||||
if (sockopt->name == NULL) {
|
||||
return -1;
|
||||
}
|
||||
int ret = memcpy_s(sockopt->name, MAX_SOCK_NAME_LEN, opt[SERVICE_SOCK_NAME], MAX_SOCK_NAME_LEN - 1);
|
||||
if (ret != 0) {
|
||||
free(sockopt->name);
|
||||
sockopt->name = NULL;
|
||||
return -1;
|
||||
}
|
||||
sockopt->next = NULL;
|
||||
sockopt->sockFd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void FreeServiceSocket(struct ServiceSocket *sockopt)
|
||||
{
|
||||
if (sockopt == NULL) {
|
||||
return;
|
||||
}
|
||||
struct ServiceSocket *tmpSock = NULL;
|
||||
while (sockopt != NULL) {
|
||||
tmpSock = sockopt;
|
||||
if (sockopt->name != NULL) {
|
||||
free(sockopt->name);
|
||||
sockopt->name = NULL;
|
||||
}
|
||||
sockopt = tmpSock->next;
|
||||
free(tmpSock);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int GetServiceSocket(const cJSON *curArrItem, Service *curServ)
|
||||
{
|
||||
cJSON* filedJ = cJSON_GetObjectItem(curArrItem, "socket");
|
||||
if (!cJSON_IsArray(filedJ)) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
|
||||
int sockCnt = cJSON_GetArraySize(filedJ);
|
||||
if (sockCnt <= 0) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->socketCfg = NULL;
|
||||
for (int i = 0; i < sockCnt; ++i) {
|
||||
cJSON *sockJ = cJSON_GetArrayItem(filedJ, i);
|
||||
if (!cJSON_IsString(sockJ) || !cJSON_GetStringValue(sockJ)) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
char *sockStr = cJSON_GetStringValue(sockJ);
|
||||
char *tmpStr[SOCK_OPT_NUMS] = {NULL};
|
||||
int num = SplitString(sockStr, tmpStr, SOCK_OPT_NUMS);
|
||||
if (num != SOCK_OPT_NUMS) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
struct ServiceSocket *socktmp = (struct ServiceSocket *)calloc(1, sizeof(struct ServiceSocket));
|
||||
if (socktmp == NULL) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
int ret = ParseServiceSocket(tmpStr, SOCK_OPT_NUMS, socktmp);
|
||||
if (ret < 0) {
|
||||
free(socktmp);
|
||||
socktmp = NULL;
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
if (curServ->socketCfg == NULL) {
|
||||
curServ->socketCfg = socktmp;
|
||||
} else {
|
||||
socktmp->next = curServ->socketCfg->next;
|
||||
curServ->socketCfg->next = socktmp;
|
||||
}
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
static int GetServiceOnRestart(const cJSON *curArrItem, Service *curServ)
|
||||
{
|
||||
cJSON* filedJ = cJSON_GetObjectItem(curArrItem, "onrestart");
|
||||
if (filedJ == NULL) {
|
||||
return SERVICE_SUCCESS; // onrestart not found, but ok.
|
||||
}
|
||||
if (!cJSON_IsArray(filedJ)) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
int cmdCnt = cJSON_GetArraySize(filedJ);
|
||||
if (cmdCnt <= 0) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->onRestart = (struct OnRestartCmd *)calloc(1, sizeof(struct OnRestartCmd));
|
||||
if (curServ->onRestart == NULL) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->onRestart->cmdLine = (CmdLine *)calloc(cmdCnt, sizeof(CmdLine));
|
||||
if (curServ->onRestart->cmdLine == NULL) {
|
||||
free(curServ->onRestart);
|
||||
curServ->onRestart = NULL;
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
curServ->onRestart->cmdNum = cmdCnt;
|
||||
for (int i = 0; i < cmdCnt; ++i) {
|
||||
cJSON* cmdJ = cJSON_GetArrayItem(filedJ, i);
|
||||
if (!cJSON_IsString(cmdJ) || !cJSON_GetStringValue(cmdJ)) {
|
||||
free(curServ->onRestart->cmdLine);
|
||||
curServ->onRestart->cmdLine = NULL;
|
||||
free(curServ->onRestart);
|
||||
curServ->onRestart = NULL;
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
char *cmdStr = cJSON_GetStringValue(cmdJ);
|
||||
ParseCmdLine(cmdStr, &curServ->onRestart->cmdLine[i]);
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
static bool IsServiceInMainStrap(const Service *curServ)
|
||||
{
|
||||
char *mainServiceList[] = {
|
||||
"appspawn", "udevd", "samgr", "multimodalinput", "weston", "installs", "hiview", "hilogd", "hdf_devmgr",
|
||||
"distributedsche", "softbus_server", "foundation"
|
||||
};
|
||||
unsigned int length = ARRAY_LENGTH(mainServiceList);
|
||||
for (unsigned int i = 0; i < length; ++i) {
|
||||
if (strncmp(curServ->name, mainServiceList[i], strlen(mainServiceList[i])) == 0) {
|
||||
INIT_LOGI("%s must be main service", curServ->name);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int GetDynamicService(const cJSON *curArrItem, Service *curServ)
|
||||
{
|
||||
cJSON *item = cJSON_GetObjectItem(curArrItem, "dynamic");
|
||||
if (item == NULL) {
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
INIT_ERROR_CHECK(cJSON_IsBool(item), return SERVICE_FAILURE,
|
||||
"Service : %s dynamic value only support bool.", curServ->name);
|
||||
bool isDynamic = (bool)cJSON_GetNumberValue(item);
|
||||
if (!isDynamic) {
|
||||
INIT_LOGI("Service : %s dynamic value is false, it will be started with init.", curServ->name);
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
if (IsServiceInMainStrap(curServ)) {
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
INIT_LOGI("%s is dynamic service", curServ->name);
|
||||
curServ->attribute |= SERVICE_ATTR_DYNAMIC;
|
||||
curServ->attribute |= SERVICE_ATTR_ONCE;
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
static int CheckServiceKeyName(const cJSON *curService)
|
||||
{
|
||||
char *cfgServiceKeyList[] = {
|
||||
"name", "path", "uid", "gid", "once", "importance", "caps", "disabled",
|
||||
"writepid", "critical", "socket", "console", "dynamic"
|
||||
};
|
||||
if (curService == NULL) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
cJSON *child = curService->child;
|
||||
if (child == NULL) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
while (child != NULL) {
|
||||
int i = 0;
|
||||
int keyListSize = ARRAY_LENGTH(cfgServiceKeyList);
|
||||
for (; i < keyListSize; i++) {
|
||||
if (strcmp(child->string, cfgServiceKeyList[i]) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < keyListSize) {
|
||||
child = child->next;
|
||||
} else {
|
||||
INIT_LOGE("CheckServiceKeyName, key name %s is not found. error.", child->string);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
static int ParseOneService(const cJSON *curItem, Service *service)
|
||||
{
|
||||
if (curItem == NULL || service == NULL) {
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
int ret = GetServiceName(curItem, service);
|
||||
ret += GetServicePathAndArgs(curItem, service);
|
||||
ret += GetUidStringNumber(curItem, service);
|
||||
ret += GetGidArray(curItem, service);
|
||||
ret += GetServiceNumber(curItem, service, ONCE_STR_IN_CFG);
|
||||
ret += GetServiceNumber(curItem, service, IMPORTANT_STR_IN_CFG);
|
||||
ret += GetServiceNumber(curItem, service, CRITICAL_STR_IN_CFG);
|
||||
ret += GetServiceNumber(curItem, service, DISABLED_STR_IN_CFG);
|
||||
ret += GetServiceNumber(curItem, service, CONSOLE_STR_IN_CFG);
|
||||
ret += GetWritepidStrings(curItem, service);
|
||||
ret += GetServiceCaps(curItem, service);
|
||||
ret += GetDynamicService(curItem, service);
|
||||
if (ret < 0) {
|
||||
return SERVICE_FAILURE;
|
||||
} else {
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
void ParseAllServices(const cJSON *fileRoot)
|
||||
{
|
||||
int servArrSize = 0;
|
||||
cJSON* serviceArr = GetArrItem(fileRoot, &servArrSize, SERVICES_ARR_NAME_IN_JSON);
|
||||
INIT_INFO_CHECK(serviceArr != NULL, return, "This config does not contain service array.");
|
||||
|
||||
INIT_ERROR_CHECK(servArrSize <= MAX_SERVICES_CNT_IN_FILE, return,
|
||||
"Too many services[cnt %d] detected, should not exceed %d.",
|
||||
servArrSize, MAX_SERVICES_CNT_IN_FILE);
|
||||
INIT_CHECK_ONLY_RETURN((g_servicesCnt + servArrSize) > 0);
|
||||
|
||||
Service* retServices = (Service*)realloc(g_services, sizeof(Service) * (g_servicesCnt + servArrSize));
|
||||
INIT_ERROR_CHECK(retServices != NULL, return,
|
||||
"Realloc for %s arr failed! %d.", SERVICES_ARR_NAME_IN_JSON, servArrSize);
|
||||
|
||||
// Skip already saved services,
|
||||
Service* tmp = retServices + g_servicesCnt;
|
||||
if (memset_s(tmp, sizeof(Service) * servArrSize, 0, sizeof(Service) * servArrSize) != EOK) {
|
||||
free(retServices);
|
||||
retServices = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < servArrSize; ++i) {
|
||||
cJSON* curItem = cJSON_GetArrayItem(serviceArr, i);
|
||||
if (CheckServiceKeyName(curItem) != SERVICE_SUCCESS) {
|
||||
ReleaseServiceMem(&tmp[i]);
|
||||
tmp[i].attribute |= SERVICE_ATTR_INVALID;
|
||||
continue;
|
||||
}
|
||||
int ret = ParseOneService(curItem, &tmp[i]);
|
||||
if (ret != SERVICE_SUCCESS) {
|
||||
// release resources if it fails
|
||||
ReleaseServiceMem(&tmp[i]);
|
||||
tmp[i].attribute |= SERVICE_ATTR_INVALID;
|
||||
INIT_LOGE("Parse information for service %s failed. ", tmp[i].name);
|
||||
continue;
|
||||
} else {
|
||||
INIT_LOGD("service[%d] name=%s, uid=%d, critical=%d, disabled=%d",
|
||||
i, tmp[i].name, tmp[i].servPerm.uID, (tmp[i].attribute & SERVICE_ATTR_CRITICAL) ? 1 : 0,
|
||||
(tmp[i].attribute & SERVICE_ATTR_DISABLED) ? 1 : 0);
|
||||
}
|
||||
if (GetServiceSocket(curItem, &tmp[i]) != SERVICE_SUCCESS) {
|
||||
if (tmp[i].socketCfg != NULL) {
|
||||
FreeServiceSocket(tmp[i].socketCfg);
|
||||
tmp[i].socketCfg = NULL;
|
||||
}
|
||||
}
|
||||
if (GetServiceOnRestart(curItem, &tmp[i]) == SERVICE_FAILURE) {
|
||||
INIT_LOGE("Failed Get Service OnRestart service");
|
||||
}
|
||||
}
|
||||
// Increase service counter.
|
||||
RegisterServices(retServices, servArrSize);
|
||||
}
|
||||
|
||||
static int FindServiceByName(const char *servName)
|
||||
{
|
||||
if ((servName == NULL) || (g_services == NULL)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < g_servicesCnt; ++i) {
|
||||
if (strlen(g_services[i].name) == strlen(servName) &&
|
||||
strncmp(g_services[i].name, servName, strlen(g_services[i].name)) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void StartServiceByName(const char *servName, bool checkDynamic)
|
||||
{
|
||||
// find service by name
|
||||
int servIdx = FindServiceByName(servName);
|
||||
if (servIdx < 0) {
|
||||
INIT_LOGE("Cannot find service %s.", servName);
|
||||
return;
|
||||
}
|
||||
if (checkDynamic && (g_services[servIdx].attribute & SERVICE_ATTR_DYNAMIC)) {
|
||||
INIT_LOGI("%s is dynamic service.", servName);
|
||||
return;
|
||||
}
|
||||
if (ServiceStart(&g_services[servIdx]) != SERVICE_SUCCESS) {
|
||||
INIT_LOGE("Service %s start failed!", g_services[servIdx].name);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void StopServiceByName(const char *servName)
|
||||
{
|
||||
// find service by name
|
||||
int servIdx = FindServiceByName(servName);
|
||||
if (servIdx < 0) {
|
||||
INIT_LOGE("Cannot find service %s.", servName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ServiceStop(&g_services[servIdx]) != SERVICE_SUCCESS) {
|
||||
INIT_LOGE("Service %s start failed!", g_services[servIdx].name);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void StopAllServices(void)
|
||||
{
|
||||
if (g_services == NULL) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < g_servicesCnt; i++) {
|
||||
if (ServiceStop(&g_services[i]) != SERVICE_SUCCESS) {
|
||||
INIT_LOGE("Service %s stop failed!", g_services[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StopAllServicesBeforeReboot(void)
|
||||
{
|
||||
if (g_services == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < g_servicesCnt; i++) {
|
||||
g_services[i].attribute |= SERVICE_ATTR_INVALID;
|
||||
if (ServiceStop(&g_services[i]) != SERVICE_SUCCESS) {
|
||||
INIT_LOGE("Service %s stop failed!", g_services[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReapServiceByPID(int pid)
|
||||
{
|
||||
if (g_services == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < g_servicesCnt; i++) {
|
||||
if (g_services[i].pid == pid) {
|
||||
#ifdef OHOS_LITE
|
||||
if (g_services[i].attribute & SERVICE_ATTR_IMPORTANT) {
|
||||
// important process exit, need to reboot system
|
||||
g_services[i].pid = -1;
|
||||
StopAllServices();
|
||||
RebootSystem();
|
||||
}
|
||||
#endif
|
||||
ServiceReap(&g_services[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init_service_socket.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include "init_log.h"
|
||||
#include "securec.h"
|
||||
|
||||
#define HOS_SOCKET_DIR "/dev/unix/socket"
|
||||
#define HOS_SOCKET_ENV_PREFIX "OHOS_SOCKET_"
|
||||
#define MAX_SOCKET_ENV_PREFIX_LEN 64
|
||||
#define MAX_SOCKET_FD_LEN 16
|
||||
|
||||
static int CreateSocket(struct ServiceSocket *sockopt)
|
||||
{
|
||||
if (sockopt == NULL || sockopt->name == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (sockopt->sockFd >= 0) {
|
||||
close(sockopt->sockFd);
|
||||
sockopt->sockFd = -1;
|
||||
}
|
||||
sockopt->sockFd = socket(PF_UNIX, sockopt->type, 0);
|
||||
INIT_ERROR_CHECK(sockopt->sockFd >= 0, return -1, "socket fail %d ", errno);
|
||||
|
||||
struct sockaddr_un addr;
|
||||
bzero(&addr, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
if (snprintf_s(addr.sun_path, sizeof(addr.sun_path), sizeof(addr.sun_path) - 1, HOS_SOCKET_DIR"/%s",
|
||||
sockopt->name) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (access(addr.sun_path, F_OK) == 0) {
|
||||
INIT_LOGE("%s already exist, remove it", addr.sun_path);
|
||||
if (unlink(addr.sun_path) != 0) {
|
||||
INIT_LOGE("ulink fail err %d ", errno);
|
||||
}
|
||||
}
|
||||
if (sockopt->passcred) {
|
||||
int on = 1;
|
||||
if (setsockopt(sockopt->sockFd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
|
||||
unlink(addr.sun_path);
|
||||
close(sockopt->sockFd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (bind(sockopt->sockFd, (struct sockaddr *)&addr, sizeof(addr))) {
|
||||
INIT_LOGE("Create socket for service %s failed: %d", sockopt->name, errno);
|
||||
unlink(addr.sun_path);
|
||||
close(sockopt->sockFd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lchown(addr.sun_path, sockopt->uid, sockopt->gid)) {
|
||||
unlink(addr.sun_path);
|
||||
close(sockopt->sockFd);
|
||||
INIT_LOGE("lchown fail %d ", errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fchmodat(AT_FDCWD, addr.sun_path, sockopt->perm, AT_SYMLINK_NOFOLLOW)) {
|
||||
unlink(addr.sun_path);
|
||||
close(sockopt->sockFd);
|
||||
INIT_LOGE("fchmodat fail %d ", errno);
|
||||
return -1;
|
||||
}
|
||||
INIT_LOGI("CreateSocket success ");
|
||||
return sockopt->sockFd;
|
||||
}
|
||||
|
||||
static int SetSocketEnv(int fd, const char *name)
|
||||
{
|
||||
if (name == NULL) {
|
||||
return -1;
|
||||
}
|
||||
char pubName[MAX_SOCKET_ENV_PREFIX_LEN] = {0};
|
||||
char val[MAX_SOCKET_FD_LEN] = {0};
|
||||
if (snprintf_s(pubName, MAX_SOCKET_ENV_PREFIX_LEN, MAX_SOCKET_ENV_PREFIX_LEN - 1,
|
||||
HOS_SOCKET_ENV_PREFIX"%s", name) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (snprintf_s(val, MAX_SOCKET_FD_LEN, MAX_SOCKET_FD_LEN - 1, "%d", fd) < 0) {
|
||||
return -1;
|
||||
}
|
||||
int ret = setenv(pubName, val, 1);
|
||||
if (ret < 0) {
|
||||
INIT_LOGE("setenv fail %d ", errno);
|
||||
return -1;
|
||||
}
|
||||
fcntl(fd, F_SETFD, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DoCreateSocket(struct ServiceSocket *sockopt)
|
||||
{
|
||||
if (sockopt == NULL) {
|
||||
return -1;
|
||||
}
|
||||
struct ServiceSocket *tmpSock = sockopt;
|
||||
while (tmpSock != NULL) {
|
||||
int fd = CreateSocket(tmpSock);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (tmpSock->name == NULL) {
|
||||
return -1;
|
||||
}
|
||||
int ret = SetSocketEnv(fd, tmpSock->name);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
tmpSock = tmpSock->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef OHOS_DEBUG
|
||||
#include <time.h>
|
||||
#endif // OHOS_DEBUG
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "init_adapter.h"
|
||||
#include "init_log.h"
|
||||
#include "init_read_cfg.h"
|
||||
#include "init_signal_handler.h"
|
||||
#ifdef OHOS_LITE
|
||||
#include "parameter.h"
|
||||
#endif
|
||||
|
||||
#ifndef OHOS_LITE
|
||||
#include "device.h"
|
||||
#include "init_param.h"
|
||||
#endif
|
||||
#include "init_utils.h"
|
||||
|
||||
static const pid_t INIT_PROCESS_PID = 1;
|
||||
|
||||
static void PrintSysInfo()
|
||||
{
|
||||
#ifdef OHOS_LITE
|
||||
const char* sysInfo = GetVersionId();
|
||||
if (sysInfo != NULL) {
|
||||
INIT_LOGE("%s", sysInfo);
|
||||
return;
|
||||
}
|
||||
INIT_LOGE("main, GetVersionId failed!");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef OHOS_DEBUG
|
||||
static long TimeDiffMs(const struct timespec* tmBefore, const struct timespec* tmAfter)
|
||||
{
|
||||
if (tmBefore != NULL && tmAfter != NULL) {
|
||||
long timeUsed = (tmAfter->tv_sec - tmBefore->tv_sec) * 1000 + // 1 s = 1000 ms
|
||||
(tmAfter->tv_nsec - tmBefore->tv_nsec) / 1000000L; // 1 ms = 1000000 ns
|
||||
return timeUsed;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif // OHOS_DEBUG
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
#ifndef OHOS_LITE
|
||||
INIT_CHECK_ONLY_ELOG(setenv("UV_THREADPOOL_SIZE", "1", 1) == 0, "set UV_THREADPOOL_SIZE error : %d.", errno);
|
||||
CloseStdio();
|
||||
OpenLogDevice();
|
||||
#endif
|
||||
|
||||
#ifdef OHOS_DEBUG
|
||||
struct timespec tmEnter;
|
||||
INIT_CHECK_ONLY_ELOG(clock_gettime(CLOCK_REALTIME, &tmEnter) == 0,
|
||||
"main, enter, get time failed! err %d.\n", errno);
|
||||
#endif // OHOS_DEBUG
|
||||
|
||||
if (getpid() != INIT_PROCESS_PID) {
|
||||
INIT_LOGE("main, current process id is %d not %d, failed!", getpid(), INIT_PROCESS_PID);
|
||||
return 0;
|
||||
}
|
||||
PrintSysInfo();
|
||||
|
||||
#ifndef OHOS_LITE
|
||||
MountBasicFs();
|
||||
CreateDeviceNode();
|
||||
EnableDevKmsg();
|
||||
MakeDirRecursive("/dev/unix/socket", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
||||
#endif
|
||||
|
||||
SignalInitModule();
|
||||
|
||||
#ifdef OHOS_DEBUG
|
||||
struct timespec tmSysInfo;
|
||||
INIT_CHECK_ONLY_ELOG(clock_gettime(CLOCK_REALTIME, &tmSysInfo) == 0,
|
||||
"main, after sysinfo, get time failed! err %d.", errno);
|
||||
#endif // OHOS_DEBUG
|
||||
|
||||
ExecuteRcs();
|
||||
|
||||
#ifdef OHOS_DEBUG
|
||||
struct timespec tmRcs;
|
||||
INIT_CHECK_ONLY_ELOG(clock_gettime(CLOCK_REALTIME, &tmRcs) == 0,
|
||||
"main, after rcs, get time failed! err %d.", errno);
|
||||
#endif // OHOS_DEBUG
|
||||
InitReadCfg();
|
||||
#ifdef OHOS_DEBUG
|
||||
struct timespec tmCfg;
|
||||
INIT_CHECK_ONLY_ELOG(clock_gettime(CLOCK_REALTIME, &tmCfg) == 0, "main, get time failed! err %d.", errno);
|
||||
#endif // OHOS_DEBUG
|
||||
|
||||
#ifdef OHOS_DEBUG
|
||||
INIT_LOGI("main, time used: sigInfo %ld ms, rcs %ld ms, cfg %ld ms.", \
|
||||
TimeDiffMs(&tmEnter, &tmSysInfo), TimeDiffMs(&tmSysInfo, &tmRcs), TimeDiffMs(&tmRcs, &tmCfg));
|
||||
#endif
|
||||
|
||||
INIT_LOGI("main, entering wait.");
|
||||
#ifndef OHOS_LITE
|
||||
StartParamService();
|
||||
#endif
|
||||
while (1) {
|
||||
(void)pause();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Executable
+145
@@ -0,0 +1,145 @@
|
||||
# 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/test.gni")
|
||||
|
||||
config("utest_config") {
|
||||
visibility = [ ":*" ]
|
||||
|
||||
cflags = [
|
||||
"-fprofile-arcs",
|
||||
"-ftest-coverage",
|
||||
"-Wno-implicit-fallthrough",
|
||||
"-Wno-unused-function",
|
||||
]
|
||||
cflags_cc = [
|
||||
"-Wno-implicit-fallthrough",
|
||||
"-fexceptions",
|
||||
]
|
||||
|
||||
ldflags = [ "--coverage" ]
|
||||
}
|
||||
|
||||
ohos_unittest("init_ut") {
|
||||
module_out_path = "startup/init"
|
||||
sources = [
|
||||
"//base/startup/init_lite/services/init/adapter/init_adapter.c",
|
||||
"//base/startup/init_lite/services/init/init_capability.c",
|
||||
"//base/startup/init_lite/services/init/init_common_cmds.c",
|
||||
"//base/startup/init_lite/services/init/init_config.c",
|
||||
"//base/startup/init_lite/services/init/init_common_service.c",
|
||||
"//base/startup/init_lite/services/init/init_service_manager.c",
|
||||
"//base/startup/init_lite/services/init/init_service_socket.c",
|
||||
"//base/startup/init_lite/services/init/standard/device.c",
|
||||
"//base/startup/init_lite/services/init/standard/init.c",
|
||||
"//base/startup/init_lite/services/init/standard/init_cmds.c",
|
||||
"//base/startup/init_lite/services/init/standard/init_jobs.c",
|
||||
"//base/startup/init_lite/services/init/standard/init_reboot.c",
|
||||
"//base/startup/init_lite/services/init/standard/init_service.c",
|
||||
"//base/startup/init_lite/services/init/standard/init_signal_handler.c",
|
||||
"//base/startup/init_lite/services/log/init_log.c",
|
||||
"//base/startup/init_lite/services/param/adapter/param_dac.c",
|
||||
"//base/startup/init_lite/services/param/adapter/param_libuvadp.c",
|
||||
"//base/startup/init_lite/services/param/adapter/param_persistadp.c",
|
||||
"//base/startup/init_lite/services/param/adapter/param_selinux.c",
|
||||
"//base/startup/init_lite/services/param/client/param_request.c",
|
||||
"//base/startup/init_lite/services/param/cmd/param_cmd.c",
|
||||
"//base/startup/init_lite/services/param/manager/param_manager.c",
|
||||
"//base/startup/init_lite/services/param/manager/param_message.c",
|
||||
"//base/startup/init_lite/services/param/manager/param_trie.c",
|
||||
"//base/startup/init_lite/services/param/manager/param_utils.c",
|
||||
"//base/startup/init_lite/services/param/service/param_persist.c",
|
||||
"//base/startup/init_lite/services/param/service/param_service.c",
|
||||
"//base/startup/init_lite/services/param/trigger/trigger_checker.c",
|
||||
"//base/startup/init_lite/services/param/trigger/trigger_manager.c",
|
||||
"//base/startup/init_lite/services/param/trigger/trigger_processor.c",
|
||||
"//base/startup/init_lite/services/param/watcher/agent/watcher.cpp",
|
||||
"//base/startup/init_lite/services/param/watcher/agent/watcher_manager_kits.cpp",
|
||||
"//base/startup/init_lite/services/param/watcher/agent/watcher_manager_proxy.cpp",
|
||||
"//base/startup/init_lite/services/param/watcher/agent/watcher_stub.cpp",
|
||||
"//base/startup/init_lite/services/param/watcher/proxy/watcher_manager.cpp",
|
||||
"//base/startup/init_lite/services/param/watcher/proxy/watcher_manager_stub.cpp",
|
||||
"//base/startup/init_lite/services/param/watcher/proxy/watcher_proxy.cpp",
|
||||
"//base/startup/init_lite/services/utils/init_utils.c",
|
||||
"//base/startup/init_lite/services/utils/list.c",
|
||||
]
|
||||
|
||||
sources += [
|
||||
"init/cmds_unittest.cpp",
|
||||
"init/service_unittest.cpp",
|
||||
"param/client_unittest.cpp",
|
||||
"param/dac_unittest.cpp",
|
||||
"param/param_unittest.cpp",
|
||||
"param/selinux_unittest.cpp",
|
||||
"param/trigger_unittest.cpp",
|
||||
"param/watcher_agent_unittest.cpp",
|
||||
"param/watcher_proxy_unittest.cpp",
|
||||
]
|
||||
|
||||
configs = [ "//base/startup/init_lite/services/test/unittest:utest_config" ]
|
||||
|
||||
include_dirs = [
|
||||
"//base/startup/init_lite/services/include",
|
||||
"//base/startup/init_lite/services/init/include",
|
||||
"//base/startup/init_lite/services/include/param",
|
||||
"//base/startup/init_lite/services/log",
|
||||
"//base/startup/init_lite/services/param/adapter",
|
||||
"//base/startup/init_lite/services/param/include",
|
||||
"//base/startup/init_lite/services/param/watcher/agent",
|
||||
"//base/startup/init_lite/services/param/watcher/include",
|
||||
"//base/startup/init_lite/services/param/watcher/proxy",
|
||||
"//base/startup/init_lite/services/test/unittest",
|
||||
"//base/startup/init_lite/services/test/unittest/param",
|
||||
"//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",
|
||||
"//utils/native/base/include",
|
||||
"//utils/system/safwk/native/include",
|
||||
"//third_party/bounds_checking_function/include",
|
||||
"//third_party/libuv/include",
|
||||
"//third_party/cJSON",
|
||||
]
|
||||
|
||||
deps = [
|
||||
"//third_party/bounds_checking_function:libsec_static",
|
||||
"//third_party/cJSON:cjson_static",
|
||||
"//third_party/googletest:gmock",
|
||||
"//third_party/googletest:gtest",
|
||||
"//third_party/libuv:uv_static",
|
||||
"//utils/native/base:utils",
|
||||
]
|
||||
|
||||
defines = [
|
||||
"INIT_AGENT",
|
||||
"STARTUP_INIT_TEST",
|
||||
"PARAM_SUPPORT_SAVE_PERSIST",
|
||||
"PARAM_SUPPORT_DAC",
|
||||
]
|
||||
|
||||
external_deps = [
|
||||
"hiviewdfx_hilog_native:libhilog",
|
||||
"ipc:ipc_core",
|
||||
"safwk:system_ability_fwk",
|
||||
"samgr_L2:samgr_proxy",
|
||||
]
|
||||
|
||||
cflags_cc = [ "-fexceptions" ]
|
||||
}
|
||||
|
||||
group("init_test") {
|
||||
testonly = true
|
||||
deps = [
|
||||
":init_ut"
|
||||
]
|
||||
}
|
||||
Regular → Executable
+15
-13
@@ -29,9 +29,8 @@ if (defined(ohos_lite)) {
|
||||
|
||||
include_dirs = [
|
||||
"//base/startup/init_lite/services/include",
|
||||
"//base/startup/init_lite/services/param/include",
|
||||
"//base/startup/init_lite/services/init/include",
|
||||
"//base/startup/init_lite/services/log",
|
||||
"//base/startup/init_lite/services/utils",
|
||||
"//third_party/cJSON",
|
||||
"//third_party/bounds_checking_function/include",
|
||||
"//base/startup/syspara_lite/interfaces/kits",
|
||||
@@ -39,19 +38,22 @@ if (defined(ohos_lite)) {
|
||||
]
|
||||
|
||||
sources = [
|
||||
"//base/startup/init_lite/services/init/adapter/init_adapter.c",
|
||||
"//base/startup/init_lite/services/init/init_capability.c",
|
||||
"//base/startup/init_lite/services/init/init_common_cmds.c",
|
||||
"//base/startup/init_lite/services/init/init_config.c",
|
||||
"//base/startup/init_lite/services/init/init_common_service.c",
|
||||
"//base/startup/init_lite/services/init/init_service_manager.c",
|
||||
"//base/startup/init_lite/services/init/init_service_socket.c",
|
||||
"//base/startup/init_lite/services/init/lite/init.c",
|
||||
"//base/startup/init_lite/services/init/lite/init_cmds.c",
|
||||
"//base/startup/init_lite/services/init/lite/init_jobs.c",
|
||||
"//base/startup/init_lite/services/init/lite/init_reboot.c",
|
||||
"//base/startup/init_lite/services/init/lite/init_service.c",
|
||||
"//base/startup/init_lite/services/init/lite/init_signal_handler.c",
|
||||
"//base/startup/init_lite/services/log/init_log.c",
|
||||
"//base/startup/init_lite/services/src/init_adapter.c",
|
||||
"//base/startup/init_lite/services/src/init_capability.c",
|
||||
"//base/startup/init_lite/services/src/init_cmds.c",
|
||||
"//base/startup/init_lite/services/src/init_import.c",
|
||||
"//base/startup/init_lite/services/src/init_jobs.c",
|
||||
"//base/startup/init_lite/services/src/init_read_cfg.c",
|
||||
"//base/startup/init_lite/services/src/init_reboot.c",
|
||||
"//base/startup/init_lite/services/src/init_service.c",
|
||||
"//base/startup/init_lite/services/src/init_service_manager.c",
|
||||
"//base/startup/init_lite/services/src/init_service_socket.c",
|
||||
"//base/startup/init_lite/services/src/init_signal_handler.c",
|
||||
"//base/startup/init_lite/services/utils/init_utils.c",
|
||||
"//base/startup/init_lite/services/utils/list.c",
|
||||
"cmd_func_test.cpp",
|
||||
]
|
||||
|
||||
|
||||
Regular → Executable
+97
-58
@@ -12,19 +12,22 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <dirent.h>
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <dirent.h>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "cJSON.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "securec.h"
|
||||
#include "init_cmds.h"
|
||||
#include "init_jobs.h"
|
||||
#include "init_service_manager.h"
|
||||
#include "securec.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace testing::ext;
|
||||
|
||||
namespace OHOS {
|
||||
@@ -37,7 +40,6 @@ const std::string TEST_PROC_MOUNTS = "/proc/mounts";
|
||||
const uid_t TEST_FILE_UID = 999;
|
||||
const gid_t TEST_FILE_GID = 999;
|
||||
const mode_t TEST_FILE_MODE = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
const mode_t DEFAULT_DIR_MODE = 0755;
|
||||
|
||||
// init.cfg releated
|
||||
const std::string CFG_FILE = "/etc/init.cfg";
|
||||
@@ -47,14 +49,14 @@ const std::string CMDS_ARR_NAME_IN_JSON = "cmds";
|
||||
const uid_t CFG_FILE_UID = 0;
|
||||
const gid_t CFG_FILE_GID = 0;
|
||||
const mode_t CFG_FILE_MODE = S_IRUSR;
|
||||
const int JOBS_IN_FILE_COUNT = 3; // pre-init, init, post-init
|
||||
const int JOBS_IN_FILE_COUNT = 3; // pre-init, init, post-init
|
||||
const int MAX_SERVICES_COUNT_IN_FILE = 100;
|
||||
const int MAX_CAPS_CNT_FOR_ONE_SERVICE = 100;
|
||||
const unsigned int MAX_CAPABILITY_VALUE = 4294967295; // 0xFFFFFFFF
|
||||
const unsigned int MAX_JSON_FILE_LEN = 102400; // max init.cfg size 100KB
|
||||
const int MAX_PATH_ARGS_CNT = 20; // max path and args count
|
||||
const int MAX_ONE_ARG_LEN = 64; // max length of one param/path
|
||||
const int CAT_BUF_SIZE = 512; // standard Cat buffer size from vfs_shell_cmd
|
||||
const unsigned int MAX_CAPABILITY_VALUE = 4294967295; // 0xFFFFFFFF
|
||||
const unsigned int MAX_JSON_FILE_LEN = 102400; // max init.cfg size 100KB
|
||||
const int TEST_MAX_PATH_ARGS_CNT = 20; // max path and args count
|
||||
const int TEST_MAX_ONE_ARG_LEN = 64; // max length of one param/path
|
||||
const int CAT_BUF_SIZE = 512; // standard Cat buffer size from vfs_shell_cmd
|
||||
|
||||
// job test releated
|
||||
const pid_t INVALID_PID = -1;
|
||||
@@ -62,6 +64,11 @@ const std::string PRE_INIT_DIR = ROOT_DIR + "preInitDir/";
|
||||
const std::string INIT_DIR = PRE_INIT_DIR + "initDir";
|
||||
const std::string POST_INIT_DIR = INIT_DIR + "postInitDir";
|
||||
|
||||
using TestCmdLine = struct {
|
||||
char name[MAX_CMD_NAME_LEN + 1];
|
||||
char cmdContent[MAX_CMD_CONTENT_LEN + 1];
|
||||
};
|
||||
|
||||
class StartupInitUTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase()
|
||||
@@ -72,8 +79,7 @@ public:
|
||||
g_supportedCmds.push_back(std::string("chown "));
|
||||
g_supportedCmds.push_back(std::string("mount "));
|
||||
g_supportedCmds.push_back(std::string("loadcfg "));
|
||||
|
||||
mode_t mode = DEFAULT_DIR_MODE;
|
||||
const mode_t mode = 0755;
|
||||
if (mkdir(TEST_DRI.c_str(), mode) != 0) {
|
||||
if (errno != EEXIST) {
|
||||
printf("[----------] StartupInitUTest, mkdir for %s failed, error %d.\n",\
|
||||
@@ -82,7 +88,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
FILE* testFile = fopen(TEST_FILE.c_str(), "w+");
|
||||
FILE *testFile = fopen(TEST_FILE.c_str(), "w+");
|
||||
if (testFile == nullptr) {
|
||||
printf("[----------] StartupInitUTest, open file %s failed, error %d.\n",\
|
||||
TEST_FILE.c_str(), errno);
|
||||
@@ -129,6 +135,41 @@ public:
|
||||
void TearDown() {}
|
||||
};
|
||||
|
||||
void ParseCmdLine(const char *content, TestCmdLine *resCmd)
|
||||
{
|
||||
if (content == nullptr || resCmd == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const struct CmdTable *cmd = GetCmdByName(content);
|
||||
if (cmd == nullptr) {
|
||||
printf("Cannot support command: %s \n", content);
|
||||
(void)memset_s(resCmd, sizeof(TestCmdLine), 0, sizeof(TestCmdLine));
|
||||
return;
|
||||
}
|
||||
if (strlen(content) <= (strlen(cmd->name) + 1)) {
|
||||
printf("Error content for command: %s \n", content);
|
||||
(void)memset_s(resCmd, sizeof(TestCmdLine), 0, sizeof(TestCmdLine));
|
||||
return;
|
||||
}
|
||||
int ret1 = strcpy_s(resCmd->name, MAX_CMD_NAME_LEN, cmd->name);
|
||||
int ret2 = strcpy_s(resCmd->cmdContent, MAX_CMD_CONTENT_LEN, content + strlen(cmd->name));
|
||||
if (ret1 || ret2) {
|
||||
printf("Error copy command: %s \n", content);
|
||||
(void)memset_s(resCmd, sizeof(TestCmdLine), 0, sizeof(TestCmdLine));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void DoCmd(const TestCmdLine *resCmd)
|
||||
{
|
||||
if (resCmd == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
DoCmdByName(resCmd->name, resCmd->cmdContent);
|
||||
}
|
||||
|
||||
/*
|
||||
** @tc.name: cmdFuncParseCmdTest_001
|
||||
** @tc.desc: parse function, nullptr test
|
||||
@@ -149,7 +190,7 @@ HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_001, TestSize.Level0)
|
||||
**/
|
||||
HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_002, TestSize.Level0)
|
||||
{
|
||||
CmdLine curCmdLine;
|
||||
TestCmdLine curCmdLine;
|
||||
memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine));
|
||||
|
||||
ParseCmdLine(nullptr, &curCmdLine);
|
||||
@@ -177,7 +218,7 @@ HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_002, TestSize.Level0)
|
||||
**/
|
||||
HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_003, TestSize.Level0)
|
||||
{
|
||||
CmdLine curCmdLine;
|
||||
TestCmdLine curCmdLine;
|
||||
memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine));
|
||||
|
||||
for (size_t i = 0; i < g_supportedCmds.size(); ++i) {
|
||||
@@ -195,7 +236,7 @@ HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_003, TestSize.Level0)
|
||||
**/
|
||||
HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_004, TestSize.Level0)
|
||||
{
|
||||
CmdLine curCmdLine;
|
||||
TestCmdLine curCmdLine;
|
||||
memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine));
|
||||
|
||||
char toLongContent[MAX_CMD_CONTENT_LEN + 10];
|
||||
@@ -203,7 +244,7 @@ HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_004, TestSize.Level0)
|
||||
toLongContent[MAX_CMD_CONTENT_LEN + 9] = '\0';
|
||||
for (size_t i = 0; i < g_supportedCmds.size(); ++i) {
|
||||
size_t curCmdLen = g_supportedCmds[i].length();
|
||||
char* curCmd = (char*)malloc(curCmdLen + MAX_CMD_CONTENT_LEN + 10);
|
||||
char *curCmd = (char *)malloc(curCmdLen + MAX_CMD_CONTENT_LEN + 10);
|
||||
if (curCmd == nullptr) {
|
||||
printf("[----------] StartupInitUTest, cmdFuncParseCmdTest004, malloc failed.\n");
|
||||
break;
|
||||
@@ -236,7 +277,7 @@ HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_004, TestSize.Level0)
|
||||
**/
|
||||
HWTEST_F(StartupInitUTest, cmdFuncParseCmdTest_005, TestSize.Level0)
|
||||
{
|
||||
CmdLine curCmdLine;
|
||||
TestCmdLine curCmdLine;
|
||||
memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine));
|
||||
|
||||
ParseCmdLine("start InitTestService", &curCmdLine);
|
||||
@@ -280,7 +321,7 @@ HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_001, TestSize.Level0)
|
||||
**/
|
||||
HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_002, TestSize.Level0)
|
||||
{
|
||||
CmdLine curCmdLine;
|
||||
TestCmdLine curCmdLine;
|
||||
memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine));
|
||||
|
||||
std::string cmdStr = "start ";
|
||||
@@ -300,7 +341,7 @@ HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_002, TestSize.Level0)
|
||||
**/
|
||||
HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_003, TestSize.Level0)
|
||||
{
|
||||
CmdLine curCmdLine;
|
||||
TestCmdLine curCmdLine;
|
||||
memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine));
|
||||
|
||||
std::string cmdStr = "mkdir ";
|
||||
@@ -312,7 +353,7 @@ HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_003, TestSize.Level0)
|
||||
DoCmd(&curCmdLine);
|
||||
|
||||
// make sure that the directory does not exist
|
||||
DIR* dirTmp = opendir(cmdContentStr.c_str());
|
||||
DIR *dirTmp = opendir(cmdContentStr.c_str());
|
||||
EXPECT_TRUE(dirTmp == nullptr);
|
||||
EXPECT_TRUE(errno == ENOENT);
|
||||
if (dirTmp != nullptr) { // just in case
|
||||
@@ -346,7 +387,7 @@ HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_003, TestSize.Level0)
|
||||
**/
|
||||
HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_004, TestSize.Level0)
|
||||
{
|
||||
CmdLine curCmdLine;
|
||||
TestCmdLine curCmdLine;
|
||||
memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine));
|
||||
|
||||
std::string cmdStr = "chmod ";
|
||||
@@ -403,7 +444,7 @@ HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_004, TestSize.Level0)
|
||||
**/
|
||||
HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_005, TestSize.Level0)
|
||||
{
|
||||
CmdLine curCmdLine;
|
||||
TestCmdLine curCmdLine;
|
||||
memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine));
|
||||
|
||||
std::string cmdStr = "chown ";
|
||||
@@ -440,7 +481,7 @@ HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_005, TestSize.Level0)
|
||||
**/
|
||||
HWTEST_F(StartupInitUTest, cmdFuncDoCmdTest_006, TestSize.Level0)
|
||||
{
|
||||
CmdLine curCmdLine;
|
||||
TestCmdLine curCmdLine;
|
||||
|
||||
// mkdir success
|
||||
std::string cmdStr = "mkdir ";
|
||||
@@ -519,8 +560,8 @@ HWTEST_F(StartupInitUTest, cfgCheckStat_001, TestSize.Level0)
|
||||
|
||||
static char* ReadFileToBuf()
|
||||
{
|
||||
char* buffer = nullptr;
|
||||
FILE* fd = nullptr;
|
||||
char *buffer = nullptr;
|
||||
FILE *fd = nullptr;
|
||||
struct stat fileStat = {0};
|
||||
(void)stat(CFG_FILE.c_str(), &fileStat);
|
||||
do {
|
||||
@@ -549,9 +590,9 @@ static char* ReadFileToBuf()
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static cJSON* GetArrItem(const cJSON* fileRoot, int& arrSize, const std::string& arrName)
|
||||
static cJSON *GetArrItem(const cJSON *fileRoot, int &arrSize, const std::string &arrName)
|
||||
{
|
||||
cJSON* arrItem = cJSON_GetObjectItemCaseSensitive(fileRoot, arrName.c_str());
|
||||
cJSON *arrItem = cJSON_GetObjectItemCaseSensitive(fileRoot, arrName.c_str());
|
||||
arrSize = cJSON_GetArraySize(arrItem);
|
||||
if (arrSize <= 0) {
|
||||
return nullptr;
|
||||
@@ -559,7 +600,7 @@ static cJSON* GetArrItem(const cJSON* fileRoot, int& arrSize, const std::string&
|
||||
return arrItem;
|
||||
}
|
||||
|
||||
static int IsForbidden(const char* fieldStr)
|
||||
static int IsForbidden(const char *fieldStr)
|
||||
{
|
||||
size_t fieldLen = strlen(fieldStr);
|
||||
size_t forbidStrLen = strlen("/bin/sh");
|
||||
@@ -587,31 +628,31 @@ static void CheckService(const cJSON* curItem)
|
||||
return;
|
||||
}
|
||||
|
||||
char* nameStr = cJSON_GetStringValue(cJSON_GetObjectItem(curItem, "name"));
|
||||
char *nameStr = cJSON_GetStringValue(cJSON_GetObjectItem(curItem, "name"));
|
||||
if (nameStr == nullptr) {
|
||||
EXPECT_TRUE(nameStr != nullptr);
|
||||
} else {
|
||||
EXPECT_TRUE(strlen(nameStr) > 0);
|
||||
}
|
||||
|
||||
cJSON* pathArgsItem = cJSON_GetObjectItem(curItem, "path");
|
||||
cJSON *pathArgsItem = cJSON_GetObjectItem(curItem, "path");
|
||||
EXPECT_TRUE(cJSON_IsArray(pathArgsItem));
|
||||
|
||||
int pathArgsCnt = cJSON_GetArraySize(pathArgsItem);
|
||||
EXPECT_TRUE(pathArgsCnt > 0);
|
||||
EXPECT_TRUE(pathArgsCnt <= MAX_PATH_ARGS_CNT);
|
||||
EXPECT_TRUE(pathArgsCnt <= TEST_MAX_PATH_ARGS_CNT);
|
||||
|
||||
for (int i = 0; i < pathArgsCnt; ++i) {
|
||||
char* curParam = cJSON_GetStringValue(cJSON_GetArrayItem(pathArgsItem, i));
|
||||
EXPECT_TRUE(curParam != NULL);
|
||||
char *curParam = cJSON_GetStringValue(cJSON_GetArrayItem(pathArgsItem, i));
|
||||
EXPECT_TRUE(curParam != nullptr);
|
||||
EXPECT_TRUE(strlen(curParam) > 0);
|
||||
EXPECT_TRUE(strlen(curParam) <= MAX_ONE_ARG_LEN);
|
||||
EXPECT_TRUE(strlen(curParam) <= TEST_MAX_ONE_ARG_LEN);
|
||||
if (i == 0) {
|
||||
EXPECT_TRUE(IsForbidden(curParam) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
cJSON* filedJ = cJSON_GetObjectItem(curItem, "uid");
|
||||
cJSON *filedJ = cJSON_GetObjectItem(curItem, "uid");
|
||||
EXPECT_TRUE(cJSON_IsNumber(filedJ));
|
||||
EXPECT_TRUE(cJSON_GetNumberValue(filedJ) >= 0.0);
|
||||
|
||||
@@ -630,7 +671,7 @@ static void CheckService(const cJSON* curItem)
|
||||
int capsCnt = cJSON_GetArraySize(filedJ);
|
||||
EXPECT_TRUE(capsCnt <= MAX_CAPS_CNT_FOR_ONE_SERVICE);
|
||||
for (int i = 0; i < capsCnt; ++i) {
|
||||
cJSON* capJ = cJSON_GetArrayItem(filedJ, i);
|
||||
cJSON *capJ = cJSON_GetArrayItem(filedJ, i);
|
||||
EXPECT_TRUE(cJSON_IsNumber(capJ));
|
||||
EXPECT_TRUE(cJSON_GetNumberValue(capJ) >= 0.0);
|
||||
|
||||
@@ -644,21 +685,21 @@ static void CheckService(const cJSON* curItem)
|
||||
}
|
||||
}
|
||||
|
||||
static void CheckServices(const cJSON* fileRoot)
|
||||
static void CheckServices(const cJSON *fileRoot)
|
||||
{
|
||||
int servArrSize = 0;
|
||||
cJSON* serviceArr = GetArrItem(fileRoot, servArrSize, SERVICE_ARR_NAME_IN_JSON);
|
||||
cJSON *serviceArr = GetArrItem(fileRoot, servArrSize, SERVICE_ARR_NAME_IN_JSON);
|
||||
EXPECT_TRUE(serviceArr != nullptr);
|
||||
EXPECT_TRUE(servArrSize <= MAX_SERVICES_COUNT_IN_FILE);
|
||||
|
||||
for (int i = 0; i < servArrSize; ++i) {
|
||||
cJSON* curItem = cJSON_GetArrayItem(serviceArr, i);
|
||||
cJSON *curItem = cJSON_GetArrayItem(serviceArr, i);
|
||||
EXPECT_TRUE(curItem != nullptr);
|
||||
CheckService(curItem);
|
||||
}
|
||||
}
|
||||
|
||||
static void CheckCmd(const CmdLine* resCmd)
|
||||
static void CheckCmd(const TestCmdLine *resCmd)
|
||||
{
|
||||
EXPECT_TRUE(strlen(resCmd->name) > 0);
|
||||
EXPECT_TRUE(strlen(resCmd->cmdContent) > 0);
|
||||
@@ -708,13 +749,13 @@ static void CheckCmd(const CmdLine* resCmd)
|
||||
}
|
||||
}
|
||||
|
||||
static void CheckJob(const cJSON* jobItem)
|
||||
static void CheckJob(const cJSON *jobItem)
|
||||
{
|
||||
if (jobItem == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
cJSON* cmdsItem = cJSON_GetObjectItem(jobItem, CMDS_ARR_NAME_IN_JSON.c_str());
|
||||
cJSON *cmdsItem = cJSON_GetObjectItem(jobItem, CMDS_ARR_NAME_IN_JSON.c_str());
|
||||
EXPECT_TRUE(cmdsItem != nullptr);
|
||||
EXPECT_TRUE(cJSON_IsArray(cmdsItem));
|
||||
|
||||
@@ -722,11 +763,11 @@ static void CheckJob(const cJSON* jobItem)
|
||||
EXPECT_TRUE(cmdLinesCnt <= MAX_CMD_CNT_IN_ONE_JOB);
|
||||
|
||||
for (int i = 0; i < cmdLinesCnt; ++i) {
|
||||
char* cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdsItem, i));
|
||||
char *cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdsItem, i));
|
||||
EXPECT_TRUE(cmdLineStr != nullptr);
|
||||
EXPECT_TRUE(strlen(cmdLineStr) > 0);
|
||||
|
||||
CmdLine resCmd;
|
||||
TestCmdLine resCmd;
|
||||
(void)memset_s(&resCmd, sizeof(resCmd), 0, sizeof(resCmd));
|
||||
ParseCmdLine(cmdLineStr, &resCmd);
|
||||
CheckCmd(&resCmd);
|
||||
@@ -736,7 +777,7 @@ static void CheckJob(const cJSON* jobItem)
|
||||
static void CheckJobs(const cJSON* fileRoot)
|
||||
{
|
||||
int jobArrSize = 0;
|
||||
cJSON* jobArr = GetArrItem(fileRoot, jobArrSize, JOBS_ARR_NAME_IN_JSON);
|
||||
cJSON *jobArr = GetArrItem(fileRoot, jobArrSize, JOBS_ARR_NAME_IN_JSON);
|
||||
EXPECT_TRUE(jobArr != nullptr);
|
||||
EXPECT_TRUE(jobArrSize == JOBS_IN_FILE_COUNT);
|
||||
|
||||
@@ -744,9 +785,9 @@ static void CheckJobs(const cJSON* fileRoot)
|
||||
bool findInit = false;
|
||||
bool findPostInit = false;
|
||||
for (int i = 0; i < jobArrSize; ++i) {
|
||||
cJSON* jobItem = cJSON_GetArrayItem(jobArr, i);
|
||||
cJSON *jobItem = cJSON_GetArrayItem(jobArr, i);
|
||||
EXPECT_TRUE(jobItem != nullptr);
|
||||
char* jobNameStr = cJSON_GetStringValue(cJSON_GetObjectItem(jobItem, "name"));
|
||||
char *jobNameStr = cJSON_GetStringValue(cJSON_GetObjectItem(jobItem, "name"));
|
||||
EXPECT_TRUE(jobNameStr != nullptr);
|
||||
if (strcmp(jobNameStr, "pre-init") == 0) {
|
||||
findPreInit = true;
|
||||
@@ -773,13 +814,13 @@ static void CheckJobs(const cJSON* fileRoot)
|
||||
**/
|
||||
HWTEST_F(StartupInitUTest, cfgCheckContent_001, TestSize.Level0)
|
||||
{
|
||||
char* fileBuf = ReadFileToBuf();
|
||||
char *fileBuf = ReadFileToBuf();
|
||||
if (fileBuf == nullptr) {
|
||||
EXPECT_TRUE(fileBuf != nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
cJSON* fileRoot = cJSON_Parse(fileBuf);
|
||||
cJSON *fileRoot = cJSON_Parse(fileBuf);
|
||||
free(fileBuf);
|
||||
fileBuf = nullptr;
|
||||
|
||||
@@ -799,7 +840,7 @@ HWTEST_F(StartupInitUTest, cfgCheckContent_001, TestSize.Level0)
|
||||
*/
|
||||
static void CreateIllegalCfg()
|
||||
{
|
||||
FILE* testCfgFile = fopen(TEST_CFG_ILLEGAL.c_str(), "w+");
|
||||
FILE *testCfgFile = fopen(TEST_CFG_ILLEGAL.c_str(), "w+");
|
||||
if (testCfgFile == nullptr) {
|
||||
printf("[----------] StartupInitUTest, open file %s failed, error %d.\n", TEST_CFG_ILLEGAL.c_str(), errno);
|
||||
return;
|
||||
@@ -823,7 +864,7 @@ static void CreateIllegalCfg()
|
||||
*/
|
||||
HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_001, TestSize.Level0)
|
||||
{
|
||||
CmdLine curCmdLine;
|
||||
TestCmdLine curCmdLine;
|
||||
memset_s(&curCmdLine, sizeof(curCmdLine), 0, sizeof(curCmdLine));
|
||||
|
||||
ParseCmdLine("loadcfg /patch/fstab.cfg", &curCmdLine);
|
||||
@@ -839,7 +880,7 @@ HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_001, TestSize.Level0)
|
||||
*/
|
||||
HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_002, TestSize.Level0)
|
||||
{
|
||||
CmdLine curCmdLine;
|
||||
TestCmdLine curCmdLine;
|
||||
std::string cmdStr = "loadcfg ";
|
||||
std::string cmdContentStr = "/patch/file_not_exist.cfg";
|
||||
struct stat testCfgStat = {0};
|
||||
@@ -879,12 +920,12 @@ HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_002, TestSize.Level0)
|
||||
*/
|
||||
HWTEST_F(StartupInitUTest, cmdFuncDoLoadCfgTest_003, TestSize.Level0)
|
||||
{
|
||||
CmdLine curCmdLine;
|
||||
TestCmdLine curCmdLine;
|
||||
std::string cmdStr = "loadcfg ";
|
||||
std::string cmdContentStr = "/patch/fstab.cfg";
|
||||
char buf[CAT_BUF_SIZE] = {0};
|
||||
struct stat testCfgStat = {0};
|
||||
FILE* fd = nullptr;
|
||||
FILE *fd = nullptr;
|
||||
size_t size;
|
||||
bool hasZpfs = false;
|
||||
std::string command = cmdStr + cmdContentStr;
|
||||
@@ -933,10 +974,8 @@ HWTEST_F(StartupInitUTest, cmdJobTest_001, TestSize.Level0)
|
||||
DoJob(nullptr);
|
||||
DoJob("job name does not exist");
|
||||
ReleaseAllJobs();
|
||||
RegisterServices(nullptr, 0);
|
||||
StartServiceByName("service name does not exist", false);
|
||||
StopAllServices();
|
||||
ReapServiceByPID(INVALID_PID);
|
||||
StopAllServices(0);
|
||||
ServiceReap(nullptr);
|
||||
EXPECT_NE(0, ServiceStart(nullptr));
|
||||
EXPECT_NE(0, ServiceStop(nullptr));
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init_cmds.h"
|
||||
#include "init_param.h"
|
||||
#include "init_unittest.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace std;
|
||||
|
||||
namespace init_ut {
|
||||
class CmdsUnitTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase(void)
|
||||
{
|
||||
InitParamService();
|
||||
};
|
||||
static void TearDownTestCase(void) {};
|
||||
void SetUp() {};
|
||||
void TearDown() {};
|
||||
};
|
||||
|
||||
HWTEST_F(CmdsUnitTest, TestGetValueForCmd, TestSize.Level1)
|
||||
{
|
||||
// 1, test one param
|
||||
SystemWriteParam("ro.test.1111.2222", "2.3.4.5.6.7.8");
|
||||
char *tmpParamValue = (char *)malloc(PARAM_VALUE_LEN_MAX + 1);
|
||||
if (tmpParamValue == nullptr) {
|
||||
EXPECT_EQ(1, 0);
|
||||
return;
|
||||
}
|
||||
tmpParamValue[0] = '\0';
|
||||
const char *cmd1 = "init.${ro.test.1111.2222}.usb.cfg";
|
||||
GetParamValue(cmd1, strlen(cmd1), tmpParamValue, PARAM_VALUE_LEN_MAX);
|
||||
printf("Tmp value %s \n", tmpParamValue);
|
||||
EXPECT_EQ(strcmp("init.2.3.4.5.6.7.8.usb.cfg", tmpParamValue), 0);
|
||||
|
||||
// 2, test two param
|
||||
const char *cmd2 = "init.${ro.test.1111.2222}.usb.${ro.test.1111.2222}";
|
||||
GetParamValue(cmd2, strlen(cmd2), tmpParamValue, PARAM_VALUE_LEN_MAX);
|
||||
printf("Tmp value %s \n", tmpParamValue);
|
||||
EXPECT_EQ(strcmp("init.2.3.4.5.6.7.8.usb.2.3.4.5.6.7.8", tmpParamValue), 0);
|
||||
|
||||
// 3, test two param
|
||||
const char *cmd3 = "${ro.test.1111.2222}.init.${ro.test.1111.2222}.usb.${ro.test.1111.2222}";
|
||||
GetParamValue(cmd3, strlen(cmd3), tmpParamValue, PARAM_VALUE_LEN_MAX);
|
||||
printf("Tmp value %s \n", tmpParamValue);
|
||||
EXPECT_EQ(strcmp("2.3.4.5.6.7.8.init.2.3.4.5.6.7.8.usb.2.3.4.5.6.7.8", tmpParamValue), 0);
|
||||
free(tmpParamValue);
|
||||
}
|
||||
HWTEST_F(CmdsUnitTest, TestDoCopy, TestSize.Level1)
|
||||
{
|
||||
DoCmdByName("copy ", "libdemo.z.so aaaa.so");
|
||||
}
|
||||
} // namespace init_ut
|
||||
Regular → Executable
+34
-38
@@ -1,38 +1,34 @@
|
||||
/*
|
||||
* 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_INITLITE_PERMS_H
|
||||
#define BASE_STARTUP_INITLITE_PERMS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define FULL_CAP 0xFFFFFFFF
|
||||
|
||||
// init
|
||||
#define DEFAULT_UMASK_INIT 022
|
||||
|
||||
// kit framework
|
||||
#define DEFAULT_UID_KIT_FRAMEWORK 3
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // BASE_STARTUP_INITLITE_PERMS_H
|
||||
/*
|
||||
* Copyright (c) 2020 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "init_unittest.h"
|
||||
|
||||
using namespace testing::ext;
|
||||
using namespace std;
|
||||
|
||||
namespace init_ut {
|
||||
class ServiceUnitTest : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase(void) {};
|
||||
static void TearDownTestCase(void) {};
|
||||
void SetUp() {};
|
||||
void TearDown() {};
|
||||
};
|
||||
|
||||
HWTEST_F(ServiceUnitTest, case01, TestSize.Level1)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace init_ut
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user