init: code Refactoring, watchdog, hdc_flashed, ramdisk

Signed-off-by: sun_fan <sun_fan1@hoperun.com>
This commit is contained in:
sun_fan
2021-10-14 16:43:33 +08:00
parent 2e42812b6b
commit 665ab179fb
128 changed files with 8334 additions and 4122 deletions
+2 -1
View File
@@ -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;
+50
View File
@@ -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"
}
+391
View File
@@ -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 SplitStringExtjust 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
View File
@@ -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
View File
@@ -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
View File
+2 -1
View File
@@ -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;
View File
@@ -14,7 +14,6 @@
*/
#include "init_socket.h"
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
Regular → Executable
View File
+5 -1
View File
@@ -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
View File
@@ -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",
+2 -4
View File
@@ -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
View File
@@ -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"]
}
]
}
+3
View File
@@ -1,4 +1,7 @@
{
"import" : [
"/vendor/etc/init.${ohos.boot.hardware}.usb.cfg"
],
"jobs" : [{
"name" : "boot",
"cmds" : [
+8 -8
View File
@@ -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
-70
View File
@@ -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
-89
View File
@@ -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
}
+2 -2
View File
@@ -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
View File
+4 -10
View File
@@ -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
+38 -10
View File
@@ -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
}
+1 -3
View File
@@ -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
+24 -15
View File
@@ -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
+12 -19
View File
@@ -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
+89
View File
@@ -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
+12 -8
View File
@@ -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
}
+100
View File
@@ -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
@@ -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
@@ -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
+130
View File
@@ -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;
}
+731
View File
@@ -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;
}
}
+101 -118
View File
@@ -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);
}
+94
View File
@@ -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);
}
}
+584
View File
@@ -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;
}
+149
View File
@@ -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;
}
+84
View File
@@ -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();
}
}
+60
View File
@@ -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;
}
+32 -55
View File
@@ -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;
}
}
+31
View File
@@ -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;
}
+77
View File
@@ -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;
}
+71
View File
@@ -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);
}
+23 -21
View File
@@ -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
+3 -5
View File
@@ -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));
}
+143
View File
@@ -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();
}
+322
View File
@@ -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;
}
+7 -6
View File
@@ -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);
}
+65
View File
@@ -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;
}
+4 -6
View File
@@ -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
+202
View File
@@ -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;
}
+76
View File
@@ -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;
}
@@ -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
}
+163
View File
@@ -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
View File
Regular → Executable
+4 -12
View File
@@ -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
View File
@@ -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
View File
@@ -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"
}
+2 -1
View File
@@ -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);
}
-1
View File
@@ -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;
+7 -3
View File
@@ -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;
+1 -1
View File
@@ -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;
+10 -4
View File
@@ -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;
+80 -8
View File
@@ -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++) {
View File
+4
View File
@@ -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
+1
View File
@@ -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
View File
View File
+14 -10
View File
@@ -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
View File
View File
+14 -8
View File
@@ -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);
}
+1 -1
View File
@@ -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);
-2
View File
@@ -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");
+1 -41
View File
@@ -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);
+6 -5
View File
@@ -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;
+114 -15
View File
@@ -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());
}
}
-1
View File
@@ -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)
{
+4 -4
View File
@@ -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);
}
+60 -22
View File
@@ -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_ {};
};
-168
View File
@@ -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
-84
View File
@@ -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;
}
-166
View File
@@ -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
}
-216
View File
@@ -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;
}
-876
View File
@@ -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;
}
}
}
-138
View File
@@ -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;
}
-128
View File
@@ -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;
}
+145
View File
@@ -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"
]
}
+15 -13
View File
@@ -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",
]
+97 -58
View File
@@ -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
View File
@@ -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
+34 -38
View File
@@ -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