提交 77b2875a 编写于 作者: O openharmony_ci 提交者: Gitee

!142 feat:重构代码

Merge pull request !142 from 熊磊/init1014
......@@ -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;
......
# 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"
}
/*
* 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 <ctype.h>
#include <fcntl.h>
#include <libgen.h>
#include <limits.h>
#include <stdio.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"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
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;
}
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++) {
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);
fclose(fp);
fp = NULL;
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 %zu. skip it\n", file, ln);
continue;
}
}
if (line != NULL) {
free(line);
}
(void)fclose(fp);
fp = NULL;
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 *mountFlag, char *fsSpecificData, size_t fsSpecificDataSize)
{
unsigned long flags = 0;
if (mountFlag == 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(mountFlag, ",", &flagCount, maxCount);
if (flagsVector == NULL || flagCount == 0) {
// No flags or something wrong in SplitStringExt,just return.
return 0;
}
for (int i = 0; i < flagCount; i++) {
char *p = flagsVector[i];
if (IsDefaultMountFlags(p)) {
flags |= ParseDefaultMountFlag(p);
} else {
if (strncat_s(fsSpecificData, fsSpecificDataSize - 1, p, strlen(p)) != EOK) {
printf("[fs_manager][warning], Failed to append mount flag \" %s \", ignore it\n", p);
continue;
}
if (i == flagCount - 1) { // last flags, do not need to append ','
break;
}
// Combined each mount flag with ','
if (strncat_s(fsSpecificData, fsSpecificDataSize - 1, ",", 1) != EOK) {
printf("[fs_manager][warning], Failed to append comma\n");
break; // If cannot add ',' to the end of flags, there is not reason to continue.
}
}
}
FreeStringVector(flagsVector, flagCount);
return flags;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
\ No newline at end of file
/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <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"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#define FS_MANAGER_BUFFER_SIZE 512
#define BLOCK_SIZE_BUFFER (64)
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;
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);
}
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;
}
(void)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
/*
* 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
#include <stdbool.h>
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
/* 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 *mountFlag, char *fsSpecificFlags, size_t fsSpecificFlagSize);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // STARTUP_FS_MANAGER_H
\ No newline at end of file
文件模式从 100644 更改为 100755
......@@ -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;
......
文件模式从 100644 更改为 100755
......@@ -14,7 +14,6 @@
*/
#include "init_socket.h"
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
......
文件模式从 100644 更改为 100755
......@@ -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"
]
}
}
......
......@@ -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_common_service.c",
"init/init_config.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_mount.c",
"init/standard/init_reboot.c",
"init/standard/init_service.c",
"init/standard/init_signal_handler.c",
"init/standard/switch_root.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",
]
......@@ -124,6 +133,11 @@ if (defined(ohos_lite)) {
"//third_party/toybox:toybox",
]
}
if (disable_init_two_stages) {
defines = [ "DISABLE_INIT_TWO_STAGES" ]
}
install_images = [
"system",
"updater",
......@@ -137,6 +151,7 @@ if (defined(ohos_lite)) {
":init",
":init_etc",
"//base/startup/init_lite/interfaces/innerkits/dynamic_service:dynamic_service",
"//base/startup/init_lite/interfaces/innerkits/fs_manager:libfsmanager_shared",
"//base/startup/init_lite/interfaces/innerkits/socket:libsocket",
"//base/startup/init_lite/services/cmds/reboot:reboot",
"//base/startup/init_lite/services/cmds/service_control:service_control",
......@@ -152,7 +167,12 @@ if (defined(ohos_lite)) {
# init etc files group
ohos_prebuilt_etc("init.cfg") {
source = "//base/startup/init_lite/services/etc/init.cfg"
if (disable_init_two_stages) {
source =
"//base/startup/init_lite/services/etc/init.without_two_stages.cfg"
} else {
source = "//base/startup/init_lite/services/etc/init.cfg"
}
part_name = "init"
}
......
......@@ -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) {
......
......@@ -2,9 +2,7 @@
"import" : [
"/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 +14,10 @@
"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}",
"load_persist_params "
]
}, {
"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"]
}
]
}
{
"import" : [
"/vendor/etc/init.${ohos.boot.hardware}.usb.cfg"
],
"jobs" : [{
"name" : "boot",
"cmds" : [
......
此差异已折叠。
......@@ -27,13 +27,13 @@ hw_sc.build.os.version=2.2.0
# ohos release type
hw_sc.build.os.releasetype=Canary1
ro.actionable_compatible_property.enabled=false
ro.postinstall.fstab.prefix=/system
ro.secure=1
const.actionable_compatible_property.enabled=false
const.postinstall.fstab.prefix=/system
const.secure=1
security.perf_harden=1
ro.allow.mock.location=0
ro.debuggable=1
ro.build.characteristics="default"
ro.product.model="ohos"
ro.product.name="OpenHarmony 2.0 Canary"
const.allow.mock.location=0
const.debuggable=1
const.build.characteristics="default"
const.product.model="ohos"
const.product.name="OpenHarmony 2.0 Canary"
persist.sys.usb.config=hdc
/*
* 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,20 +12,29 @@
* 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"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#define MAX_CMD_NAME_LEN 32
#define MAX_CMD_CNT_IN_ONE_JOB 200
#define MAX_CMD_CONTENT_LEN 256
#define MAX_JOB_NAME_LEN 64
// one cmd line
typedef struct {
char name[MAX_CMD_NAME_LEN + 1]; // cmd name
char cmdContent[MAX_CMD_CONTENT_LEN + 1]; // 256 cmd content
} CmdLine;
typedef struct {
int cmdNum;
CmdLine cmds[0];
} CmdLines;
// one job, could have many cmd lines
typedef struct {
......@@ -34,10 +43,6 @@ typedef struct {
CmdLine* cmdLines;
} Job;
void ParseAllJobs(const cJSON* fileRoot);
void DoJob(const char* jobName);
void ReleaseAllJobs(void);
void DumpAllJobs(void);
#ifdef __cplusplus
#if __cplusplus
}
......
......@@ -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
}
......
......@@ -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
......
文件模式从 100644 更改为 100755
......@@ -13,13 +13,9 @@
* limitations under the License.
*/
#ifndef INIT_CAPABILITY_H
#define INIT_CAPABILITY_H
#ifndef INIT_SWITCH_ROOT_H
#define INIT_SWITCH_ROOT_H
#include "cJSON.h"
#include "init_service.h"
int GetServiceCaps(const cJSON* curArrItem, Service* curServ);
#endif
int SwitchRoot(const char *newRoot);
#endif // INIT_SWITCH_ROOT_H
\ No newline at end of file
/*
* 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
}
/*
* 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
......
/*
* 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
/*
* 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
\ No newline at end of file
#endif // BASE_STARTUP_INITLITE_ADAPTER_H
\ No newline at end of file
/*
* 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,55 +12,74 @@
* 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
#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
#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
#define OPTIONS_SIZE 128
#define SUPPORT_MAX_ARG_FOR_EXEC 10
// one cmd line
typedef struct {
char name[MAX_CMD_NAME_LEN + 1];
int cmdIndex;
char cmdContent[MAX_CMD_CONTENT_LEN + 1];
} CmdLine;
typedef struct {
int cmdNum;
CmdLine cmds[0];
} CmdLines;
struct CmdArgs {
int argc;
char **argv;
char *argv[0];
};
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);
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);
const char *GetMatchCmd(const char *cmdStr, unsigned int *index);
const char *GetCmdKey(unsigned int index);
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
}
......
/*
* 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_JOBS_INTERNAL_H
#define BASE_STARTUP_INITLITE_JOBS_INTERNAL_H
#include "cJSON.h"
#include "init_cmds.h"
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
#define MAX_JOB_NAME_LEN 64
// one job, could have many cmd lines
typedef struct {
char name[MAX_JOB_NAME_LEN + 1];
CmdLines *cmdLines;
} Job;
void ParseAllJobs(const cJSON *fileRoot);
void DoJob(const char *jobName);
void ReleaseAllJobs(void);
void DumpAllJobs(void);
#ifndef DISABLE_INIT_TWO_STAGES
#define INIT_CONFIGURATION_FILE "/etc/init.cfg"
#else
#define INIT_CONFIGURATION_FILE "/etc/init.without_two_stages.cfg"
#endif
#define OTHER_CFG_PATH "/system/etc/init"
#define MAX_PATH_ARGS_CNT 20
void ReadConfig(void);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // BASE_STARTUP_INITLITE_JOBS_INTERNAL_H
/*
* 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,14 @@
* 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" {
......@@ -31,19 +31,23 @@ extern "C" {
#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 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"
......@@ -56,29 +60,36 @@ typedef struct {
unsigned int capsCnt;
} Perms;
struct OnRestartCmd {
CmdLine *cmdLine;
int cmdNum;
};
typedef struct {
int count;
char **argv;
} ServiceArgs;
typedef struct {
char name[MAX_SERVICE_NAME + 1];
char** pathArgs;
int pathArgsCnt;
int pid;
int crashCnt;
ListNode node;
char name[MAX_SERVICE_NAME + 1];
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;
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
......
/*
* 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
......
/*
* 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
/*
* 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;
}
此差异已折叠。
/*
* 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);
}
/*
* 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;
}
/*
* 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_internal.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);
}
}
此差异已折叠。
/*
* 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,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "init_service_socket.h"
#include <ctype.h>
......@@ -24,19 +23,29 @@
#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 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)
static int GetSocketAddr(struct sockaddr_un *addr, const char *name)
{
if (sockopt == NULL || sockopt->name == NULL) {
return -1;
}
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;
......@@ -45,63 +54,53 @@ static int CreateSocket(struct ServiceSocket *sockopt)
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))) {
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);
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);
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);
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 ");
INIT_LOGI("CreateSocket %s success", sockopt->name);
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) {
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, MAX_SOCKET_FD_LEN, MAX_SOCKET_FD_LEN - 1, "%d", fd) < 0) {
if (snprintf_s(val, sizeof(val), sizeof(val) - 1, "%d", fd) < 0) {
return -1;
}
int ret = setenv(pubName, val, 1);
......@@ -113,20 +112,15 @@ static int SetSocketEnv(int fd, const char *name)
return 0;
}
int DoCreateSocket(struct ServiceSocket *sockopt)
int CreateServiceSocket(ServiceSocket *sockopt)
{
if (sockopt == NULL) {
return -1;
}
struct ServiceSocket *tmpSock = sockopt;
INIT_CHECK(sockopt != NULL, return 0);
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;
......@@ -136,3 +130,20 @@ int DoCreateSocket(struct ServiceSocket *sockopt)
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;
}
\ No newline at end of file
/*
* Copyright (c) 2020 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "init.h"
#include "init_log.h"
#include "init_jobs_internal.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)
{
return;
}
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();
}
}
/*
* 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 <stdlib.h>
#include <string.h>
#include "init.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;
}
/*
* 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,8 +12,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "init_jobs.h"
#include "init_jobs_internal.h"
#include <stdio.h>
#include <string.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);
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;
int ret = GetCmdLinesFromJson(cmdsItem, &resJob->cmdLines);
if (ret != 0) {
INIT_LOGE("ParseJob, faild to get cmds for job!");
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,8 +154,6 @@ 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;
}
}
......@@ -183,4 +161,3 @@ void ReleaseAllJobs(void)
g_jobs = NULL;
g_jobCnt = 0;
}
/*
* 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;
}
/*
* 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;
}
\ No newline at end of file
/*
* 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);
}
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
/*
* 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_internal.h"
#include "init_param.h"
void DoReboot(const char *value);
#endif
void ParseAllJobs(const cJSON *fileRoot)
{
ParseTriggerConfig(fileRoot);
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
文件模式从 100644 更改为 100755
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
文件模式从 100644 更改为 100755
......@@ -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
......
文件模式从 100644 更改为 100755
文件模式从 100644 更改为 100755
文件模式从 100644 更改为 100755
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册