diff --git a/OAT.xml b/OAT.xml
index 32f3b55..5f8a157 100644
--- a/OAT.xml
+++ b/OAT.xml
@@ -62,7 +62,8 @@
-
+
+
diff --git a/interfaces/innerkits/dynamic_service/dynamic_service.c b/interfaces/innerkits/dynamic_service/dynamic_service.c
index ada23dc..db4a8c0 100755
--- a/interfaces/innerkits/dynamic_service/dynamic_service.c
+++ b/interfaces/innerkits/dynamic_service/dynamic_service.c
@@ -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;
diff --git a/interfaces/innerkits/fs_manager/BUILD.gn b/interfaces/innerkits/fs_manager/BUILD.gn
new file mode 100755
index 0000000..add5f51
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/BUILD.gn
@@ -0,0 +1,50 @@
+# Copyright (c) 2021 Huawei Device Co., Ltd.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/ohos.gni")
+
+fs_manager_sources = [
+ "fstab.c",
+ "fstab_mount.c",
+]
+
+fs_manager_include_dirs = [
+ "//base/startup/init_lite/interfaces/innerkits/include",
+ "//third_party/bounds_checking_function/include",
+ "//base/startup/init_lite/services/log",
+ "//base/startup/init_lite/services/include",
+]
+
+fs_manager_deps = [
+ "//base/startup/init_lite/services/log:init_log",
+ "//base/startup/init_lite/services/utils:libinit_utils",
+ "//third_party/bounds_checking_function:libsec_static",
+]
+
+ohos_shared_library("libfsmanager_shared") {
+ sources = fs_manager_sources
+ deps = fs_manager_deps
+ include_dirs = fs_manager_include_dirs
+ part_name = "init"
+ install_images = [
+ "system",
+ ]
+}
+
+ohos_static_library("libfsmanager_static") {
+ sources = fs_manager_sources
+ deps = fs_manager_deps
+ include_dirs = fs_manager_include_dirs
+ part_name = "init"
+}
+
diff --git a/interfaces/innerkits/fs_manager/fstab.c b/interfaces/innerkits/fs_manager/fstab.c
new file mode 100755
index 0000000..37a52fc
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/fstab.c
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "fs_manager/fs_manager.h"
+#include "init_utils.h"
+#include "securec.h"
+
+struct FsManagerFlags {
+ char *name;
+ unsigned int flags;
+};
+
+struct MountFlags {
+ char *name;
+ unsigned long flags;
+};
+
+unsigned int ConvertFlags(char *flagBuffer)
+{
+ static struct FsManagerFlags fsFlags[] = {
+ {"check", FS_MANAGER_CHECK},
+ {"wait", FS_MANAGER_WAIT},
+ {"required", FS_MANAGER_REQUIRED},
+ };
+
+ if (flagBuffer == NULL || *flagBuffer == '\0') {
+ // No valid flags.
+ return 0;
+ }
+ printf("[fs_manager][debug], fstab flags string: %s\n", flagBuffer);
+ int flagCount = 0;
+ unsigned int flags = 0;
+ const int maxCount = 3;
+ char **vector = SplitStringExt(flagBuffer, ",", &flagCount, maxCount);
+ if (vector == NULL || flagCount == 0) {
+ return 0;
+ }
+
+ for (size_t i = 0; i < ARRAY_LENGTH(fsFlags); i++) {
+ for (int j = 0; j < flagCount; j++) {
+ printf("[fs_manager][debug], flag: %s\n", vector[j]);
+ if (strcmp(fsFlags[i].name, vector[j]) == 0) {
+ flags |= fsFlags[i].flags;
+ }
+ }
+ }
+ FreeStringVector(vector, flagCount);
+ return flags;
+}
+
+static void AddToFstab(Fstab *fstab, FstabItem *item)
+{
+ if (fstab == NULL || item == NULL) {
+ return;
+ }
+ if (fstab->head != NULL) {
+ item->next = fstab->head->next;
+ fstab->head->next = item;
+ } else {
+ fstab->head = item;
+ }
+}
+
+void ReleaseFstabItem(FstabItem *item)
+{
+ if (item != NULL) {
+ if (item->deviceName != NULL) {
+ free(item->deviceName);
+ item->deviceName = NULL;
+ }
+
+ if (item->mountPoint != NULL) {
+ free(item->mountPoint);
+ item->mountPoint = NULL;
+ }
+
+ if (item->fsType != NULL) {
+ free(item->fsType);
+ item->fsType = NULL;
+ }
+
+ if (item->mountOptions != NULL) {
+ free(item->mountOptions);
+ item->mountOptions = NULL;
+ }
+ free(item);
+ item = NULL;
+ }
+}
+
+void ReleaseFstab(Fstab *fstab)
+{
+ if (fstab != NULL) {
+ FstabItem *item = fstab->head;
+ while (item != NULL) {
+ FstabItem *tmp = item->next;
+ ReleaseFstabItem(item);
+ item = tmp;
+ }
+ free(fstab);
+ fstab = NULL;
+ }
+}
+
+static int ParseFstabPerLine(char *str, Fstab *fstab, bool procMounts)
+{
+ if (str == NULL || fstab == NULL) {
+ return -1;
+ }
+ const char *separator = " \t";
+ char *rest = NULL;
+ FstabItem *item = NULL;
+ char *p = NULL;
+
+ if ((item = (FstabItem *)calloc(1, sizeof(FstabItem))) == NULL) {
+ errno = ENOMEM;
+ printf("[fs_manager] Allocate memory for FS table item failed, err = %d\n", errno);
+ return -1;
+ }
+
+ do {
+ if ((p = strtok_r(str, separator, &rest)) == NULL) {
+ fprintf(stderr, "Failed to parse block device.\n");
+ break;
+ }
+ item->deviceName = strdup(p);
+
+ if ((p = strtok_r(NULL, separator, &rest)) == NULL) {
+ fprintf(stderr, "Failed to parse mount point.\n");
+ break;
+ }
+ item->mountPoint = strdup(p);
+
+ if ((p = strtok_r(NULL, separator, &rest)) == NULL) {
+ fprintf(stderr, "Failed to parse fs type.\n");
+ break;
+ }
+ item->fsType = strdup(p);
+
+ if ((p = strtok_r(NULL, separator, &rest)) == NULL) {
+ fprintf(stderr, "Failed to parse mount options.\n");
+ break;
+ }
+ item->mountOptions = strdup(p);
+
+ if ((p = strtok_r(NULL, separator, &rest)) == NULL) {
+ fprintf(stderr, "Failed to parse fs manager flags.\n");
+ break;
+ }
+ // @fsManagerFlags only for fstab
+ // Ignore it if we read from /proc/mounts
+ if (!procMounts) {
+ item->fsManagerFlags = ConvertFlags(p);
+ } else {
+ item->fsManagerFlags = 0;
+ }
+ AddToFstab(fstab, item);
+ return 0;
+ } while (0);
+
+ free(item);
+ item = NULL;
+ return -1;
+}
+
+Fstab *ReadFstabFromFile(const char *file, bool procMounts)
+{
+ char *line = NULL;
+ size_t allocn = 0;
+ ssize_t readn = 0;
+ Fstab *fstab = NULL;
+
+ if (file == NULL) {
+ printf("[fs_manager], invalid file\n");
+ return NULL;
+ }
+
+ FILE *fp = fopen(file, "r");
+ if (fp == NULL) {
+ printf("[fs_manager] Open %s failed, err = %d", file, errno);
+ return NULL;
+ }
+
+ if ((fstab = (Fstab *)calloc(1, sizeof(Fstab))) == NULL) {
+ printf("[fs_manager] Allocate memory for FS table failed, err = %d\n", errno);
+ return NULL;
+ }
+
+ // Record line number of fstab file
+ size_t ln = 0;
+ while ((readn = getline(&line, &allocn, fp)) != -1) {
+ char *p = NULL;
+ ln++;
+ if (line[readn - 1] == '\n') {
+ line[readn - 1] = '\0';
+ }
+ p = line;
+ while (isspace(*p)) {
+ p++;
+ }
+
+ if (*p == '\0' || *p == '#') {
+ continue;
+ }
+
+ if (ParseFstabPerLine(p, fstab, procMounts) < 0) {
+ if (errno == ENOMEM) {
+ // Ran out of memory, there is no reason to continue.
+ break;
+ }
+ // If one line in fstab file parsed with a failure. just give a warning
+ // and skip it.
+ printf("[fs_manager][warning] Cannot parse file \" %s \" at line %u. skip it\n", file, ln);
+ continue;
+ }
+ }
+ if (line != NULL) {
+ free(line);
+ }
+ return fstab;
+}
+
+FstabItem *FindFstabItemForMountPoint(Fstab fstab, const char *mp)
+{
+ FstabItem *item = NULL;
+ if (mp != NULL) {
+ for (item = fstab.head; item != NULL; item = item->next) {
+ if (strcmp(item->mountPoint, mp) == 0) {
+ break;
+ }
+ }
+ }
+ return item;
+}
+
+FstabItem *FindFstabItemForPath(Fstab fstab, const char *path)
+{
+ FstabItem *item = NULL;
+
+ if (path == NULL) {
+ return NULL;
+ }
+
+ char tmp[PATH_MAX] = {0};
+ char *dir = NULL;
+ if (strncpy_s(tmp, PATH_MAX -1, path, strlen(path)) != EOK) {
+ printf("[fs_manager][error], Failed to copy path\n");
+ return NULL;
+ }
+
+ dir = tmp;
+ while (true) {
+ item = FindFstabItemForMountPoint(fstab, dir);
+ if (item != NULL) {
+ break;
+ }
+ dir = dirname(dir);
+ // Reverse walk through path and met "/", just quit.
+ if (dir == NULL || strcmp(dir, "/") == 0) {
+ break;
+ }
+ }
+ return item;
+}
+
+static const struct MountFlags mountFlags[] = {
+ { "noatime", MS_NOATIME },
+ { "noexec", MS_NOEXEC },
+ { "nosuid", MS_NOSUID },
+ { "nodev", MS_NODEV },
+ { "nodiratime", MS_NODIRATIME },
+ { "ro", MS_RDONLY },
+ { "rw", 0 },
+ { "sync", MS_SYNCHRONOUS },
+ { "remount", MS_REMOUNT },
+ { "bind", MS_BIND },
+ { "rec", MS_REC },
+ { "unbindable", MS_UNBINDABLE },
+ { "private", MS_PRIVATE },
+ { "slave", MS_SLAVE },
+ { "shared", MS_SHARED },
+ { "defaults", 0 },
+};
+
+static bool IsDefaultMountFlags(const char *str) {
+ bool isDefault = false;
+
+ if (str != NULL) {
+ for (size_t i = 0; i < ARRAY_LENGTH(mountFlags); i++) {
+ if (strcmp(str, mountFlags[i].name) == 0) {
+ isDefault = true;
+ }
+ }
+ }
+ return isDefault;
+}
+
+static unsigned long ParseDefaultMountFlag(const char *str)
+{
+ unsigned long flags = 0;
+
+ if (str != NULL) {
+ for (size_t i = 0; i < ARRAY_LENGTH(mountFlags); i++) {
+ if (strcmp(str, mountFlags[i].name) == 0) {
+ flags = mountFlags[i].flags;
+ break;
+ }
+ }
+ }
+ return flags;
+}
+
+unsigned long GetMountFlags(char *mountFlags, char *fsSpecificData, size_t fsSpecificDataSize)
+{
+ unsigned long flags = 0;
+
+ if (mountFlags == NULL || fsSpecificData == NULL) {
+ return 0;
+ }
+
+ int flagCount = 0;
+ // Why max count of mount flags is 15?
+ // There are lots for mount flags defined in sys/mount.h
+ // But we only support to parse 15 in @ParseDefaultMountFlags() function
+ // So set default mount flag number to 15.
+ // If the item configured in fstab contains flag over than 15,
+ // @SplitStringExt can handle it and parse them all. but the parse function will drop it.
+ const int maxCount = 15;
+ char **flagsVector = SplitStringExt(mountFlags, ",", &flagCount, maxCount);
+
+ if (flagsVector == NULL || flagCount == 0) {
+ // No flags or something wrong in SplitStringExt,just return.
+ return 0;
+ }
+
+ for (int i = 0; i < flagCount; i++) {
+ char *p = flagsVector[i];
+ if (IsDefaultMountFlags(p)) {
+ flags |= ParseDefaultMountFlag(p);
+ } else {
+ if (strncat_s(fsSpecificData, fsSpecificDataSize - 1, p, strlen(p)) != EOK) {
+ printf("[fs_manager][warning], Failed to append mount flag \" %s \", ignore it\n", p);
+ continue;
+ }
+ if (i == flagCount - 1) { // last flags, do not need to append ','
+ break;
+ }
+ // Combined each mount flag with ','
+ if (strncat_s(fsSpecificData, fsSpecificDataSize - 1, ",", 1) != EOK) {
+ printf("[fs_manager][warning], Failed to append comma\n");
+ break; // If cannot add ',' to the end of flags, there is not reason to continue.
+ }
+ }
+ }
+
+ FreeStringVector(flagsVector, flagCount);
+ return flags;
+}
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
\ No newline at end of file
diff --git a/interfaces/innerkits/fs_manager/fstab_mount.c b/interfaces/innerkits/fs_manager/fstab_mount.c
new file mode 100755
index 0000000..7761d80
--- /dev/null
+++ b/interfaces/innerkits/fs_manager/fstab_mount.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "fs_manager/fs_manager.h"
+#include "init_log.h"
+#include "init_utils.h"
+#include "securec.h"
+
+#define FS_MANAGER_BUFFER_SIZE 512
+bool IsSupportedFilesystem(const char *fsType)
+{
+ static const char *supportedFilesystem[] = {"ext4", "f2fs", NULL};
+
+ bool supported = false;
+ int index = 0;
+ if (fsType != NULL) {
+ while (supportedFilesystem[index] != NULL) {
+ if (strcmp(supportedFilesystem[index++], fsType) == 0) {
+ supported = true;
+ break;
+ }
+ }
+ }
+ return supported;
+}
+
+static int ExecCommand(int argc, char **argv)
+{
+ if (argc == 0 || argv == NULL || argv[0] == NULL) {
+ return -1;
+ }
+ pid_t pid = fork();
+ if (pid < 0) {
+ INIT_LOGE("Fork new process to format failed: %d", errno);
+ return -1;
+ }
+ if (pid == 0) {
+ execv(argv[0], argv);
+ exit(-1);
+ }
+ int status;
+ waitpid(pid, &status, 0);
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ printf("Command %s failed with status %d", argv[0], WEXITSTATUS(status));
+ }
+ return WEXITSTATUS(status);
+}
+
+int DoFormat(const char *devPath, const char *fsType)
+{
+ if (devPath == NULL || fsType == NULL) {
+ return -1;
+ }
+
+ if (!IsSupportedFilesystem(fsType)) {
+ printf("[fs_manager][error] Do not support filesystem \" %s \"\n", fsType);
+ return -1;
+ }
+ int ret = 0;
+ #define BLOCK_SIZE_BUFFER (64)
+ char blockSizeBuffer[BLOCK_SIZE_BUFFER] = {0};
+ if (strcmp(fsType, "ext4") == 0) {
+ const unsigned int blockSize = 4096;
+ if (snprintf_s(blockSizeBuffer, BLOCK_SIZE_BUFFER, BLOCK_SIZE_BUFFER - 1, "%u", blockSize) == -1) {
+ printf("[fs_manager][error] Failed to build block size buffer\n");
+ return -1;
+ }
+ char *formatCmds[] = {
+ "/bin/mke2fs", "-F", "-t", (char *)fsType, "-b", blockSizeBuffer, (char *)devPath, NULL
+ };
+ int argc = ARRAY_LENGTH(formatCmds);
+ char **argv = (char **)formatCmds;
+ ret = ExecCommand(argc, argv);
+ } else if (strcmp(fsType, "f2fs") == 0) {
+ char *formatCmds[] = {
+ "/bin/make_f2fs", (char *)devPath, NULL
+ };
+ int argc = ARRAY_LENGTH(formatCmds);
+ char **argv = (char **)formatCmds;
+ ret = ExecCommand(argc, argv);
+ }
+ #undef BLOCK_SIZE_BUFFER
+ return ret;
+}
+
+MountStatus GetMountStatusForMountPoint(const char *mp)
+{
+ if (mp == NULL) {
+ return MOUNT_ERROR;
+ }
+ char buffer[FS_MANAGER_BUFFER_SIZE] = {0};
+ size_t n = 0;
+ const int expectedItems = 6;
+ int count = 0;
+ char **mountItems = NULL;
+ MountStatus status = MOUNT_ERROR;
+ bool found = false;
+
+ FILE *fp = fopen("/proc/mounts", "r");
+ if (fp == NULL) {
+ return status;
+ }
+ while (fgets(buffer, sizeof(buffer) - 1, fp) != NULL) {
+ n = strlen(buffer);
+ if (buffer[n - 1] == '\n') {
+ buffer[n - 1] = '\0';
+ }
+ mountItems = SplitStringExt(buffer, " ", &count, expectedItems);
+ if (mountItems != NULL && count == expectedItems) {
+ // Second item in /proc/mounts is mount point
+ if (strcmp(mountItems[1], mp) == 0) {
+ FreeStringVector(mountItems, count);
+ found = true;
+ break;
+ }
+ FreeStringVector(mountItems, count);
+ }
+ }
+ if (found == true) {
+ status = MOUNT_MOUNTED;
+ } else if (feof(fp) > 0) {
+ status = MOUNT_UMOUNTED;
+ }
+ fclose(fp);
+ fp = NULL;
+ return status;
+}
+
+static int Mount(const char *source, const char *target, const char *fsType,
+ unsigned long flags, const char *data)
+{
+ struct stat st = {};
+ int rc = -1;
+
+ if (source == NULL || target == NULL || fsType == NULL) {
+ printf("[fs_manager][error] Invalid argment for mount\n");
+ return -1;
+ }
+ if (stat(target, &st) != 0 && errno != ENOENT) {
+ printf("[fs_manager][error] Cannot get stat of \" %s \", err = %d\n", target, errno);
+ return -1;
+ }
+ if ((st.st_mode & S_IFMT) == S_IFLNK) { // link, delete it.
+ unlink(target);
+ }
+ if (mkdir(target, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) {
+ if (errno != EEXIST) {
+ printf("[fs_manager][error] Failed to create dir \" %s \", err = %d\n", target, errno);
+ return -1;
+ }
+ }
+ errno = 0;
+ while ((rc = mount(source, target, fsType, flags, data) != 0)) {
+ if (errno == EAGAIN) {
+ printf("[fs_manager][warning] Mount %s to %s failed. try again", source, target);
+ continue;
+ } else {
+ break;
+ }
+ }
+ return rc;
+}
+
+int MountOneItem(FstabItem *item)
+{
+ if (item == NULL) {
+ return -1;
+ }
+ unsigned long mountFlags;
+ char fsSpecificData[FS_MANAGER_BUFFER_SIZE] = {0};
+
+ mountFlags = GetMountFlags(item->mountOptions, fsSpecificData, sizeof(fsSpecificData));
+ if (!IsSupportedFilesystem(item->fsType)) {
+ printf("[fs_manager][error]Unsupported file system \" %s \"", item->fsType);
+ return -1;
+ }
+ if (FM_MANAGER_WAIT_ENABLED(item->fsManagerFlags)) {
+ WaitForFile(item->deviceName, WAIT_MAX_COUNT);
+ }
+ int rc = Mount(item->deviceName, item->mountPoint, item->fsType, mountFlags, fsSpecificData);
+ if (rc != 0) {
+ INIT_LOGE("Mount %s to %s failed %d", item->deviceName, item->mountPoint, errno);
+ } else {
+ INIT_LOGI("Mount %s to %s successful", item->deviceName, item->mountPoint);
+ }
+ return rc;
+}
+
+int CheckRequiredAndMount(FstabItem *item, bool required)
+{
+ int rc = -1;
+ if (item == NULL) {
+ return rc;
+ }
+ if (required) { // Mount partition during first startup.
+ if (FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) {
+ rc = MountOneItem(item);
+ }
+ } else { // Mount partition during second startup.
+ if (!FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) {
+ rc = MountOneItem(item);
+ }
+ }
+ return rc;
+}
+
+int MountAllWithFstabFile(const char *fstabFile, bool required)
+{
+ if (fstabFile == NULL || *fstabFile == '\0') {
+ return -1;
+ }
+ Fstab *fstab = NULL;
+ if ((fstab = ReadFstabFromFile(fstabFile, false)) == NULL) {
+ printf("[fs_manager][error] Read fstab file \" %s \" failed\n", fstabFile);
+ return -1;
+ }
+
+ FstabItem *item = NULL;
+ int rc = -1;
+ for (item = fstab->head; item != NULL; item = item->next) {
+ rc = CheckRequiredAndMount(item, required);
+ }
+ ReleaseFstab(fstab);
+ fstab = NULL;
+ return rc;
+}
+
+int UmountAllWithFstabFile(const char *fstabFile)
+{
+ if (fstabFile == NULL || *fstabFile == '\0') {
+ return -1;
+ }
+ Fstab *fstab = NULL;
+ if ((fstab = ReadFstabFromFile(fstabFile, false)) == NULL) {
+ printf("[fs_manager][error] Read fstab file \" %s \" failed\n", fstabFile);
+ return -1;;
+ }
+
+ FstabItem *item = NULL;
+ int rc = -1;
+ for (item = fstab->head; item != NULL; item = item->next) {
+ printf("[fs_manager][info]Umount %s\n", item->mountPoint);
+ MountStatus status = GetMountStatusForMountPoint(item->mountPoint);
+ if (status == MOUNT_ERROR) {
+ printf("[fs_manager][warning] Cannot get mount status of mount point \" %s \"\n", item->mountPoint);
+ continue; // Cannot get mount status, just ignore it and try next one.
+ } else if (status == MOUNT_UMOUNTED) {
+ printf("[fs_manager][info] Mount point \" %s \" already unmounted. device path: %s, fs type: %s\n",
+ item->mountPoint, item->deviceName, item->fsType);
+ continue;
+ } else {
+ rc = umount(item->mountPoint);
+ if (rc == -1) {
+ printf("[fs_manager][error] Umount %s failed, device path: %s, fs type: %s, err = %d",
+ item->mountPoint, item->deviceName, item->fsType, errno);
+ } else {
+ printf("[fs_manager][info] Umount %s successfully\n",
+ item->mountPoint);
+ }
+ }
+ }
+ ReleaseFstab(fstab);
+ fstab = NULL;
+ return rc;
+}
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
diff --git a/interfaces/innerkits/include/fs_manager/fs_manager.h b/interfaces/innerkits/include/fs_manager/fs_manager.h
new file mode 100755
index 0000000..59df574
--- /dev/null
+++ b/interfaces/innerkits/include/fs_manager/fs_manager.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef STARTUP_FS_MANAGER_H
+#define STARTUP_FS_MANAGER_H
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+#include
+
+/* Fs manager flags definition */
+#define FS_MANAGER_CHECK 0x00000001
+#define FS_MANAGER_WAIT 0x00000002
+#define FS_MANAGER_REQUIRED 0x00000004
+
+#define VALID_FS_MANAGER_FLAGS (FS_MANAGER_CHECK | FS_MANAGER_WAIT | FS_MANAGER_REQUIRED)
+#define FS_MANAGER_FLAGS_ENABLED(fsMgrFlags, flag) (((fsMgrFlags) & FS_MANAGER_##flag) != 0)
+
+#define FM_MANAGER_CHECK_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), CHECK)
+#define FM_MANAGER_WAIT_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), WAIT)
+#define FM_MANAGER_REQUIRED_ENABLED(fsMgrFlags) FS_MANAGER_FLAGS_ENABLED((fsMgrFlags), REQUIRED)
+
+typedef enum MountStatus {
+ MOUNT_ERROR = -1,
+ MOUNT_UMOUNTED = 0,
+ MOUNT_MOUNTED = 1,
+} MountStatus;
+
+typedef struct FstabItem {
+ char *deviceName; // Block device name
+ char *mountPoint; // Mount point
+ char *fsType; // File system type
+ char * mountOptions; // File system mount options. readonly, rw, remount etc.
+ unsigned int fsManagerFlags; // flags defined by fs manager.
+ struct FstabItem *next;
+} FstabItem;
+
+typedef struct {
+ struct FstabItem *head;
+} Fstab;
+
+void ReleaseFstab(Fstab *fstab);
+Fstab *ReadFstabFromFile(const char *file, bool procMounts);
+FstabItem *FindFstabItemForPath(Fstab fstab, const char *path);
+FstabItem* FindFstabItemForMountPoint(Fstab fstab, const char *mp);
+
+bool IsSupportedFilesystem(const char *fsType);
+int DoFormat(const char *devPath, const char *fsType);
+int MountOneItem(FstabItem *item);
+MountStatus GetMountStatusForMountPoint(const char *mp);
+int MountAllWithFstabFile(const char *file, bool required);
+int UmountAllWithFstabFile(const char *file);
+unsigned long GetMountFlags(char *mountFlags, char *fsSpecificFlags, size_t fsSpecificFlagSize);
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+
+#endif // STARTUP_FS_MANAGER_H
\ No newline at end of file
diff --git a/interfaces/innerkits/reboot/BUILD.gn b/interfaces/innerkits/reboot/BUILD.gn
old mode 100644
new mode 100755
diff --git a/interfaces/innerkits/reboot/init_reboot.c b/interfaces/innerkits/reboot/init_reboot.c
old mode 100644
new mode 100755
index bbbab36..6e6df19
--- a/interfaces/innerkits/reboot/init_reboot.c
+++ b/interfaces/innerkits/reboot/init_reboot.c
@@ -17,6 +17,7 @@
#include
#include
#include
+
#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;
diff --git a/interfaces/innerkits/socket/BUILD.gn b/interfaces/innerkits/socket/BUILD.gn
old mode 100644
new mode 100755
diff --git a/interfaces/innerkits/socket/init_socket.c b/interfaces/innerkits/socket/init_socket.c
index f71e120..ce28193 100755
--- a/interfaces/innerkits/socket/init_socket.c
+++ b/interfaces/innerkits/socket/init_socket.c
@@ -14,7 +14,6 @@
*/
#include "init_socket.h"
-
#include
#include
#include
diff --git a/interfaces/kits/init_sync.h b/interfaces/kits/init_sync.h
old mode 100644
new mode 100755
diff --git a/ohos.build b/ohos.build
index a8ef47b..84b89d8 100644
--- a/ohos.build
+++ b/ohos.build
@@ -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"
]
}
}
diff --git a/services/BUILD.gn b/services/BUILD.gn
old mode 100644
new mode 100755
index 2e3317e..4dc1be4
--- a/services/BUILD.gn
+++ b/services/BUILD.gn
@@ -10,6 +10,20 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+
+init_common_sources = [
+ "init/init_capability.c",
+ "init/init_common_cmds.c",
+ "init/init_config.c",
+ "init/init_common_service.c",
+ "init/init_service_manager.c",
+ "init/init_service_socket.c",
+ "init/main.c",
+ "log/init_log.c",
+ "utils/init_utils.c",
+ "utils/list.c",
+]
+
if (defined(ohos_lite)) {
# feature: init
executable("init_lite") {
@@ -19,27 +33,21 @@ if (defined(ohos_lite)) {
"OHOS_LITE",
]
sources = [
- "log/init_log.c",
- "src/init_adapter.c",
- "src/init_capability.c",
- "src/init_cmds.c",
- "src/init_import.c",
- "src/init_jobs.c",
- "src/init_read_cfg.c",
- "src/init_reboot.c",
- "src/init_service.c",
- "src/init_service_manager.c",
- "src/init_service_socket.c",
- "src/init_signal_handler.c",
- "src/main.c",
- "utils/init_utils.c",
+ "init/adapter/init_adapter.c",
+ "init/lite/init.c",
+ "init/lite/init_cmds.c",
+ "init/lite/init_jobs.c",
+ "init/lite/init_reboot.c",
+ "init/lite/init_service.c",
+ "init/lite/init_signal_handler.c",
]
+ sources += init_common_sources
+
include_dirs = [
"//base/startup/init_lite/services/include",
- "//base/startup/init_lite/services/param/include",
+ "//base/startup/init_lite/services/init/include",
"//base/startup/init_lite/services/log",
- "//base/startup/init_lite/services/utils",
"//third_party/cJSON",
"//third_party/bounds_checking_function/include",
"//base/startup/syspara_lite/interfaces/kits",
@@ -88,33 +96,34 @@ if (defined(ohos_lite)) {
ohos_executable("init") {
sources = [
- "src/device.c",
- "src/init_adapter.c",
- "src/init_capability.c",
- "src/init_cmds.c",
- "src/init_import.c",
- "src/init_jobs.c",
- "src/init_read_cfg.c",
- "src/init_reboot.c",
- "src/init_service.c",
- "src/init_service_manager.c",
- "src/init_service_socket.c",
- "src/init_signal_handler.c",
- "src/main.c",
+ "init/adapter/init_adapter.c",
+ "init/standard/device.c",
+ "init/standard/init.c",
+ "init/standard/init_cmds.c",
+ "init/standard/init_jobs.c",
+ "init/standard/init_reboot.c",
+ "init/standard/init_service.c",
+ "init/standard/init_signal_handler.c",
+ "init/standard/switch_root.c",
+ "init/standard/init_mount.c",
]
+
+ sources += init_common_sources
+
include_dirs = [
"//base/startup/init_lite/services/include/param",
"//base/startup/init_lite/services/include",
+ "//base/startup/init_lite/services/init/include",
"//base/startup/init_lite/services/log",
- "//base/startup/init_lite/services/utils",
+ "//base/startup/init_lite/interfaces/innerkits/include",
"//third_party/cJSON",
"//third_party/bounds_checking_function/include",
"//third_party/libuv/include",
]
deps = [
+ "//base/startup/init_lite/interfaces/innerkits/fs_manager:libfsmanager_static",
"//base/startup/init_lite/services/log:init_log",
"//base/startup/init_lite/services/param:param_service",
- "//base/startup/init_lite/services/utils:libinit_utils",
"//third_party/bounds_checking_function:libsec_static",
"//third_party/cJSON:cjson_static",
]
@@ -138,6 +147,7 @@ if (defined(ohos_lite)) {
":init_etc",
"//base/startup/init_lite/interfaces/innerkits/dynamic_service:dynamic_service",
"//base/startup/init_lite/interfaces/innerkits/socket:libsocket",
+ "//base/startup/init_lite/interfaces/innerkits/fs_manager:libfsmanager_shared",
"//base/startup/init_lite/services/cmds/reboot:reboot",
"//base/startup/init_lite/services/cmds/service_control:service_control",
"//base/startup/init_lite/services/param:param",
diff --git a/services/cmds/reboot/init_cmd_reboot.c b/services/cmds/reboot/init_cmd_reboot.c
old mode 100644
new mode 100755
index 39b4069..528a9d3
--- a/services/cmds/reboot/init_cmd_reboot.c
+++ b/services/cmds/reboot/init_cmd_reboot.c
@@ -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 {
diff --git a/services/cmds/service_control/service_control.c b/services/cmds/service_control/service_control.c
index c000c28..320e155 100755
--- a/services/cmds/service_control/service_control.c
+++ b/services/cmds/service_control/service_control.c
@@ -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) {
diff --git a/services/etc/init.cfg b/services/etc/init.cfg
index e0e54be..5e07aac 100755
--- a/services/etc/init.cfg
+++ b/services/etc/init.cfg
@@ -3,8 +3,7 @@
"/etc/init.usb.cfg",
"/etc/init.usb.configfs.cfg",
"/etc/init.usb.cfg",
- "/etc/init.Hi3516DV300.usb.cfg",
- "/etc/init.Hi3516DV300.cfg"
+ "/vendor/etc/init.${ohos.boot.hardware}.cfg"
],
"jobs" : [{
"name" : "pre-init",
@@ -16,10 +15,9 @@
"mkdir /dev/memcg/apps/ 0755 system system",
"mkdir /dev/memcg/system 0550 system system",
"start ueventd",
- "mkdir /vendor",
+ "start watchdog_service",
"mkdir /data",
- "mount ext4 /dev/block/platform/soc/10100000.himci.eMMC/by-name/vendor /vendor wait rdonly barrier=1",
- "mount ext4 /dev/block/platform/soc/10100000.himci.eMMC/by-name/userdata /data wait nosuid nodev noatime barrier=1,data=ordered,noauto_da_alloc"
+ "mount_fstab /vendor/etc/fstab.${ohos.boot.hardware}"
]
}, {
"name" : "init",
@@ -386,8 +384,8 @@
"write /proc/sys/kernel/perf_event_paranoid 3"
]
}, {
- "name" : "boot && param:ro.debuggable=1",
- "condition" : "boot && ro.debuggable=1",
+ "name" : "boot && param:const.debuggable=1",
+ "condition" : "boot && const.debuggable=1",
"cmds" : [
"chmod 0773 /data/misc/trace",
"chmod 0775 /data/misc/wmtrace",
@@ -406,6 +404,13 @@
"console" : 1,
"uid" : "root",
"gid" : ["shell", "log", "readproc"]
+ }, {
+ "name" : "watchdog_service",
+ "path" : ["/system/bin/watchdog_service", "10", "2"],
+ "disabled" : 1,
+ "uid" : "root",
+ "gid" : ["shell", "log", "readproc"]
}
+
]
}
diff --git a/services/etc/init.usb.cfg b/services/etc/init.usb.cfg
index dd282c0..10cf95f 100755
--- a/services/etc/init.usb.cfg
+++ b/services/etc/init.usb.cfg
@@ -1,4 +1,7 @@
{
+ "import" : [
+ "/vendor/etc/init.${ohos.boot.hardware}.usb.cfg"
+ ],
"jobs" : [{
"name" : "boot",
"cmds" : [
diff --git a/services/etc/param/ohos.para b/services/etc/param/ohos.para
index f53e55a..8c910ab 100755
--- a/services/etc/param/ohos.para
+++ b/services/etc/param/ohos.para
@@ -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
diff --git a/services/include/init_cmds.h b/services/include/init_cmds.h
deleted file mode 100644
index 343ec32..0000000
--- a/services/include/init_cmds.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BASE_STARTUP_INITLITE_CMDS_H
-#define BASE_STARTUP_INITLITE_CMDS_H
-
-#ifdef __cplusplus
-#if __cplusplus
-extern "C" {
-#endif
-#endif
-
-#define MAX_CMD_NAME_LEN 32
-#define MAX_CMD_CONTENT_LEN 256
-#define MAX_CMD_CNT_IN_ONE_JOB 200
-#define MAX_COPY_BUF_SIZE 256
-#define DEFAULT_COPY_ARGS_CNT 2
-
-#ifndef OHOS_LITE
-// Limit max length of parameter value to 96
-#define MAX_PARAM_VALUE_LEN 96
-// Limit max length of parameter name to 96
-#define MAX_PARAM_NAME_LEN 96
-#else
-// For lite ohos, do not support parameter operation
-#define MAX_PARAM_VALUE_LEN 0
-#define MAX_PARAM_NAME_LEN 0
-#endif
-
-// one cmd line
-typedef struct {
- char name[MAX_CMD_NAME_LEN + 1];
- char cmdContent[MAX_CMD_CONTENT_LEN + 1];
-} CmdLine;
-
-struct CmdArgs {
- int argc;
- char **argv;
-};
-
-int GetParamValue(const char *symValue, char *paramValue, unsigned int paramLen);
-struct CmdArgs* GetCmd(const char *cmdContent, const char *delim, int argsCount);
-void FreeCmd(struct CmdArgs *cmd);
-
-void ParseCmdLine(const char* cmdStr, CmdLine* resCmd);
-void DoCmd(const CmdLine* curCmd);
-
-void DoCmdByName(const char *name, const char *cmdContent);
-const char *GetMatchCmd(const char *cmdStr, unsigned int *index);
-const char *GetCmdKey(unsigned int index);
-
-#ifdef __cplusplus
-#if __cplusplus
-}
-#endif
-#endif
-
-#endif // BASE_STARTUP_INITLITE_CMDS_H
diff --git a/services/include/init_service.h b/services/include/init_service.h
deleted file mode 100644
index dc887a1..0000000
--- a/services/include/init_service.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BASE_STARTUP_INITLITE_SERVICE_H
-#define BASE_STARTUP_INITLITE_SERVICE_H
-
-#include
-#include "init_cmds.h"
-#include "init_service_socket.h"
-
-#ifdef __cplusplus
-#if __cplusplus
-extern "C" {
-#endif
-#endif
-
-// return value
-#define SERVICE_FAILURE (-1)
-#define SERVICE_SUCCESS 0
-
-// service attributes
-#define SERVICE_ATTR_INVALID 0x001 // option invalid
-#define SERVICE_ATTR_ONCE 0x002 // do not restart when it exits
-#define SERVICE_ATTR_NEED_RESTART 0x004 // will restart in the near future
-#define SERVICE_ATTR_NEED_STOP 0x008 // will stop in reap
-#define SERVICE_ATTR_IMPORTANT 0x010 // will reboot if it crash
-#define SERVICE_ATTR_CRITICAL 0x020 // critical, will reboot if it crash 4 times in 4 minutes
-#define SERVICE_ATTR_DISABLED 0x040 // disabled
-#define SERVICE_ATTR_CONSOLE 0x080 // console
-#define SERVICE_ATTR_DYNAMIC 0x100 // dynamic service
-
-#define MAX_SERVICE_NAME 32
-#define MAX_WRITEPID_FILES 100
-
-#define CAP_NUM 2
-
-#define SERVICES_ARR_NAME_IN_JSON "services"
-
-typedef struct {
- uid_t uID;
- gid_t *gIDArray;
- int gIDCnt;
- unsigned int *caps;
- unsigned int capsCnt;
-} Perms;
-
-struct OnRestartCmd {
- CmdLine *cmdLine;
- int cmdNum;
-};
-
-typedef struct {
- char name[MAX_SERVICE_NAME + 1];
- char** pathArgs;
- int pathArgsCnt;
- int pid;
- int crashCnt;
- time_t firstCrashTime;
- char *writepidFiles[MAX_WRITEPID_FILES];
- unsigned int attribute;
- int importance;
- Perms servPerm;
- struct OnRestartCmd *onRestart;
- struct ServiceSocket *socketCfg;
-} Service;
-
-int ServiceStart(Service *service);
-int ServiceStop(Service *service);
-void ServiceReap(Service *service);
-
-#ifdef __cplusplus
-#if __cplusplus
-}
-#endif
-#endif
-
-#endif // BASE_STARTUP_INITLITE_SERVICE_H
diff --git a/services/utils/init_utils.h b/services/include/init_utils.h
similarity index 72%
rename from services/utils/init_utils.h
rename to services/include/init_utils.h
index d7d39f2..52d460a 100755
--- a/services/utils/init_utils.h
+++ b/services/include/init_utils.h
@@ -28,18 +28,23 @@ extern "C" {
#define BINARY_BASE 2
#define OCTAL_BASE 8
#define DECIMAL_BASE 10
+#define WAIT_MAX_COUNT 10
#define ARRAY_LENGTH(array) (sizeof((array)) / sizeof((array)[0]))
uid_t DecodeUid(const char *name);
char *ReadFileToBuf(const char *configFile);
-int SplitString(char *srcPtr, char **dstPtr, int maxNum);
+int SplitString(char *srcPtr, const char *del, char **dstPtr, int maxNum);
void WaitForFile(const char *source, unsigned int maxCount);
size_t WriteAll(int fd, const char *buffer, size_t size);
-char *Realpath(const char *source, char *resolvedPath, size_t resolvedPathSize);
+char *GetRealPath(const char *source);
int StringToInt(const char *str, int defaultValue);
int MakeDirRecursive(const char *dir, mode_t mode);
int MakeDir(const char *dir, mode_t mode);
-
+int ReadFileInDir(const char *dirPath, const char *includeExt,
+ int (*processFile)(const char *fileName, void *context), void *context);
+char **SplitStringExt(char *buffer, const char *del, int *returnCount, int maxItemCount);
+void FreeStringVector(char **vector, int count);
+int InUpdaterMode(void);
#ifdef __cplusplus
#if __cplusplus
}
diff --git a/services/include/param/init_param.h b/services/include/param/init_param.h
old mode 100644
new mode 100755
index 3ef4dab..5d9eb45
--- a/services/include/param/init_param.h
+++ b/services/include/param/init_param.h
@@ -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
diff --git a/services/include/param/sys_param.h b/services/include/param/sys_param.h
old mode 100644
new mode 100755
diff --git a/services/include/init_capability.h b/services/include/switch_root.h
old mode 100644
new mode 100755
similarity index 78%
rename from services/include/init_capability.h
rename to services/include/switch_root.h
index 842959e..833edbb
--- a/services/include/init_capability.h
+++ b/services/include/switch_root.h
@@ -13,13 +13,7 @@
* limitations under the License.
*/
-#ifndef INIT_CAPABILITY_H
-#define INIT_CAPABILITY_H
-
-#include "cJSON.h"
-#include "init_service.h"
-
-int GetServiceCaps(const cJSON* curArrItem, Service* curServ);
-
-#endif
-
+ #ifndef INIT_SWITCH_ROOT_H
+ #define INIT_SWITCH_ROOT_H
+ int SwitchRoot(const char *newRoot);
+ #endif // INIT_SWITCH_ROOT_H
\ No newline at end of file
diff --git a/services/src/init_adapter.c b/services/init/adapter/init_adapter.c
old mode 100644
new mode 100755
similarity index 72%
rename from services/src/init_adapter.c
rename to services/init/adapter/init_adapter.c
index 2788e64..0cd8eb7
--- a/services/src/init_adapter.c
+++ b/services/init/adapter/init_adapter.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -12,23 +12,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#include "init_adapter.h"
#include
+#include
#include
-#include
#include
#include
+#include
+#if defined OHOS_LITE && !defined __LINUX__
+#include
+#else
+#include
+#endif
+
#if ((defined __LINUX__) || (!defined OHOS_LITE))
#include
#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
}
-
diff --git a/services/include/device.h b/services/init/include/device.h
old mode 100644
new mode 100755
similarity index 95%
rename from services/include/device.h
rename to services/init/include/device.h
index c68d456..043b2f1
--- a/services/include/device.h
+++ b/services/init/include/device.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -12,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
#ifdef __cplusplus
diff --git a/services/include/init_signal_handler.h b/services/init/include/init.h
old mode 100644
new mode 100755
similarity index 51%
rename from services/include/init_signal_handler.h
rename to services/init/include/init.h
index 433d4f9..966c4d6
--- a/services/include/init_signal_handler.h
+++ b/services/init/include/init.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -12,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
-#include
-#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
diff --git a/services/include/init_adapter.h b/services/init/include/init_adapter.h
old mode 100644
new mode 100755
similarity index 65%
rename from services/include/init_adapter.h
rename to services/init/include/init_adapter.h
index ea02c1e..36f91de
--- a/services/include/init_adapter.h
+++ b/services/init/include/init_adapter.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -12,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
-#else
-#include
-#endif
-
+#include
#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
diff --git a/services/init/include/init_cmds.h b/services/init/include/init_cmds.h
new file mode 100755
index 0000000..a616673
--- /dev/null
+++ b/services/init/include/init_cmds.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef BASE_STARTUP_INIT_CMDS_H
+#define BASE_STARTUP_INIT_CMDS_H
+#include
+#include
+#include
+#include
+#include "cJSON.h"
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+#define DEFAULT_DIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH) // mkdir, default mode
+#define SPACES_CNT_IN_CMD_MAX 10 // mount, max number of spaces in cmdline
+#define SPACES_CNT_IN_CMD_MIN 2 // mount, min number of spaces in cmdline
+
+#define LOADCFG_BUF_SIZE 128 // loadcfg, max buffer for one cmdline
+#define LOADCFG_MAX_FILE_LEN 51200 // loadcfg, max file size is 50K
+#define LOADCFG_MAX_LOOP 20 // loadcfg, to prevent to be trapped in infite loop
+#define OCTAL_TYPE 8 // 8 means octal to decimal
+#define MAX_BUFFER 256UL
+#define AUTHORITY_MAX_SIZE 128
+
+#define MAX_CMD_NAME_LEN 32
+#define MAX_CMD_CONTENT_LEN 256
+#define MAX_CMD_CNT_IN_ONE_JOB 200
+#define MAX_COPY_BUF_SIZE 256
+#define DEFAULT_COPY_ARGS_CNT 2
+
+#define OPTIONS_SIZE 128
+
+#define SUPPORT_MAX_ARG_FOR_EXEC 10
+// one cmd line
+typedef struct {
+ int cmdIndex;
+ char cmdContent[MAX_CMD_CONTENT_LEN + 1];
+} CmdLine;
+
+typedef struct {
+ int cmdNum;
+ CmdLine cmds[0];
+} CmdLines;
+
+struct CmdArgs {
+ int argc;
+ char *argv[0];
+};
+
+struct CmdTable {
+ char name[MAX_CMD_NAME_LEN];
+ unsigned char minArg;
+ unsigned char maxArg;
+ void (*DoFuncion)(const struct CmdArgs *ctx, const char *cmdContent);
+};
+
+int GetParamValue(const char *symValue, unsigned int symLen, char *paramValue, unsigned int paramLen);
+const struct CmdArgs *GetCmdArg(const char *cmdContent, const char *delim, int argsCount);
+void FreeCmdArg(struct CmdArgs *cmd);
+void DoCmdByName(const char *name, const char *cmdContent);
+void DoCmdByIndex(int index, const char *cmdContent);
+const char *GetMatchCmd(const char *cmdStr, int *index);
+const char *GetCmdKey(int index);
+const struct CmdTable *GetCmdTable(int *number);
+int GetCmdLinesFromJson(const cJSON *root, CmdLines **cmdLines);
+const struct CmdTable *GetCmdByName(const char *name);
+void ExecReboot(const char *value);
+char *BuildStringFromCmdArg(const struct CmdArgs *ctx, int startIndex);
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+
+#endif // BASE_STARTUP_INITLITE_CMDS_H
diff --git a/services/include/init_jobs.h b/services/init/include/init_jobs.h
old mode 100644
new mode 100755
similarity index 74%
rename from services/include/init_jobs.h
rename to services/init/include/init_jobs.h
index 47937a7..e74cb25
--- a/services/include/init_jobs.h
+++ b/services/init/include/init_jobs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -12,12 +12,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#ifndef BASE_STARTUP_INITLITE_JOBS_H
#define BASE_STARTUP_INITLITE_JOBS_H
-
-#include "init_cmds.h"
#include "cJSON.h"
+#include "init_cmds.h"
#ifdef __cplusplus
#if __cplusplus
@@ -30,14 +28,20 @@ extern "C" {
// one job, could have many cmd lines
typedef struct {
char name[MAX_JOB_NAME_LEN + 1];
- int cmdLinesCnt;
- CmdLine* cmdLines;
+ CmdLines *cmdLines;
} Job;
-void ParseAllJobs(const cJSON* fileRoot);
-void DoJob(const char* jobName);
+void ParseAllJobs(const cJSON *fileRoot);
+void DoJob(const char *jobName);
void ReleaseAllJobs(void);
void DumpAllJobs(void);
+
+#define INIT_CONFIGURATION_FILE "/etc/init.cfg"
+#define OTHER_CFG_PATH "/system/etc/init"
+#define MAX_PATH_ARGS_CNT 20
+
+void ReadConfig(void);
+
#ifdef __cplusplus
#if __cplusplus
}
diff --git a/services/init/include/init_service.h b/services/init/include/init_service.h
new file mode 100755
index 0000000..87713e1
--- /dev/null
+++ b/services/init/include/init_service.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef BASE_STARTUP_INITLITE_SERVICE_H
+#define BASE_STARTUP_INITLITE_SERVICE_H
+#include
+
+#include "cJSON.h"
+#include "init_cmds.h"
+#include "init_service_socket.h"
+#include "list.h"
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif
+
+// return value
+#define SERVICE_FAILURE (-1)
+#define SERVICE_SUCCESS 0
+
+// service attributes
+#define SERVICE_ATTR_INVALID 0x001 // option invalid
+#define SERVICE_ATTR_ONCE 0x002 // do not restart when it exits
+#define SERVICE_ATTR_NEED_RESTART 0x004 // will restart in the near future
+#define SERVICE_ATTR_NEED_STOP 0x008 // will stop in reap
+#define SERVICE_ATTR_IMPORTANT 0x010 // will reboot if it crash
+#define SERVICE_ATTR_CRITICAL 0x020 // critical, will reboot if it crash 4 times in 4 minutes
+#define SERVICE_ATTR_DISABLED 0x040 // disabled
+#define SERVICE_ATTR_CONSOLE 0x080 // console
+#define SERVICE_ATTR_DYNAMIC 0x100 // dynamic service
+
+#define MAX_SERVICE_NAME 32
+#define MAX_WRITEPID_FILES 100
+
+#define FULL_CAP 0xFFFFFFFF
+// init
+#define DEFAULT_UMASK_INIT 022
+
+#define CAP_NUM 2
+
+#define SERVICES_ARR_NAME_IN_JSON "services"
+
+typedef struct {
+ uid_t uID;
+ gid_t *gIDArray;
+ int gIDCnt;
+ unsigned int *caps;
+ unsigned int capsCnt;
+} Perms;
+
+typedef struct {
+ int count;
+ char **argv;
+} ServiceArgs;
+
+typedef struct {
+ ListNode node;
+ char name[MAX_SERVICE_NAME + 1];
+ int pid;
+ int crashCnt;
+ time_t firstCrashTime;
+ unsigned int attribute;
+ int importance;
+ Perms servPerm;
+ ServiceArgs pathArgs;
+ ServiceArgs writePidArgs;
+ CmdLines *restartArg;
+ ServiceSocket *socketCfg;
+} Service;
+
+int ServiceStart(Service *service);
+int ServiceStop(Service *service);
+void ServiceReap(Service *service);
+void ReapService(Service *service);
+
+void NotifyServiceChange(const char *serviceName, const char *change);
+int IsForbidden(const char *fieldStr);
+int SetImportantValue(Service *curServ, const char *attrName, int value, int flag);
+int GetServiceCaps(const cJSON *curArrItem, Service *curServ);
+int ServiceExec(const Service *service);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+
+#endif // BASE_STARTUP_INITLITE_SERVICE_H
diff --git a/services/include/init_service_manager.h b/services/init/include/init_service_manager.h
old mode 100644
new mode 100755
similarity index 57%
rename from services/include/init_service_manager.h
rename to services/init/include/init_service_manager.h
index 1208307..45c91d8
--- a/services/include/init_service_manager.h
+++ b/services/init/include/init_service_manager.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -12,12 +12,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#ifndef BASE_STARTUP_INITLITE_SERVICEMANAGER_H
#define BASE_STARTUP_INITLITE_SERVICEMANAGER_H
#include "init_service.h"
#include "cJSON.h"
+#include "list.h"
#ifdef __cplusplus
#if __cplusplus
@@ -25,26 +25,37 @@ extern "C" {
#endif
#endif
-#define UID_STR_IN_CFG "uid"
-#define GID_STR_IN_CFG "gid"
-#define ONCE_STR_IN_CFG "once"
-#define IMPORTANT_STR_IN_CFG "importance"
-#define BIN_SH_NOT_ALLOWED "/bin/sh"
-#define CRITICAL_STR_IN_CFG "critical"
-#define DISABLED_STR_IN_CFG "disabled"
-#define CONSOLE_STR_IN_CFG "console"
+#define UID_STR_IN_CFG "uid"
+#define GID_STR_IN_CFG "gid"
+#define ONCE_STR_IN_CFG "once"
+#define IMPORTANT_STR_IN_CFG "importance"
+#define BIN_SH_NOT_ALLOWED "/bin/sh"
+#define CRITICAL_STR_IN_CFG "critical"
+#define DISABLED_STR_IN_CFG "disabled"
+#define CONSOLE_STR_IN_CFG "console"
#define MAX_SERVICES_CNT_IN_FILE 100
-void RegisterServices(Service *services, int servicesCnt);
+typedef struct {
+ char *capStr;
+ unsigned int CapNum;
+} CapStrCapNum;
+
+typedef struct {
+ ListNode services;
+ int serviceCount;
+} ServiceSpace;
+
+Service *GetServiceByPid(pid_t pid);
+Service *GetServiceByName(const char *servName);
+cJSON *GetArrayItem(const cJSON *fileRoot, int *arrSize, const char *arrName);
+
void StartServiceByName(const char *serviceName, bool checkDynamic);
void StopServiceByName(const char *serviceName);
-void StopAllServices(void);
-void StopAllServicesBeforeReboot(void);
-void ReapServiceByPID(int pid);
+void StopAllServices(int flags);
void ParseAllServices(const cJSON *fileRoot);
#ifdef OHOS_SERVICE_DUMP
-void DumpAllServices(void);
+void DumpAllServices();
#endif
#ifdef __cplusplus
#if __cplusplus
diff --git a/services/include/init_service_socket.h b/services/init/include/init_service_socket.h
old mode 100644
new mode 100755
similarity index 57%
rename from services/include/init_service_socket.h
rename to services/init/include/init_service_socket.h
index 6ff5ed5..0b216c4
--- a/services/include/init_service_socket.h
+++ b/services/init/include/init_service_socket.h
@@ -1,10 +1,10 @@
/*
- * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -12,17 +12,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#ifndef INIT_SERVICE_SOCKET_
#define INIT_SERVICE_SOCKET_
#include
-#include
#include
+#include
#include
#include
+#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
diff --git a/services/init/init_capability.c b/services/init/init_capability.c
new file mode 100755
index 0000000..48d1806
--- /dev/null
+++ b/services/init/init_capability.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include
+#include
+#include
+#include
+#include
+#if defined OHOS_LITE && !defined __LINUX__
+#include
+#else
+#include
+#endif
+#include
+#include
+
+#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;
+}
diff --git a/services/init/init_common_cmds.c b/services/init/init_common_cmds.c
new file mode 100755
index 0000000..90a7721
--- /dev/null
+++ b/services/init/init_common_cmds.c
@@ -0,0 +1,731 @@
+/*
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "init_cmds.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "init.h"
+#include "init_jobs.h"
+#include "init_log.h"
+#include "init_service_manager.h"
+#include "init_utils.h"
+#include "securec.h"
+
+static char *AddOneArg(const char *param, size_t paramLen)
+{
+ int valueCount = 1;
+ char *begin = strchr(param, '$');
+ while (begin != NULL) {
+ valueCount++;
+ begin = strchr(begin + 1, '$');
+ }
+ size_t allocSize = paramLen + (PARAM_VALUE_LEN_MAX * valueCount) + 1;
+ char *arg = calloc(sizeof(char), allocSize);
+ INIT_CHECK(arg != NULL, return NULL);
+ int ret = GetParamValue(param, paramLen, arg, allocSize);
+ INIT_ERROR_CHECK(ret == 0, free(arg);
+ return NULL, "Failed to get value for %s", param);
+ return arg;
+}
+
+char *BuildStringFromCmdArg(const struct CmdArgs *ctx, int startIndex)
+{
+ char *options = (char *)calloc(1, OPTIONS_SIZE + 1);
+ INIT_ERROR_CHECK(options != NULL, return NULL, "Failed to get memory ");
+ options[0] = '\0';
+ int curr = 0;
+ for (int i = startIndex; i < ctx->argc; i++) { // save opt
+ if (ctx->argv[i] == NULL) {
+ continue;
+ }
+ int len = snprintf_s(options + curr, OPTIONS_SIZE - curr, OPTIONS_SIZE - 1 - curr, "%s ", ctx->argv[i]);
+ if (len <= 0) {
+ INIT_LOGE("Failed to format other opt");
+ options[0] = '\0';
+ return options;
+ }
+ curr += len;
+ }
+ if ((curr > 0) && (curr < OPTIONS_SIZE)) {
+ options[curr - 1] = '\0';
+ }
+ return options;
+}
+
+const struct CmdArgs *GetCmdArg(const char *cmdContent, const char *delim, int argsCount)
+{
+ INIT_CHECK_RETURN_VALUE(cmdContent != NULL, NULL);
+ if (argsCount > SPACES_CNT_IN_CMD_MAX) {
+ INIT_LOGW("Too much arguments for command, max number is %d", SPACES_CNT_IN_CMD_MAX);
+ argsCount = SPACES_CNT_IN_CMD_MAX;
+ }
+ struct CmdArgs *ctx = (struct CmdArgs *)calloc(1, sizeof(struct CmdArgs) + sizeof(char *) * (argsCount + 1));
+ INIT_ERROR_CHECK(ctx != NULL, return NULL, "Failed to malloc memory for arg");
+ ctx->argc = 0;
+ char *p = (char *)cmdContent;
+ char *end = (char *)cmdContent + strlen(cmdContent);
+ char *token = NULL;
+ do {
+ // Skip lead whitespaces
+ while (isspace(*p)) {
+ p++;
+ }
+ token = strstr(p, delim);
+ if (token == NULL) {
+ ctx->argv[ctx->argc] = AddOneArg(p, end - p);
+ INIT_CHECK(ctx->argv[ctx->argc] != NULL, FreeCmdArg(ctx);
+ return NULL);
+ } else {
+ ctx->argv[ctx->argc] = AddOneArg(p, token - p);
+ INIT_CHECK(ctx->argv[ctx->argc] != NULL, FreeCmdArg(ctx);
+ return NULL);
+ }
+ ctx->argc++;
+ ctx->argv[ctx->argc] = NULL;
+ if (ctx->argc == argsCount) {
+ break;
+ }
+ p = token;
+ } while (token != NULL);
+ return ctx;
+}
+
+void FreeCmdArg(struct CmdArgs *cmd)
+{
+ INIT_CHECK_ONLY_RETURN(cmd != NULL);
+ for (int i = 0; i < cmd->argc; ++i) {
+ if (cmd->argv[i] != NULL) {
+ free(cmd->argv[i]);
+ }
+ }
+ free(cmd);
+ return;
+}
+
+static void ExecCmd(const struct CmdTable *cmd, const char *cmdContent)
+{
+ if (cmd == NULL) {
+ INIT_LOGE("Invalid cmd for %s", cmdContent);
+ return;
+ }
+
+ const struct CmdArgs *ctx = GetCmdArg(cmdContent, " ", cmd->maxArg);
+ if (ctx == NULL) {
+ INIT_LOGE("Invalid arguments cmd: %s content: %s", cmd->name, cmdContent);
+ } else if ((ctx->argc <= cmd->maxArg) && (ctx->argc >= cmd->minArg)) {
+ cmd->DoFuncion(ctx, cmdContent);
+ } else {
+ INIT_LOGE("Invalid arguments cmd: %s content: %s argc: %d %d", cmd->name, cmdContent, ctx->argc, cmd->maxArg);
+ }
+ FreeCmdArg((struct CmdArgs *)ctx);
+}
+
+static void SetProcName(const struct CmdArgs *ctx, const char *procFile)
+{
+ int fd = open(procFile, O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, S_IRUSR | S_IWUSR);
+ INIT_ERROR_CHECK(fd >= 0, return, "Failed to set %s errno: %d", procFile, errno);
+
+ size_t size = strlen(ctx->argv[0]);
+ ssize_t n = write(fd, ctx->argv[0], size);
+ INIT_ERROR_CHECK(n == (ssize_t)size, close(fd);
+ return, "Failed to write domainname errno: %d", errno);
+ close(fd);
+}
+
+static void DoSetDomainname(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ SetProcName(ctx, "/proc/sys/kernel/domainname");
+}
+
+static void DoSetHostname(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ SetProcName(ctx, "/proc/sys/kernel/hostname");
+}
+
+static void DoSleep(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ errno = 0;
+ unsigned long sleepTime = strtoul(ctx->argv[0], NULL, DECIMAL_BASE);
+ if (errno != 0) {
+ INIT_LOGE("cannot covert sleep time in command \" sleep \"");
+ return;
+ }
+
+ // Limit sleep time in 5 seconds
+ const unsigned long sleepTimeLimit = 5;
+ if (sleepTime > sleepTimeLimit) {
+ sleepTime = sleepTimeLimit;
+ }
+ INIT_LOGI("Sleeping %d second(s)", sleepTime);
+ sleep((unsigned int)sleepTime);
+}
+
+static void DoStart(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(ctx);
+ INIT_LOGD("DoStart %s", cmdContent);
+ StartServiceByName(cmdContent, true);
+}
+
+static void DoStop(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(ctx);
+ INIT_LOGD("DoStop %s", cmdContent);
+ StopServiceByName(cmdContent);
+ return;
+}
+
+static void DoReset(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(ctx);
+ INIT_LOGD("DoReset %s", cmdContent);
+ DoStop(ctx, cmdContent);
+ DoStart(ctx, cmdContent);
+}
+
+static void DoCopy(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ int srcFd = -1;
+ int dstFd = -1;
+ char buf[MAX_COPY_BUF_SIZE] = { 0 };
+ char *realPath1 = NULL;
+ char *realPath2 = NULL;
+ if (ctx == NULL || ctx->argc != DEFAULT_COPY_ARGS_CNT) {
+ INIT_LOGE("DoCopy invalid arguments :%s", cmdContent);
+ return;
+ }
+ do {
+ realPath1 = GetRealPath(ctx->argv[0]);
+ if (realPath1 == NULL) {
+ INIT_LOGE("Failed to get real path %s", ctx->argv[0]);
+ break;
+ }
+ srcFd = open(realPath1, O_RDONLY);
+ if (srcFd < 0) {
+ INIT_LOGE("Failed to open source path %s %d", ctx->argv[0], errno);
+ break;
+ }
+ struct stat fileStat = { 0 };
+ if (stat(ctx->argv[0], &fileStat) != 0) {
+ INIT_LOGE("Failed to state source path %s %d", ctx->argv[0], errno);
+ break;
+ }
+ mode_t mode = fileStat.st_mode;
+ realPath2 = GetRealPath(ctx->argv[1]);
+ if (realPath2 != NULL) {
+ dstFd = open(realPath2, O_WRONLY | O_TRUNC | O_CREAT, mode);
+ } else {
+ dstFd = open(ctx->argv[1], O_WRONLY | O_TRUNC | O_CREAT, mode);
+ }
+ if (srcFd < 0) {
+ INIT_LOGE("Failed to open dest path %s %d", ctx->argv[1], errno);
+ break;
+ }
+ int rdLen = 0;
+ while ((rdLen = read(srcFd, buf, sizeof(buf) - 1)) > 0) {
+ int rtLen = write(dstFd, buf, rdLen);
+ if (rtLen != rdLen) {
+ INIT_LOGE("Failed to write to dest path %s %d", ctx->argv[1], errno);
+ break;
+ }
+ }
+ fsync(dstFd);
+ } while (0);
+ INIT_CHECK(srcFd < 0, close(srcFd));
+ INIT_CHECK(dstFd < 0, close(dstFd));
+ INIT_CHECK(realPath1 == NULL, free(realPath1));
+ INIT_CHECK(realPath2 == NULL, free(realPath2));
+}
+
+static int SetOwner(const char *file, const char *ownerStr, const char *groupStr)
+{
+ INIT_ERROR_CHECK(file != NULL, return -1, "SetOwner invalid file.");
+ INIT_ERROR_CHECK(ownerStr != NULL, return -1, "SetOwner invalid file.");
+ INIT_ERROR_CHECK(groupStr != NULL, return -1, "SetOwner invalid file.");
+
+ uid_t owner = DecodeUid(ownerStr);
+ INIT_ERROR_CHECK(owner != (uid_t)-1, return -1, "SetOwner invalid uid :%s.", ownerStr);
+ gid_t group = DecodeUid(groupStr);
+ INIT_ERROR_CHECK(group != (gid_t)-1, return -1, "SetOwner invalid gid :%s.", groupStr);
+ return (chown(file, owner, group) != 0) ? -1 : 0;
+}
+
+static void DoChown(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ // format: chown owner group /xxx/xxx/xxx
+ const int pathPos = 2;
+ int ret = SetOwner(ctx->argv[pathPos], ctx->argv[0], ctx->argv[1]);
+ if (ret != 0) {
+ INIT_LOGE("Failed to change owner %s, err %d.", cmdContent, errno);
+ }
+ return;
+}
+
+static void DoMkDir(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ // mkdir support format:
+ // 1.mkdir path
+ // 2.mkdir path mode
+ // 3.mkdir path mode owner group
+ UNUSED(cmdContent);
+ const int ownerPos = 2;
+ const int groupPos = 3;
+ if (ctx->argc != 1 && ctx->argc != (groupPos + 1) && ctx->argc != ownerPos) {
+ INIT_LOGE("DoMkDir invalid arguments: %s", cmdContent);
+ return;
+ }
+ mode_t mode = DEFAULT_DIR_MODE;
+ if (mkdir(ctx->argv[0], mode) != 0 && errno != EEXIST) {
+ INIT_LOGE("DoMkDir, failed for '%s', err %d.", ctx->argv[0], errno);
+ return;
+ }
+ if (ctx->argc <= 1) {
+ return;
+ }
+
+ mode = strtoul(ctx->argv[1], NULL, OCTAL_TYPE);
+ if (chmod(ctx->argv[0], mode) != 0) {
+ INIT_LOGE("DoMkDir failed for '%s', err %d.", ctx->argv[0], errno);
+ }
+ if (ctx->argc <= ownerPos) {
+ return;
+ }
+ int ret = SetOwner(ctx->argv[0], ctx->argv[ownerPos], ctx->argv[groupPos]);
+ if (ret != 0) {
+ INIT_LOGE("Failed to change owner %s, err %d.", cmdContent, errno);
+ }
+ return;
+}
+
+static void DoChmod(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ // format: chmod xxxx /xxx/xxx/xxx
+ mode_t mode = strtoul(ctx->argv[0], NULL, OCTAL_TYPE);
+ if (mode == 0) {
+ INIT_LOGE("DoChmod, strtoul failed for %s, er %d.", cmdContent, errno);
+ return;
+ }
+
+ if (chmod(ctx->argv[1], mode) != 0) {
+ INIT_LOGE("Failed to change mode \" %s \" mode to %04o, err = %d", ctx->argv[1], mode, errno);
+ }
+}
+
+static int GetMountFlag(unsigned long *mountflag, const char *targetStr, const char *source)
+{
+ if (targetStr == NULL || mountflag == NULL) {
+ return 0;
+ }
+ struct {
+ char *flagName;
+ int value;
+ } mountFlagMap[] = {
+ { "noatime", MS_NOATIME },
+ { "noexec", MS_NOEXEC },
+ { "nosuid", MS_NOSUID },
+ { "nodev", MS_NODEV },
+ { "nodiratime", MS_NODIRATIME },
+ { "ro", MS_RDONLY },
+ { "rdonly", MS_RDONLY },
+ { "rw", 0 },
+ { "sync", MS_SYNCHRONOUS },
+ { "remount", MS_REMOUNT },
+ { "bind", MS_BIND },
+ { "rec", MS_REC },
+ { "unbindable", MS_UNBINDABLE },
+ { "private", MS_PRIVATE },
+ { "slave", MS_SLAVE },
+ { "shared", MS_SHARED },
+ { "defaults", 0 },
+ };
+ for (unsigned int i = 0; i < ARRAY_LENGTH(mountFlagMap); i++) {
+ if (strncmp(targetStr, mountFlagMap[i].flagName, strlen(mountFlagMap[i].flagName)) == 0) {
+ *mountflag |= mountFlagMap[i].value;
+ return 1;
+ }
+ }
+ if (strncmp(targetStr, "wait", strlen("wait")) == 0) {
+ WaitForFile(source, WAIT_MAX_COUNT);
+ return 1;
+ }
+ return 0;
+}
+
+static void DoMount(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(ctx);
+ INIT_ERROR_CHECK(ctx->argc <= SPACES_CNT_IN_CMD_MAX, return, "Invalid arg number");
+ // format: fileSystemType source target mountFlag1 mountFlag2... data
+ int index = 0;
+ char *fileSysType = (ctx->argc > index) ? ctx->argv[index] : NULL;
+ INIT_ERROR_CHECK(fileSysType != NULL, return, "Failed to get fileSysType %s", cmdContent);
+ index++;
+
+ char *source = (ctx->argc > index) ? ctx->argv[index] : NULL;
+ INIT_ERROR_CHECK(source != NULL, return, "Failed to get source %s", cmdContent);
+ index++;
+
+ // maybe only has "filesystype source target", 2 spaces
+ char *target = (ctx->argc > index) ? ctx->argv[index] : NULL;
+ INIT_ERROR_CHECK(target != NULL, return, "Failed to get target %s", cmdContent);
+ ++index;
+
+ int ret = 0;
+ unsigned long mountflags = 0;
+ while (index < ctx->argc) {
+ ret = GetMountFlag(&mountflags, ctx->argv[index], source);
+ if (ret == 0) {
+ break;
+ }
+ index++;
+ }
+ if (index >= ctx->argc) {
+ ret = mount(source, target, fileSysType, mountflags, NULL);
+ } else {
+ char *data = BuildStringFromCmdArg(ctx, index);
+ INIT_ERROR_CHECK(data != NULL, return, "Failed to get data %s", cmdContent);
+ ret = mount(source, target, fileSysType, mountflags, data);
+ free(data);
+ }
+ if (ret != 0) {
+ INIT_LOGE("Failed to mount %s, err %d.", cmdContent, errno);
+ }
+}
+
+static bool CheckValidCfg(const char *path)
+{
+ static const char *supportCfg[] = {
+ "/etc/patch.cfg",
+ "/patch/fstab.cfg",
+ };
+ INIT_ERROR_CHECK(path != NULL, return false, "Invalid path for cfg");
+ struct stat fileStat = { 0 };
+ if (stat(path, &fileStat) != 0 || fileStat.st_size <= 0 || fileStat.st_size > LOADCFG_MAX_FILE_LEN) {
+ return false;
+ }
+ size_t cfgCnt = ARRAY_LENGTH(supportCfg);
+ for (size_t i = 0; i < cfgCnt; ++i) {
+ if (strcmp(path, supportCfg[i]) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void DoLoadCfg(const struct CmdArgs *ctx, const char *path)
+{
+ UNUSED(ctx);
+ char buf[LOADCFG_BUF_SIZE] = { 0 };
+ size_t maxLoop = 0;
+ int len;
+ if (!CheckValidCfg(path)) {
+ INIT_LOGE("CheckCfg file %s Failed", path);
+ return;
+ }
+ char *realPath = GetRealPath(path);
+ INIT_ERROR_CHECK(realPath != NULL, return, "Failed to get realpath %s", path);
+ FILE *fp = fopen(realPath, "r");
+ if (fp == NULL) {
+ INIT_LOGE("Failed to open cfg %s error:%d", path, errno);
+ free(realPath);
+ return;
+ }
+
+ while (fgets(buf, LOADCFG_BUF_SIZE - 1, fp) != NULL && maxLoop < LOADCFG_MAX_LOOP) {
+ maxLoop++;
+ len = strlen(buf);
+ if (len < 1) {
+ continue;
+ }
+ if (buf[len - 1] == '\n') {
+ buf[len - 1] = '\0'; // we replace '\n' with '\0'
+ }
+ const struct CmdTable *cmd = GetCmdByName(buf);
+ if (cmd == NULL) {
+ INIT_LOGE("Cannot support command: %s", buf);
+ continue;
+ }
+ ExecCmd(cmd, &buf[strlen(cmd->name) + 1]);
+ }
+ free(realPath);
+ (void)fclose(fp);
+}
+
+static void DoWrite(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ // format: write path content
+ char *realPath = GetRealPath(ctx->argv[0]);
+ int fd = -1;
+ if (realPath != NULL) {
+ fd = open(realPath, O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR);
+ } else {
+ fd = open(ctx->argv[0], O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR);
+ }
+ if (fd >= 0) {
+ size_t ret = write(fd, ctx->argv[1], strlen(ctx->argv[1]));
+ if (ret < 0) {
+ INIT_LOGE("DoWrite: write to file %s failed: %d", ctx->argv[0], errno);
+ }
+ }
+ if (realPath != NULL) {
+ free(realPath);
+ }
+ realPath = NULL;
+ close(fd);
+}
+
+static void DoRmdir(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ // format: rmdir path
+ int ret = rmdir(ctx->argv[0]);
+ if (ret == -1) {
+ INIT_LOGE("DoRmdir: remove %s failed: %d.", ctx->argv[0], errno);
+ }
+ return;
+}
+
+static void DoRebootCmd(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(ctx);
+ ExecReboot(cmdContent);
+ return;
+}
+
+static void DoSetrlimit(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ static const char *resource[] = {
+ "RLIMIT_CPU", "RLIMIT_FSIZE", "RLIMIT_DATA", "RLIMIT_STACK", "RLIMIT_CORE", "RLIMIT_RSS",
+ "RLIMIT_NPROC", "RLIMIT_NOFILE", "RLIMIT_MEMLOCK", "RLIMIT_AS", "RLIMIT_LOCKS", "RLIMIT_SIGPENDING",
+ "RLIMIT_MSGQUEUE", "RLIMIT_NICE", "RLIMIT_RTPRIO", "RLIMIT_RTTIME", "RLIM_NLIMITS"
+ };
+ // format: setrlimit resource curValue maxValue
+ const int rlimMaxPos = 2;
+ struct rlimit limit;
+ limit.rlim_cur = (rlim_t)atoi(ctx->argv[1]);
+ limit.rlim_max = (rlim_t)atoi(ctx->argv[rlimMaxPos]);
+ int rcs = -1;
+ for (unsigned int i = 0; i < ARRAY_LENGTH(resource); ++i) {
+ if (strcmp(ctx->argv[0], resource[i]) == 0) {
+ rcs = (int)i;
+ }
+ }
+ if (rcs == -1) {
+ INIT_LOGE("DoSetrlimit failed, resouces :%s not support.", ctx->argv[0]);
+ return;
+ }
+ int ret = setrlimit(rcs, &limit);
+ if (ret) {
+ INIT_LOGE("DoSetrlimit failed : %d", errno);
+ }
+}
+
+static void DoRm(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ // format: rm /xxx/xxx/xxx
+ int ret = unlink(ctx->argv[0]);
+ if (ret == -1) {
+ INIT_LOGE("DoRm: unlink %s failed: %d.", ctx->argv[0], errno);
+ }
+}
+
+static void DoExport(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ // format: export xxx /xxx/xxx/xxx
+ int ret = setenv(ctx->argv[0], ctx->argv[1], 1);
+ if (ret != 0) {
+ INIT_LOGE("DoExport: set %s with %s failed: %d", ctx->argv[0], ctx->argv[1], errno);
+ }
+}
+
+static const struct CmdTable g_cmdTable[] = {
+ { "start ", 0, 1, DoStart },
+ { "mkdir ", 1, 4, DoMkDir },
+ { "chmod ", 2, 2, DoChmod },
+ { "chown ", 3, 3, DoChown },
+ { "mount ", 1, 10, DoMount },
+ { "export ", 2, 2, DoExport },
+ { "loadcfg ", 1, 1, DoLoadCfg },
+ { "rm ", 1, 1, DoRm },
+ { "rmdir ", 1, 1, DoRmdir },
+ { "write ", 2, 2, DoWrite },
+ { "stop ", 1, 1, DoStop },
+ { "reset ", 1, 1, DoReset },
+ { "copy ", 2, 2, DoCopy },
+ { "reboot ", 1, 1, DoRebootCmd },
+ { "setrlimit ", 3, 3, DoSetrlimit },
+ { "sleep ", 1, 1, DoSleep },
+ { "hostname ", 1, 1, DoSetHostname },
+ { "domainname ", 1, 1, DoSetDomainname }
+};
+
+static const struct CmdTable *GetCommCmdTable(int *number)
+{
+ *number = (int)ARRAY_LENGTH(g_cmdTable);
+ return g_cmdTable;
+}
+
+const struct CmdTable *GetCmdByName(const char *name)
+{
+ int cmdCnt = 0;
+ const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt);
+ for (int i = 0; i < cmdCnt; ++i) {
+ if (strncmp(name, commCmds[i].name, strlen(commCmds[i].name)) == 0) {
+ return &commCmds[i];
+ }
+ }
+ int number = 0;
+ const struct CmdTable *cmds = GetCmdTable(&number);
+ for (int i = 0; i < number; ++i) {
+ if (strncmp(name, cmds[i].name, strlen(cmds[i].name)) == 0) {
+ return &cmds[i];
+ }
+ }
+ return NULL;
+}
+
+const char *GetMatchCmd(const char *cmdStr, int *index)
+{
+ if (cmdStr == NULL || index == NULL) {
+ return NULL;
+ }
+ int cmdCnt = 0;
+ const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt);
+ for (int i = 0; i < cmdCnt; ++i) {
+ if (strncmp(cmdStr, commCmds[i].name, strlen(commCmds[i].name)) == 0) {
+ *index = i;
+ return commCmds[i].name;
+ }
+ }
+ int number = 0;
+ const struct CmdTable *cmds = GetCmdTable(&number);
+ for (int i = 0; i < number; ++i) {
+ if (strncmp(cmdStr, cmds[i].name, strlen(cmds[i].name)) == 0) {
+ *index = cmdCnt + i;
+ return cmds[i].name;
+ }
+ }
+ return NULL;
+}
+
+const char *GetCmdKey(int index)
+{
+ int cmdCnt = 0;
+ const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt);
+ if (index < cmdCnt) {
+ return commCmds[index].name;
+ }
+ int number = 0;
+ const struct CmdTable *cmds = GetCmdTable(&number);
+ if (index < number) {
+ return cmds[index].name;
+ }
+ return NULL;
+}
+
+int GetCmdLinesFromJson(const cJSON *root, CmdLines **cmdLines)
+{
+ INIT_CHECK(root != NULL, return -1);
+ INIT_CHECK(cmdLines != NULL, return -1);
+ *cmdLines = NULL;
+ if (!cJSON_IsArray(root)) {
+ return -1;
+ }
+ int cmdCnt = cJSON_GetArraySize(root);
+ if (cmdCnt <= 0) {
+ return -1;
+ }
+ *cmdLines = (CmdLines *)calloc(1, sizeof(CmdLines) + sizeof(CmdLine) * cmdCnt);
+ if (*cmdLines == NULL) {
+ return -1;
+ }
+ (*cmdLines)->cmdNum = 0;
+ for (int i = 0; i < cmdCnt; ++i) {
+ cJSON *line = cJSON_GetArrayItem(root, i);
+ if (!cJSON_IsString(line)) {
+ continue;
+ }
+ char *tmp = cJSON_GetStringValue(line);
+ if (tmp == NULL) {
+ continue;
+ }
+ int index = 0;
+ const char *cmd = GetMatchCmd(tmp, &index);
+ if (cmd == NULL) {
+ INIT_LOGE("Cannot support command: %s", tmp);
+ continue;
+ }
+ int ret = strcpy_s((*cmdLines)->cmds[(*cmdLines)->cmdNum].cmdContent, MAX_CMD_CONTENT_LEN, tmp + strlen(cmd));
+ if (ret != EOK) {
+ INIT_LOGE("Invalid cmd arg: %s", tmp);
+ continue;
+ }
+ (*cmdLines)->cmds[(*cmdLines)->cmdNum].cmdIndex = index;
+ (*cmdLines)->cmdNum++;
+ }
+ return 0;
+}
+
+void DoCmdByName(const char *name, const char *cmdContent)
+{
+ if (name == NULL || cmdContent == NULL) {
+ return;
+ }
+ const struct CmdTable *cmd = GetCmdByName(name);
+ ExecCmd(cmd, cmdContent);
+}
+
+void DoCmdByIndex(int index, const char *cmdContent)
+{
+ if (cmdContent == NULL) {
+ return;
+ }
+ int cmdCnt = 0;
+ const struct CmdTable *commCmds = GetCommCmdTable(&cmdCnt);
+ if (index < cmdCnt) {
+ ExecCmd(&commCmds[index], cmdContent);
+ return;
+ }
+ int number = 0;
+ const struct CmdTable *cmds = GetCmdTable(&number);
+ if (index < (cmdCnt + number)) {
+ ExecCmd(&cmds[index - cmdCnt], cmdContent);
+ return;
+ }
+}
diff --git a/services/src/init_service.c b/services/init/init_common_service.c
old mode 100644
new mode 100755
similarity index 57%
rename from services/src/init_service.c
rename to services/init/init_common_service.c
index 4cb4a7c..197db70
--- a/services/src/init_service.c
+++ b/services/init/init_common_service.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -12,12 +12,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#include "init_service.h"
#include
#include
-#include
#include
#include
#include
@@ -25,46 +23,32 @@
#ifdef __MUSL__
#include
#endif
+#include
#include
-#ifndef OHOS_LITE
-#include
-#endif
#include
#include
#include
+#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);
}
-
diff --git a/services/init/init_config.c b/services/init/init_config.c
new file mode 100755
index 0000000..af59132
--- /dev/null
+++ b/services/init/init_config.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "init.h"
+#include "init_jobs.h"
+#include "init_log.h"
+#include "init_service_manager.h"
+#include "init_utils.h"
+
+static void ParseAllImports(const cJSON *root);
+
+static void ParseInitCfgContents(const char *cfgName, const cJSON *root)
+{
+ INIT_ERROR_CHECK(root != NULL, return, "Root is null");
+ INIT_LOGI("Parse init cfg %s ", cfgName);
+
+ ParseAllServices(root);
+ // parse jobs
+ ParseAllJobs(root);
+ // parse imports
+ ParseAllImports(root);
+}
+
+static int ParseInitCfg(const char *configFile, void *context)
+{
+ UNUSED(context);
+ char *fileBuf = ReadFileToBuf(configFile);
+ INIT_ERROR_CHECK(fileBuf != NULL, return -1, "Failed to read file content %s", configFile);
+
+ cJSON *fileRoot = cJSON_Parse(fileBuf);
+ INIT_ERROR_CHECK(fileRoot != NULL, free(fileBuf);
+ return -1, "Failed to parse json file %s", configFile);
+
+ ParseInitCfgContents(configFile, fileRoot);
+ cJSON_Delete(fileRoot);
+ free(fileBuf);
+ return 0;
+}
+
+static void ParseAllImports(const cJSON *root)
+{
+ char *tmpParamValue = malloc(PARAM_VALUE_LEN_MAX + 1);
+ INIT_ERROR_CHECK(tmpParamValue != 0, return, "Failed to alloc memory for param");
+
+ cJSON *importAttr = cJSON_GetObjectItemCaseSensitive(root, "import");
+ if (!cJSON_IsArray(importAttr)) {
+ free(tmpParamValue);
+ return;
+ }
+ int importAttrSize = cJSON_GetArraySize(importAttr);
+ for (int i = 0; i < importAttrSize; i++) {
+ cJSON *importItem = cJSON_GetArrayItem(importAttr, i);
+ if (!cJSON_IsString(importItem)) {
+ INIT_LOGE("Invalid type of import item. should be string");
+ break;
+ }
+ char *importContent = cJSON_GetStringValue(importItem);
+ if (importContent == NULL) {
+ INIT_LOGE("cannot get import config file");
+ break;
+ }
+ int ret = GetParamValue(importContent, strlen(importContent), tmpParamValue, PARAM_VALUE_LEN_MAX);
+ if (ret != 0) {
+ INIT_LOGE("cannot get value for %s", importContent);
+ continue;
+ }
+ INIT_LOGI("Import %s ...", tmpParamValue);
+ ParseInitCfg(tmpParamValue, NULL);
+ }
+ free(tmpParamValue);
+ return;
+}
+
+void ReadConfig(void)
+{
+ // parse cfg
+ if (InUpdaterMode() == 0) {
+ ParseInitCfg(INIT_CONFIGURATION_FILE, NULL);
+ ReadFileInDir(OTHER_CFG_PATH, ".cfg", ParseInitCfg, NULL);
+ } else {
+ ReadFileInDir("/etc", ".cfg", ParseInitCfg, NULL);
+ }
+}
diff --git a/services/init/init_service_manager.c b/services/init/init_service_manager.c
new file mode 100755
index 0000000..ccdba93
--- /dev/null
+++ b/services/init/init_service_manager.c
@@ -0,0 +1,584 @@
+/*
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "init_service_manager.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "cJSON.h"
+#include "init.h"
+#include "init_jobs.h"
+#include "init_log.h"
+#include "init_service_socket.h"
+#include "init_utils.h"
+#include "securec.h"
+
+// All serivce processes that init will fork+exec.
+static ServiceSpace g_serviceSpace = { { &g_serviceSpace.services, &g_serviceSpace.services }, 0 };
+
+#ifdef OHOS_SERVICE_DUMP
+static void DumpServiceArgs(const char *info, const ServiceArgs *args)
+{
+ INIT_LOGD("\t\t%s count %d", info, args->count);
+ for (int j = 0; j < args->count; j++) {
+ if (args->argv[j] != NULL) {
+ INIT_LOGD("\t\tinfo [%d] %s", j, args->argv[j]);
+ }
+ }
+}
+
+void DumpAllServices()
+{
+ INIT_LOGD("Ready to dump all services:");
+ INIT_LOGD("total service number: %d", g_serviceSpace.serviceCount);
+ ListNode *node = g_serviceSpace.services.next;
+ while (node != &g_serviceSpace.services) {
+ Service *service = ListEntry(node, Service, node);
+ INIT_LOGD("\tservice name: [%s]", service->name);
+ INIT_LOGD("\tservice pid: [%d]", service->pid);
+ INIT_LOGD("\tservice crashCnt: [%d]", service->crashCnt);
+ INIT_LOGD("\tservice attribute: [%d]", service->attribute);
+ INIT_LOGD("\tservice importance: [%d]", service->importance);
+ INIT_LOGD("\tservice perms uID [%d]", service->servPerm.uID);
+ DumpServiceArgs("path arg", &service->pathArgs);
+ DumpServiceArgs("writepid file", &service->writePidArgs);
+
+ INIT_LOGD("\tservice perms groupId %d", service->servPerm.gIDCnt);
+ for (int i = 0; i < service->servPerm.gIDCnt; i++) {
+ INIT_LOGD("\t\tservice perms groupId %d", service->servPerm.gIDArray[i]);
+ }
+
+ INIT_LOGD("\tservice perms capability %d", service->servPerm.capsCnt);
+ for (int i = 0; i < service->servPerm.capsCnt; i++) {
+ INIT_LOGD("\t\tservice perms capability %d", service->servPerm.caps[i]);
+ }
+ if (service->restartArg != NULL) {
+ for (int j = 0; j < service->restartArg->cmdNum; j++) {
+ CmdLine *cmd = &service->restartArg->cmds[j];
+ INIT_LOGD("\t\tcmd arg: %s %s", GetCmdKey(cmd->cmdIndex), cmd->cmdContent);
+ }
+ }
+ if (service->socketCfg != NULL) {
+ INIT_LOGD("\tservice socket name: %s", service->socketCfg->name);
+ INIT_LOGD("\tservice socket type: %d", service->socketCfg->type);
+ INIT_LOGD("\tservice socket uid: %d", service->socketCfg->uid);
+ INIT_LOGD("\tservice socket gid: %d", service->socketCfg->gid);
+ }
+ node = node->next;
+ }
+ INIT_LOGD("Dump all services finished");
+}
+#endif
+
+static void FreeServiceArg(ServiceArgs *arg)
+{
+ if (arg != NULL) {
+ return;
+ }
+ for (int i = 0; i < arg->count; ++i) {
+ if (arg->argv[i] != NULL) {
+ free(arg->argv[i]);
+ arg->argv[i] = NULL;
+ }
+ }
+ free(arg->argv);
+ arg->argv = NULL;
+ arg->count = 0;
+}
+
+static void FreeServiceSocket(ServiceSocket *sockopt)
+{
+ while (sockopt != NULL) {
+ ServiceSocket *tmp = sockopt;
+ if (tmp->sockFd >= 0) {
+ close(tmp->sockFd);
+ tmp->sockFd = -1;
+ }
+ sockopt = sockopt->next;
+ free(tmp);
+ }
+ return;
+}
+
+static Service *AddService(void)
+{
+ Service *service = (Service *)calloc(1, sizeof(Service));
+ INIT_ERROR_CHECK(service != NULL, return NULL, "Failed to malloc for service");
+ ListInit(&service->node);
+ ListAddTail(&g_serviceSpace.services, &service->node);
+ g_serviceSpace.serviceCount++;
+ return service;
+}
+
+static void ReleaseService(Service *service)
+{
+ if (service == NULL) {
+ return;
+ }
+ FreeServiceArg(&service->pathArgs);
+ FreeServiceArg(&service->writePidArgs);
+
+ if (service->servPerm.caps != NULL) {
+ free(service->servPerm.caps);
+ service->servPerm.caps = NULL;
+ }
+ service->servPerm.capsCnt = 0;
+ if (service->servPerm.gIDArray != NULL) {
+ free(service->servPerm.gIDArray);
+ service->servPerm.gIDArray = NULL;
+ }
+ service->servPerm.gIDCnt = 0;
+ FreeServiceSocket(service->socketCfg);
+
+ if (!ListEmpty(service->node)) {
+ ListRemove(&service->node);
+ g_serviceSpace.serviceCount--;
+ }
+ free(service);
+}
+
+static int GetStringItem(const cJSON *json, const char *name, char *buffer, int buffLen)
+{
+ INIT_ERROR_CHECK(json != NULL, return SERVICE_FAILURE, "Invalid json for %s", name);
+ char *fieldStr = cJSON_GetStringValue(cJSON_GetObjectItem(json, name));
+ INIT_ERROR_CHECK(fieldStr != NULL, return SERVICE_FAILURE, "Failed to get string for %s", name);
+ size_t strLen = strlen(fieldStr);
+ if ((strLen == 0) || (strLen > (size_t)buffLen)) {
+ INIT_LOGE("Invalid str filed %s for %s", fieldStr, name);
+ return SERVICE_FAILURE;
+ }
+ return strcpy_s(buffer, buffLen, fieldStr);
+}
+
+cJSON *GetArrayItem(const cJSON *fileRoot, int *arrSize, const char *arrName)
+{
+ cJSON *arrItem = cJSON_GetObjectItemCaseSensitive(fileRoot, arrName);
+ if (!cJSON_IsArray(arrItem)) {
+ return NULL;
+ }
+ *arrSize = cJSON_GetArraySize(arrItem);
+ if (*arrSize <= 0) {
+ return NULL;
+ }
+ return arrItem;
+}
+
+static int GetServiceArgs(const cJSON *argJson, const char *name, int maxCount, ServiceArgs *args)
+{
+ INIT_ERROR_CHECK(argJson != NULL, return SERVICE_FAILURE, "Invalid argJson");
+ cJSON *obj = cJSON_GetObjectItem(argJson, name);
+ INIT_CHECK(obj != NULL, return SERVICE_FAILURE);
+
+ int ret = cJSON_IsArray(obj);
+ INIT_ERROR_CHECK(ret, return SERVICE_FAILURE, "Invalid type");
+ int count = cJSON_GetArraySize(obj);
+ INIT_ERROR_CHECK((count > 0) && (count < maxCount), return SERVICE_FAILURE, "Array size = %d is wrong", count);
+
+ args->argv = (char **)malloc((count + 1) * sizeof(char *));
+ INIT_ERROR_CHECK(args->argv != NULL, return SERVICE_FAILURE, "Failed to malloc for argv");
+ for (int i = 0; i < count + 1; ++i) {
+ args->argv[i] = NULL;
+ }
+ args->count = count + 1;
+ for (int i = 0; i < count; ++i) {
+ char *curParam = cJSON_GetStringValue(cJSON_GetArrayItem(obj, i));
+ INIT_ERROR_CHECK(curParam != NULL, return SERVICE_FAILURE, "Invalid arg %d", i);
+ INIT_ERROR_CHECK(strlen(curParam) <= MAX_ONE_ARG_LEN, return SERVICE_FAILURE, "Arg %s is tool long", curParam);
+ args->argv[i] = strdup(curParam);
+ INIT_ERROR_CHECK(args->argv[i] != NULL, return SERVICE_FAILURE, "Failed to dupstring %s", curParam);
+ }
+ return SERVICE_SUCCESS;
+}
+
+static int GetUid(cJSON *json, uid_t *uid)
+{
+ INIT_CHECK_RETURN_VALUE(json != NULL, SERVICE_SUCCESS);
+ if (cJSON_IsString(json)) {
+ char *str = cJSON_GetStringValue(json);
+ INIT_ERROR_CHECK(str != NULL, return SERVICE_FAILURE, "Invalid str");
+ *uid = DecodeUid(str);
+ } else if (cJSON_IsNumber(json)) {
+ *uid = (uid_t)cJSON_GetNumberValue(json);
+ }
+ if (*uid == (uid_t)(-1)) {
+ return SERVICE_FAILURE;
+ }
+ return SERVICE_SUCCESS;
+}
+
+static int GetServiceGids(const cJSON *curArrItem, Service *curServ)
+{
+ int gidCount = 0;
+ cJSON *arrItem = cJSON_GetObjectItemCaseSensitive(curArrItem, GID_STR_IN_CFG);
+ if (!cJSON_IsArray(arrItem)) {
+ gidCount = 1;
+ } else {
+ gidCount = cJSON_GetArraySize(arrItem);
+ }
+ if ((gidCount == 0) || (gidCount > NGROUPS_MAX + 1)) {
+ INIT_LOGE("Invalid gid count %d", gidCount);
+ return SERVICE_FAILURE;
+ }
+ curServ->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t) * gidCount);
+ INIT_ERROR_CHECK(curServ->servPerm.gIDArray != NULL, return SERVICE_FAILURE, "Failed to malloc");
+ curServ->servPerm.gIDCnt = gidCount;
+
+ gid_t gid;
+ if (!cJSON_IsArray(arrItem)) {
+ int ret = GetUid(arrItem, &gid);
+ INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to uid");
+ curServ->servPerm.gIDArray[0] = gid;
+ return SERVICE_SUCCESS;
+ }
+
+ for (int i = 0; i < gidCount; ++i) {
+ cJSON *item = cJSON_GetArrayItem(arrItem, i);
+ int ret = GetUid(item, &gid);
+ if (ret != 0) {
+ curServ->servPerm.gIDArray[i] = 0;
+ continue;
+ }
+ curServ->servPerm.gIDArray[i] = gid;
+ }
+ return SERVICE_SUCCESS;
+}
+
+static int GetServiceAttr(const cJSON *curArrItem, Service *curServ, const char *attrName, int flag,
+ int (*processAttr)(Service *curServ, const char *attrName, int value, int flag))
+{
+ cJSON *filedJ = cJSON_GetObjectItem(curArrItem, attrName);
+ if (filedJ == NULL) {
+ return SERVICE_SUCCESS;
+ }
+ if (!cJSON_IsNumber(filedJ)) {
+ INIT_LOGE("%s is null or is not a number, service name is %s", attrName, curServ->name);
+ return SERVICE_FAILURE;
+ }
+
+ int value = (int)cJSON_GetNumberValue(filedJ);
+ if (processAttr == NULL) {
+ curServ->attribute &= ~flag;
+ if (value == 1) {
+ curServ->attribute |= flag;
+ }
+ return 0;
+ }
+ return processAttr(curServ, attrName, value, flag);
+}
+
+static int AddServiceSocket(cJSON *json, Service *service)
+{
+ char *opt[SOCK_OPT_NUMS] = {
+ NULL,
+ };
+ if (!cJSON_IsString(json) || !cJSON_GetStringValue(json)) {
+ return SERVICE_FAILURE;
+ }
+ char *sockStr = cJSON_GetStringValue(json);
+ int num = SplitString(sockStr, " ", opt, SOCK_OPT_NUMS);
+ if (num != SOCK_OPT_NUMS) {
+ return SERVICE_FAILURE;
+ }
+ if (opt[SERVICE_SOCK_NAME] == NULL || opt[SERVICE_SOCK_TYPE] == NULL || opt[SERVICE_SOCK_PERM] == NULL ||
+ opt[SERVICE_SOCK_UID] == NULL || opt[SERVICE_SOCK_GID] == NULL || opt[SERVICE_SOCK_SETOPT] == NULL) {
+ INIT_LOGE("Invalid socket opt");
+ return SERVICE_FAILURE;
+ }
+
+ ServiceSocket *sockopt = (ServiceSocket *)calloc(1, sizeof(ServiceSocket) + strlen(opt[SERVICE_SOCK_NAME]) + 1);
+ INIT_INFO_CHECK(sockopt != NULL, return SERVICE_FAILURE, "Failed to malloc for socket %s", opt[SERVICE_SOCK_NAME]);
+ int ret = strcpy_s(sockopt->name, strlen(opt[SERVICE_SOCK_NAME]) + 1, opt[SERVICE_SOCK_NAME]);
+ INIT_INFO_CHECK(ret == 0, free(sockopt);
+ return SERVICE_FAILURE, "Failed to copy socket name %s", opt[SERVICE_SOCK_NAME]);
+
+ sockopt->type = SOCK_SEQPACKET;
+ if (strncmp(opt[SERVICE_SOCK_TYPE], "stream", strlen(opt[SERVICE_SOCK_TYPE])) == 0) {
+ sockopt->type = SOCK_STREAM;
+ } else if (strncmp(opt[SERVICE_SOCK_TYPE], "dgram", strlen(opt[SERVICE_SOCK_TYPE])) == 0) {
+ sockopt->type = SOCK_DGRAM;
+ }
+ sockopt->perm = strtoul(opt[SERVICE_SOCK_PERM], 0, OCTAL_BASE);
+ sockopt->uid = DecodeUid(opt[SERVICE_SOCK_UID]);
+ sockopt->gid = DecodeUid(opt[SERVICE_SOCK_GID]);
+ if (sockopt->uid == (uid_t)-1 || sockopt->gid == (uid_t)-1) {
+ free(sockopt);
+ INIT_LOGE("Invalid uid %d or gid %d", sockopt->uid, sockopt->gid);
+ return SERVICE_FAILURE;
+ }
+ sockopt->passcred = false;
+ if (strncmp(opt[SERVICE_SOCK_SETOPT], "passcred", strlen(opt[SERVICE_SOCK_SETOPT])) == 0) {
+ sockopt->passcred = true;
+ }
+ sockopt->next = NULL;
+ if (service->socketCfg == NULL) {
+ service->socketCfg = sockopt;
+ } else {
+ sockopt->next = service->socketCfg->next;
+ service->socketCfg->next = sockopt;
+ }
+ return SERVICE_SUCCESS;
+}
+
+static int ParseServiceSocket(const cJSON *curArrItem, Service *curServ)
+{
+ int sockCnt = 0;
+ cJSON *filedJ = GetArrayItem(curArrItem, &sockCnt, "socket");
+ INIT_CHECK(filedJ != NULL && sockCnt > 0, return SERVICE_FAILURE);
+ int ret = 0;
+ curServ->socketCfg = NULL;
+ for (int i = 0; i < sockCnt; ++i) {
+ cJSON *sockJ = cJSON_GetArrayItem(filedJ, i);
+ ret = AddServiceSocket(sockJ, curServ);
+ if (ret != 0) {
+ break;
+ }
+ }
+ return ret;
+}
+
+static bool IsServiceInMainStrap(Service *curServ)
+{
+ char *mainServiceList[] = {
+ "appspawn", "udevd", "samgr", "multimodalinput", "weston", "installs",
+ "hiview", "hilogd", "hdf_devmgr", "distributedsche", "softbus_server", "foundation"
+ };
+ unsigned int length = ARRAY_LENGTH(mainServiceList);
+ for (unsigned int i = 0; i < length; ++i) {
+ if (strncmp(curServ->name, mainServiceList[i], strlen(mainServiceList[i])) == 0) {
+ INIT_LOGI("%s must be main service", curServ->name);
+ return true;
+ }
+ }
+ return false;
+}
+
+static int GetDynamicService(const cJSON *curArrItem, Service *curServ)
+{
+ cJSON *item = cJSON_GetObjectItem(curArrItem, "dynamic");
+ if (item == NULL) {
+ return SERVICE_SUCCESS;
+ }
+
+ INIT_ERROR_CHECK(cJSON_IsBool(item), return SERVICE_FAILURE,
+ "Service : %s dynamic value only support bool.", curServ->name);
+ bool isDynamic = (bool)cJSON_GetNumberValue(item);
+ if (!isDynamic) {
+ INIT_LOGI("Service : %s dynamic value is false, it will be started with init.", curServ->name);
+ return SERVICE_SUCCESS;
+ }
+
+ if (IsServiceInMainStrap(curServ)) {
+ return SERVICE_SUCCESS;
+ }
+ INIT_LOGI("%s is dynamic service", curServ->name);
+ curServ->attribute |= SERVICE_ATTR_DYNAMIC;
+ curServ->attribute |= SERVICE_ATTR_ONCE;
+ return SERVICE_SUCCESS;
+}
+
+static int CheckServiceKeyName(const cJSON *curService)
+{
+ char *cfgServiceKeyList[] = {
+ "name", "path", "uid", "gid", "once", "importance", "caps", "disabled",
+ "writepid", "critical", "socket", "console", "dynamic"
+ };
+ if (curService == NULL) {
+ return SERVICE_FAILURE;
+ }
+ cJSON *child = curService->child;
+ if (child == NULL) {
+ return SERVICE_FAILURE;
+ }
+ while (child != NULL) {
+ int i = 0;
+ int keyListSize = ARRAY_LENGTH(cfgServiceKeyList);
+ for (; i < keyListSize; i++) {
+ if (strcmp(child->string, cfgServiceKeyList[i]) == 0) {
+ break;
+ }
+ }
+ if (i < keyListSize) {
+ child = child->next;
+ } else {
+ INIT_LOGE("CheckServiceKeyName, key name %s is not found. error.", child->string);
+ return SERVICE_FAILURE;
+ }
+ }
+ return SERVICE_SUCCESS;
+}
+
+static int ParseOneService(const cJSON *curItem, Service *service)
+{
+ if (curItem == NULL || service == NULL) {
+ return SERVICE_FAILURE;
+ }
+ int ret = GetStringItem(curItem, "name", service->name, MAX_SERVICE_NAME);
+ INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get service name");
+ ret = GetServiceArgs(curItem, "path", MAX_PATH_ARGS_CNT, &service->pathArgs);
+ INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get path for service %s", service->name);
+ if ((service->pathArgs.count > 0) && IsForbidden(service->pathArgs.argv[0])) {
+ INIT_LOGE("Service %s is forbidden.", service->name);
+ return SERVICE_FAILURE;
+ }
+ ret = GetUid(cJSON_GetObjectItem(curItem, UID_STR_IN_CFG), &service->servPerm.uID);
+ INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get uid for service %s", service->name);
+ ret = GetServiceGids(curItem, service);
+ INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get gid for service %s", service->name);
+
+ ret = GetServiceAttr(curItem, service, ONCE_STR_IN_CFG, SERVICE_ATTR_ONCE, NULL);
+ INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get once flag for service %s", service->name);
+ ret = GetServiceAttr(curItem, service, IMPORTANT_STR_IN_CFG, SERVICE_ATTR_IMPORTANT, SetImportantValue);
+ INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get import flag for service %s", service->name);
+ ret = GetServiceAttr(curItem, service, CRITICAL_STR_IN_CFG, SERVICE_ATTR_CRITICAL, NULL);
+ INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get critical flag for service %s", service->name);
+ ret = GetServiceAttr(curItem, service, DISABLED_STR_IN_CFG, SERVICE_ATTR_DISABLED, NULL);
+ INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get disabled flag for service %s", service->name);
+ ret = GetServiceAttr(curItem, service, CONSOLE_STR_IN_CFG, SERVICE_ATTR_CONSOLE, NULL);
+ INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get console for service %s", service->name);
+
+ ret = GetServiceArgs(curItem, "writepid", MAX_WRITEPID_FILES, &service->writePidArgs);
+ INIT_CHECK_ONLY_ELOG(ret == 0, "No writepid arg for service %s", service->name);
+ ret = GetServiceCaps(curItem, service);
+ INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get caps for service %s", service->name);
+ ret = GetDynamicService(curItem, service);
+ INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Failed to get dynamic flag for service %s", service->name);
+ return ret;
+}
+
+void ParseAllServices(const cJSON *fileRoot)
+{
+ int servArrSize = 0;
+ cJSON *serviceArr = GetArrayItem(fileRoot, &servArrSize, SERVICES_ARR_NAME_IN_JSON);
+ INIT_INFO_CHECK(serviceArr != NULL, return, "This config does not contain service array.");
+
+ INIT_ERROR_CHECK(servArrSize <= MAX_SERVICES_CNT_IN_FILE, return,
+ "Too many services[cnt %d] detected, should not exceed %d.",
+ servArrSize, MAX_SERVICES_CNT_IN_FILE);
+
+ Service tmpService = {};
+ for (int i = 0; i < servArrSize; ++i) {
+ cJSON *curItem = cJSON_GetArrayItem(serviceArr, i);
+ int ret = GetStringItem(curItem, "name", tmpService.name, MAX_SERVICE_NAME);
+ if (ret != 0) {
+ INIT_LOGE("Failed to get service name %s", tmpService.name);
+ continue;
+ }
+ if (CheckServiceKeyName(curItem) != SERVICE_SUCCESS) { // invalid service
+ INIT_LOGE("Invalid service name %s", tmpService.name);
+ continue;
+ }
+ Service *service = GetServiceByName(tmpService.name);
+ if (service != NULL) {
+ INIT_LOGE("Service name %s has been exist", tmpService.name);
+ continue;
+ }
+ service = AddService();
+ if (service == NULL) {
+ INIT_LOGE("Failed to create service name %s", tmpService.name);
+ continue;
+ }
+
+ ret = ParseOneService(curItem, service);
+ if (ret != SERVICE_SUCCESS) {
+ ReleaseService(service);
+ continue;
+ }
+ ret = ParseServiceSocket(curItem, service);
+ if (ret != SERVICE_SUCCESS) {
+ FreeServiceSocket(service->socketCfg);
+ service->socketCfg = NULL;
+ }
+ ret = GetCmdLinesFromJson(cJSON_GetObjectItem(curItem, "onrestart"), &service->restartArg);
+ if (ret != SERVICE_SUCCESS) {
+ service->restartArg = NULL;
+ }
+ INIT_LOGD("service[%d] name=%s, uid=%d, critical=%d, disabled=%d",
+ i, service->name, service->servPerm.uID,
+ (service->attribute & SERVICE_ATTR_CRITICAL) ? 1 : 0,
+ (service->attribute & SERVICE_ATTR_DISABLED) ? 1 : 0);
+ }
+}
+
+void StartServiceByName(const char *servName, bool checkDynamic)
+{
+ Service *service = GetServiceByName(servName);
+ INIT_ERROR_CHECK(service != NULL, return, "Cannot find service %s.", servName);
+
+ if (checkDynamic && (service->attribute & SERVICE_ATTR_DYNAMIC)) {
+ INIT_LOGI("%s is dynamic service.", servName);
+ return;
+ }
+ if (ServiceStart(service) != SERVICE_SUCCESS) {
+ INIT_LOGE("Service %s start failed!", servName);
+ }
+ return;
+}
+
+void StopServiceByName(const char *servName)
+{
+ Service *service = GetServiceByName(servName);
+ INIT_ERROR_CHECK(service != NULL, return, "Cannot find service %s.", servName);
+
+ if (ServiceStop(service) != SERVICE_SUCCESS) {
+ INIT_LOGE("Service %s start failed!", servName);
+ }
+ return;
+}
+
+void StopAllServices(int flags)
+{
+ ListNode *node = g_serviceSpace.services.next;
+ while (node != &g_serviceSpace.services) {
+ Service *service = ListEntry(node, Service, node);
+ service->attribute |= flags;
+ int ret = ServiceStop(service);
+ if (ret != SERVICE_SUCCESS) {
+ INIT_LOGE("Service %s stop failed!", service->name);
+ }
+ node = node->next;
+ }
+}
+
+Service *GetServiceByPid(pid_t pid)
+{
+ ListNode *node = g_serviceSpace.services.next;
+ while (node != &g_serviceSpace.services) {
+ Service *service = ListEntry(node, Service, node);
+ if (service->pid == pid) {
+ return service;
+ }
+ node = node->next;
+ }
+ return NULL;
+}
+
+Service *GetServiceByName(const char *servName)
+{
+ ListNode *node = g_serviceSpace.services.next;
+ while (node != &g_serviceSpace.services) {
+ Service *service = ListEntry(node, Service, node);
+ if (strcmp(service->name, servName) == 0) {
+ return service;
+ }
+ node = node->next;
+ }
+ return NULL;
+}
diff --git a/services/init/init_service_socket.c b/services/init/init_service_socket.c
new file mode 100755
index 0000000..11d2bdb
--- /dev/null
+++ b/services/init/init_service_socket.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "init_service_socket.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "init_log.h"
+#include "init_service.h"
+#include "securec.h"
+
+#define HOS_SOCKET_DIR "/dev/unix/socket"
+#define HOS_SOCKET_ENV_PREFIX "OHOS_SOCKET_"
+#define MAX_SOCKET_ENV_PREFIX_LEN 64
+#define MAX_SOCKET_FD_LEN 16
+
+static int GetSocketAddr(struct sockaddr_un *addr, const char *name)
+{
+ bzero(addr, sizeof(struct sockaddr_un));
+ addr->sun_family = AF_UNIX;
+ size_t addrLen = sizeof(addr->sun_path);
+ int ret = snprintf_s(addr->sun_path, addrLen, addrLen - 1, HOS_SOCKET_DIR "/%s", name);
+ INIT_ERROR_CHECK(ret >= 0, return -1, "Failed to format addr %s", name);
+ return 0;
+}
+
+static int CreateSocket(ServiceSocket *sockopt)
+{
+ INIT_ERROR_CHECK(sockopt != NULL, return SERVICE_FAILURE, "Invalid socket opt");
+ if (sockopt->sockFd >= 0) {
+ close(sockopt->sockFd);
+ sockopt->sockFd = -1;
+ }
+ sockopt->sockFd = socket(PF_UNIX, sockopt->type, 0);
+ INIT_ERROR_CHECK(sockopt->sockFd >= 0, return -1, "socket fail %d ", errno);
+
+ struct sockaddr_un addr;
+ int ret = GetSocketAddr(&addr, sockopt->name);
+ INIT_ERROR_CHECK(ret == 0, return -1, "Failed to format addr %s", sockopt->name);
+
+ do {
+ ret = -1;
+ if (access(addr.sun_path, F_OK)) {
+ INIT_LOGI("%s already exist, remove it", addr.sun_path);
+ unlink(addr.sun_path);
+ }
+ if (sockopt->passcred) {
+ int on = 1;
+ if (setsockopt(sockopt->sockFd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
+ break;
+ }
+ }
+ if (bind(sockopt->sockFd, (struct sockaddr *)&addr, sizeof(addr))) {
+ INIT_LOGE("Create socket for service %s failed: %d", sockopt->name, errno);
+ break;
+ }
+ if (lchown(addr.sun_path, sockopt->uid, sockopt->gid)) {
+ INIT_LOGE("lchown fail %d ", errno);
+ break;
+ }
+ if (fchmodat(AT_FDCWD, addr.sun_path, sockopt->perm, AT_SYMLINK_NOFOLLOW)) {
+ INIT_LOGE("fchmodat fail %d ", errno);
+ break;
+ }
+ ret = 0;
+ } while (0);
+ if (ret != 0) {
+ close(sockopt->sockFd);
+ unlink(addr.sun_path);
+ return -1;
+ }
+ INIT_LOGI("CreateSocket %s success", sockopt->name);
+ return sockopt->sockFd;
+}
+
+static int SetSocketEnv(int fd, const char *name)
+{
+ INIT_ERROR_CHECK(name != NULL, return SERVICE_FAILURE, "Invalid name");
+ char pubName[MAX_SOCKET_ENV_PREFIX_LEN] = { 0 };
+ char val[MAX_SOCKET_FD_LEN] = { 0 };
+ if (snprintf_s(pubName, sizeof(pubName), sizeof(pubName) - 1, HOS_SOCKET_ENV_PREFIX "%s", name) < 0) {
+ return -1;
+ }
+ if (snprintf_s(val, sizeof(val), sizeof(val) - 1, "%d", fd) < 0) {
+ return -1;
+ }
+ int ret = setenv(pubName, val, 1);
+ if (ret < 0) {
+ INIT_LOGE("setenv fail %d ", errno);
+ return -1;
+ }
+ fcntl(fd, F_SETFD, 0);
+ return 0;
+}
+
+int CreateServiceSocket(ServiceSocket *sockopt)
+{
+ INIT_CHECK(sockopt != NULL, return 0);
+ ServiceSocket *tmpSock = sockopt;
+ while (tmpSock != NULL) {
+ int fd = CreateSocket(tmpSock);
+ if (fd < 0) {
+ return -1;
+ }
+ int ret = SetSocketEnv(fd, tmpSock->name);
+ if (ret < 0) {
+ return -1;
+ }
+ tmpSock = tmpSock->next;
+ }
+ return 0;
+}
+
+void CloseServiceSocket(ServiceSocket *sockopt)
+{
+ INIT_CHECK(sockopt != NULL, return);
+ struct sockaddr_un addr;
+ ServiceSocket *tmpSock = sockopt;
+ while (tmpSock != NULL) {
+ if (sockopt->sockFd >= 0) {
+ close(sockopt->sockFd);
+ sockopt->sockFd = -1;
+ }
+ if (GetSocketAddr(&addr, sockopt->name) == 0) {
+ unlink(addr.sun_path);
+ }
+ tmpSock = tmpSock->next;
+ }
+ return;
+}
\ No newline at end of file
diff --git a/services/init/lite/init.c b/services/init/lite/init.c
new file mode 100755
index 0000000..b3374c8
--- /dev/null
+++ b/services/init/lite/init.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "init.h"
+#include "init_log.h"
+#include "init_jobs.h"
+#ifndef __LINUX__
+#include "init_stage.h"
+#endif
+#include "parameter.h"
+#include "securec.h"
+
+static void PrintSysInfo(void)
+{
+ const char *sysInfo = GetVersionId();
+ if (sysInfo != NULL) {
+ INIT_LOGE("%s", sysInfo);
+ return;
+ }
+}
+
+void SystemInit(void)
+{
+ SignalInit();
+}
+
+void LogInit(void)
+{
+
+}
+
+void SystemPrepare(void)
+{
+ PrintSysInfo();
+}
+
+void SystemConfig(void)
+{
+ // read config
+ ReadConfig();
+
+ // dump config
+#ifdef OHOS_SERVICE_DUMP
+ DumpAllServices();
+#endif
+
+ // execute init
+ DoJob("pre-init");
+#ifndef __LINUX__
+ TriggerStage(EVENT1, EVENT1_WAITTIME, QS_STAGE1);
+#endif
+
+ DoJob("init");
+#ifndef __LINUX__
+ TriggerStage(EVENT2, EVENT2_WAITTIME, QS_STAGE2);
+#endif
+
+ DoJob("post-init");
+#ifndef __LINUX__
+ TriggerStage(EVENT3, EVENT3_WAITTIME, QS_STAGE3);
+ InitStageFinished();
+#endif
+ ReleaseAllJobs();
+}
+
+void SystemRun(void)
+{
+ while (1) {
+ // pause only returns when a signal was caught and the signal-catching function returned.
+ // pause only returns -1, no need to process the return value.
+ (void)pause();
+ }
+}
\ No newline at end of file
diff --git a/services/init/lite/init_cmds.c b/services/init/lite/init_cmds.c
new file mode 100755
index 0000000..5534777
--- /dev/null
+++ b/services/init/lite/init_cmds.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include
+#include
+
+#include "init.h"
+#include "init_cmds.h"
+#include "init_log.h"
+#include "init_utils.h"
+#include "securec.h"
+
+int GetParamValue(const char *symValue, unsigned int symLen, char *paramValue, unsigned int paramLen)
+{
+ return (strncpy_s(paramValue, paramLen, symValue, symLen) == EOK) ? 0 : -1;
+}
+
+static void DoExec(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(ctx);
+ // format: exec /xxx/xxx/xxx xxx
+ pid_t pid = fork();
+ if (pid < 0) {
+ INIT_LOGE("DoExec: failed to fork child process to exec \"%s\"", cmdContent);
+ return;
+ }
+ if (pid == 0) {
+ struct CmdArgs *subCtx = GetCmdArg(cmdContent, " ", SUPPORT_MAX_ARG_FOR_EXEC);
+ if (subCtx == NULL || subCtx->argv[0] == NULL) {
+ INIT_LOGE("DoExec: invalid arguments :%s", cmdContent);
+ _exit(0x7f);
+ }
+ int ret = execve(subCtx->argv[0], subCtx->argv, NULL);
+ if (ret == -1) {
+ INIT_LOGE("DoExec: execute \"%s\" failed: %d.", cmdContent, errno);
+ }
+ FreeCmdArg(subCtx);
+ _exit(0x7f);
+ }
+ return;
+}
+
+static const struct CmdTable g_cmdTable[] = { { "exec ", 1, 10, DoExec } };
+
+const struct CmdTable *GetCmdTable(int *number)
+{
+ *number = (int)ARRAY_LENGTH(g_cmdTable);
+ return g_cmdTable;
+}
diff --git a/services/src/init_jobs.c b/services/init/lite/init_jobs.c
old mode 100644
new mode 100755
similarity index 56%
rename from services/src/init_jobs.c
rename to services/init/lite/init_jobs.c
index 1bac3d7..ab09c6a
--- a/services/src/init_jobs.c
+++ b/services/init/lite/init_jobs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -12,7 +12,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#include "init_jobs.h"
#include
@@ -25,28 +24,31 @@
#define JOBS_ARR_NAME_IN_JSON "jobs"
#define CMDS_ARR_NAME_IN_JSON "cmds"
-#define MAX_JOBS_COUNT 100
+#define MAX_JOBS_COUNT 100
-static Job* g_jobs = NULL;
+static Job *g_jobs = NULL;
static int g_jobCnt = 0;
void DumpAllJobs(void)
{
- INIT_LOGD("Ready to dump all jobs:");
+ INIT_LOGD("Start to dump all jobs...");
for (int i = 0; i < g_jobCnt; i++) {
INIT_LOGD("\tjob name: %s", g_jobs[i].name);
+ if (g_jobs[i].cmdLines == NULL) {
+ continue;
+ }
INIT_LOGD("\tlist all commands:");
- for (int j = 0; j < g_jobs[i].cmdLinesCnt; j++) {
- INIT_LOGD("\t\tcommand name : %s, command options: %s",
- g_jobs[i].cmdLines[j].name, g_jobs[i].cmdLines[j].cmdContent);
+ for (int j = 0; j < g_jobs[i].cmdLines->cmdNum; j++) {
+ CmdLine *cmd = &g_jobs[i].cmdLines->cmds[j];
+ INIT_LOGD("\t\tcommand: %s %s", GetCmdKey(cmd->cmdIndex), cmd->cmdContent);
}
}
- INIT_LOGD("To dump all jobs finished");
+ INIT_LOGD("Finish dump all jobs");
}
-static int GetJobName(const cJSON* jobItem, Job* resJob)
+static int GetJobName(const cJSON *jobItem, Job *resJob)
{
- char* jobNameStr = cJSON_GetStringValue(cJSON_GetObjectItem(jobItem, "name"));
+ char *jobNameStr = cJSON_GetStringValue(cJSON_GetObjectItem(jobItem, "name"));
if (jobNameStr == NULL) {
return 0;
}
@@ -59,7 +61,7 @@ static int GetJobName(const cJSON* jobItem, Job* resJob)
return 1;
}
-static void ParseJob(const cJSON* jobItem, Job* resJob)
+static void ParseJob(const cJSON *jobItem, Job *resJob)
{
if (!GetJobName(jobItem, resJob)) {
INIT_LOGE("get JobName failed");
@@ -67,52 +69,27 @@ static void ParseJob(const cJSON* jobItem, Job* resJob)
return;
}
- cJSON* cmdsItem = cJSON_GetObjectItem(jobItem, CMDS_ARR_NAME_IN_JSON);
+ cJSON *cmdsItem = cJSON_GetObjectItem(jobItem, CMDS_ARR_NAME_IN_JSON);
if (!cJSON_IsArray(cmdsItem)) {
INIT_LOGE("job %s is not an arrary", resJob->name);
return;
}
-
- int cmdLinesCnt = cJSON_GetArraySize(cmdsItem);
- if (cmdLinesCnt <= 0) { // empty job, no cmd
- INIT_LOGE("empty job \"%s\"", resJob->name);
+ int ret = GetCmdLinesFromJson(cmdsItem, &resJob->cmdLines);
+ if (ret != 0) {
+ INIT_LOGE("ParseJob, faild to get cmds for job!");
return;
}
-
- INIT_LOGD("job = %s, cmdLineCnt = %d", resJob->name, cmdLinesCnt);
- if (cmdLinesCnt > MAX_CMD_CNT_IN_ONE_JOB) {
- INIT_LOGE("ParseAllJobs, too many cmds[cnt %d] in one job, it should not exceed %d.",
- cmdLinesCnt, MAX_CMD_CNT_IN_ONE_JOB);
- return;
- }
-
- resJob->cmdLines = (CmdLine*)malloc(cmdLinesCnt * sizeof(CmdLine));
- if (resJob->cmdLines == NULL) {
- INIT_LOGE("allocate memory for command line failed");
- return;
- }
-
- if (memset_s(resJob->cmdLines, cmdLinesCnt * sizeof(CmdLine), 0, cmdLinesCnt * sizeof(CmdLine)) != EOK) {
- free(resJob->cmdLines);
- resJob->cmdLines = NULL;
- return;
- }
- resJob->cmdLinesCnt = cmdLinesCnt;
-
- for (int i = 0; i < cmdLinesCnt; ++i) {
- char* cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdsItem, i));
- ParseCmdLine(cmdLineStr, &(resJob->cmdLines[i]));
- }
+ return;
}
-void ParseAllJobs(const cJSON* fileRoot)
+void ParseAllJobs(const cJSON *fileRoot)
{
if (fileRoot == NULL) {
INIT_LOGE("ParseAllJobs, input fileRoot is NULL!");
return;
}
- cJSON* jobArr = cJSON_GetObjectItemCaseSensitive(fileRoot, JOBS_ARR_NAME_IN_JSON);
+ cJSON *jobArr = cJSON_GetObjectItemCaseSensitive(fileRoot, JOBS_ARR_NAME_IN_JSON);
if (!cJSON_IsArray(jobArr)) {
INIT_LOGE("ParseAllJobs, job item is not array!");
return;
@@ -125,13 +102,13 @@ void ParseAllJobs(const cJSON* fileRoot)
return;
}
- Job* retJobs = (Job*)realloc(g_jobs, sizeof(Job) * (g_jobCnt + jobArrSize));
+ Job *retJobs = (Job *)realloc(g_jobs, sizeof(Job) * (g_jobCnt + jobArrSize));
if (retJobs == NULL) {
INIT_LOGE("ParseAllJobs, malloc failed! job arrSize %d.", jobArrSize);
return;
}
- Job* tmp = retJobs + g_jobCnt;
+ Job *tmp = retJobs + g_jobCnt;
if (memset_s(tmp, sizeof(Job) * jobArrSize, 0, sizeof(Job) * jobArrSize) != EOK) {
INIT_LOGE("ParseAllJobs, memset_s failed.");
free(retJobs);
@@ -140,14 +117,14 @@ void ParseAllJobs(const cJSON* fileRoot)
}
for (int i = 0; i < jobArrSize; ++i) {
- cJSON* jobItem = cJSON_GetArrayItem(jobArr, i);
+ cJSON *jobItem = cJSON_GetArrayItem(jobArr, i);
ParseJob(jobItem, &(tmp[i]));
}
g_jobs = retJobs;
g_jobCnt += jobArrSize;
}
-void DoJob(const char* jobName)
+void DoJob(const char *jobName)
{
if (jobName == NULL) {
INIT_LOGE("DoJob, input jobName NULL!");
@@ -157,9 +134,12 @@ void DoJob(const char* jobName)
INIT_LOGD("Call job with name %s", jobName);
for (int i = 0; i < g_jobCnt; ++i) {
if (strncmp(jobName, g_jobs[i].name, strlen(g_jobs[i].name)) == 0) {
- CmdLine* cmdLines = g_jobs[i].cmdLines;
- for (int j = 0; j < g_jobs[i].cmdLinesCnt; ++j) {
- DoCmd(&(cmdLines[j]));
+ CmdLines *cmdLines = g_jobs[i].cmdLines;
+ if (cmdLines == NULL) {
+ continue;
+ }
+ for (int j = 0; j < cmdLines->cmdNum; ++j) {
+ DoCmdByIndex(cmdLines->cmds[j].cmdIndex, cmdLines->cmds[j].cmdContent);
}
}
}
@@ -174,13 +154,10 @@ void ReleaseAllJobs(void)
for (int i = 0; i < g_jobCnt; ++i) {
if (g_jobs[i].cmdLines != NULL) {
free(g_jobs[i].cmdLines);
- g_jobs[i].cmdLines = NULL;
- g_jobs[i].cmdLinesCnt = 0;
}
}
free(g_jobs);
g_jobs = NULL;
g_jobCnt = 0;
-}
-
+}
\ No newline at end of file
diff --git a/services/init/lite/init_reboot.c b/services/init/lite/init_reboot.c
new file mode 100755
index 0000000..b041723
--- /dev/null
+++ b/services/init/lite/init_reboot.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include
+#include
+#include
+#include
+
+#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;
+}
diff --git a/services/init/lite/init_service.c b/services/init/lite/init_service.c
new file mode 100755
index 0000000..2395e1a
--- /dev/null
+++ b/services/init/lite/init_service.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "init_service.h"
+
+#include
+#include
+#include
+#include
+
+#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
diff --git a/services/init/lite/init_signal_handler.c b/services/init/lite/init_signal_handler.c
new file mode 100755
index 0000000..f78d407
--- /dev/null
+++ b/services/init/lite/init_signal_handler.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include
+#include
+#include
+
+#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
diff --git a/services/include/init_read_cfg.h b/services/init/main.c
old mode 100644
new mode 100755
similarity index 50%
rename from services/include/init_read_cfg.h
rename to services/init/main.c
index 4cb57e1..e97e11e
--- a/services/include/init_read_cfg.h
+++ b/services/init/main.c
@@ -12,26 +12,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include
+#include "init.h"
+#include "init_log.h"
-#ifndef BASE_STARTUP_INITLITE_READ_CFG_H
-#define BASE_STARTUP_INITLITE_READ_CFG_H
-
-#ifdef __cplusplus
-#if __cplusplus
-extern "C" {
-#endif
-#endif
-#define INIT_CONFIGURATION_FILE "/etc/init.cfg"
-#define MAX_PATH_ARGS_CNT 20
-#define MAX_ONE_ARG_LEN 200 // max length of one param/path
-
-void InitReadCfg();
-void ParseInitCfg(const char *configFile);
-
-#ifdef __cplusplus
-#if __cplusplus
+static const pid_t INIT_PROCESS_PID = 1;
+int main(int argc, char* const argv[])
+{
+ int isSecondStage = 0;
+ if (argc == 2 && (strcmp(argv[1], "--second-stage") == 0)) {
+ isSecondStage = 1;
+ }
+ if (getpid() != INIT_PROCESS_PID) {
+ INIT_LOGE("Process id error %d!", getpid());
+ return 0;
+ }
+ LogInit();
+ if (isSecondStage == 0) {
+ SystemPrepare();
+ }
+ SystemInit();
+ SystemExecuteRcs();
+ SystemConfig();
+ SystemRun();
+ return 0;
}
-#endif
-#endif
-
-#endif // BASE_STARTUP_INITLITE_READ_CFG_H
diff --git a/services/src/device.c b/services/init/standard/device.c
old mode 100644
new mode 100755
similarity index 91%
rename from services/src/device.c
rename to services/init/standard/device.c
index 43ec88a..1a548f5
--- a/services/src/device.c
+++ b/services/init/standard/device.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -12,14 +12,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#include "device.h"
+
#include
#include
#include
#include
#include
#include
+
#include "init_log.h"
#define DEFAULT_RW_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
@@ -62,9 +63,6 @@ void MountBasicFs(void)
void CreateDeviceNode(void)
{
- if (mknod("/dev/kmsg", S_IFCHR | DEFAULT_NO_AUTHORITY_MODE, makedev(MEM_MAJOR, DEV_KMSG_MINOR)) != 0) {
- INIT_LOGE("Create /dev/kmsg device node failed. %s", strerror(errno));
- }
if (mknod("/dev/null", S_IFCHR | DEFAULT_RW_MODE, makedev(MEM_MAJOR, DEV_NULL_MINOR)) != 0) {
INIT_LOGE("Create /dev/null device node failed. %s", strerror(errno));
}
diff --git a/services/init/standard/init.c b/services/init/standard/init.c
new file mode 100755
index 0000000..65aea93
--- /dev/null
+++ b/services/init/standard/init.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "init.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "device.h"
+#include "init_log.h"
+#include "init_mount.h"
+#include "init_param.h"
+#include "init_utils.h"
+#include "securec.h"
+#include "switch_root.h"
+
+void SystemInit(void)
+{
+ SignalInit();
+ MakeDirRecursive("/dev/unix/socket", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+}
+
+void LogInit(void)
+{
+ CloseStdio();
+ int ret = mknod("/dev/kmsg", S_IFCHR | S_IWUSR | S_IRUSR,
+ makedev(MEM_MAJOR, DEV_KMSG_MINOR));
+ if (ret == 0) {
+ OpenLogDevice();
+ }
+}
+
+static pid_t StartUeventd(void)
+{
+ char *const argv[] = {
+ "/bin/ueventd",
+ NULL,
+ };
+ pid_t pid = fork();
+ if (pid < 0) {
+ INIT_LOGE("Failed to fork child process");
+ }
+ if (pid == 0) {
+ if (execv(argv[0], argv) != 0) {
+ INIT_LOGE("service %s execve failed! err %d.", argv[0], errno);
+ }
+ _exit(0x7f); // 0x7f: user specified
+ }
+ return pid;
+}
+
+static void StartInitSecondStage(void)
+{
+ pid_t ueventPid = StartUeventd();
+ if (ueventPid < 0) {
+ INIT_LOGE("Failed to start ueventd");
+ abort();
+ }
+ if (MountRequriedPartitions() < 0) {
+ // If mount required partitions failure.
+ // There is no necessary to continue.
+ // Just abort
+ INIT_LOGE("Mount requried partitions failed");
+ abort();
+ }
+ // Kill ueventd, because init second stage will start it again.
+ (void)kill(ueventPid, SIGKILL);
+ // The init process in ramdisk has done its job.
+ // It's ready to switch to system partition.
+ // The system partition mounted in first stage to /usr
+ // Because the directory /system is in use. we cannot use it.
+ // After switch root. /usr will become new root.
+ SwitchRoot("/usr");
+ // Execute init second stage
+ char *const args[] = {
+ "/bin/init",
+ "--second-stage",
+ NULL,
+ };
+ if (execv("/bin/init", args) != 0) {
+ INIT_LOGE("Failed to exec \"/bin/init\", err = %d", errno);
+ exit(-1);
+ }
+}
+
+void SystemPrepare(void)
+{
+ MountBasicFs();
+ // Make sure init log always output to /dev/kmsg.
+ EnableDevKmsg();
+ CreateDeviceNode();
+ // Only ohos normal system support
+ // two stages of init.
+ // If we are in updater mode, only one stage of init,
+ if (InUpdaterMode() == 0) {
+ StartInitSecondStage();
+ }
+}
+
+void SystemConfig(void)
+{
+ InitParamService();
+ // parse parameters
+ LoadDefaultParams("/system/etc/param/ohos_const", LOAD_PARAM_NORMAL);
+ LoadDefaultParams("/vendor/etc/param", LOAD_PARAM_NORMAL);
+ LoadDefaultParams("/system/etc/param", LOAD_PARAM_ONLY_ADD);
+
+ // read config
+ ReadConfig();
+ INIT_LOGI("Parse init config file done.");
+
+ // dump config
+#ifdef OHOS_SERVICE_DUMP
+ DumpAllServices();
+ DumpParametersAndTriggers();
+#endif
+
+ // execute init
+ PostTrigger(EVENT_TRIGGER_BOOT, "pre-init", strlen("pre-init"));
+ PostTrigger(EVENT_TRIGGER_BOOT, "init", strlen("init"));
+ PostTrigger(EVENT_TRIGGER_BOOT, "post-init", strlen("post-init"));
+}
+
+void SystemRun(void)
+{
+ StartParamService();
+}
diff --git a/services/init/standard/init_cmds.c b/services/init/standard/init_cmds.c
new file mode 100755
index 0000000..df90153
--- /dev/null
+++ b/services/init/standard/init_cmds.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "init_cmds.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "init.h"
+#include "init_jobs.h"
+#include "init_log.h"
+#include "init_param.h"
+#include "init_service_manager.h"
+#include "init_utils.h"
+#include "fs_manager/fs_manager.h"
+#include "securec.h"
+
+int GetParamValue(const char *symValue, unsigned int symLen, char *paramValue, unsigned int paramLen)
+{
+ if ((symValue == NULL) || (paramValue == NULL) || (paramLen == 0)) {
+ return -1;
+ }
+ char tmpName[PARAM_NAME_LEN_MAX] = { 0 };
+ int ret = 0;
+ uint32_t curr = 0;
+ char *start = (char *)symValue;
+ char *end = (char *)symValue + symLen;
+ do {
+ char *begin = strchr(start, '$');
+ if (begin == NULL || begin >= end) { // not has '$' copy the original string
+ ret = strncpy_s(paramValue + curr, paramLen - curr, start, symLen);
+ INIT_ERROR_CHECK(ret == EOK, return -1, "Failed to copy start %s", start);
+ break;
+ } else {
+ ret = memcpy_s(paramValue + curr, paramLen - curr, start, begin - start);
+ INIT_ERROR_CHECK(ret == 0, return -1, "Failed to copy first value %s", symValue);
+ curr += begin - start;
+ }
+ while (*begin != '{') {
+ begin++;
+ }
+ begin++;
+ char *left = strchr(begin, '}');
+ if (left == NULL) {
+ return -1;
+ }
+ // copy param name
+ ret = strncpy_s(tmpName, PARAM_NAME_LEN_MAX, begin, left - begin);
+ INIT_ERROR_CHECK(ret == EOK, return -1, "Invalid param name %s", symValue);
+ uint32_t valueLen = paramLen - curr;
+ ret = SystemReadParam(tmpName, paramValue + curr, &valueLen);
+ INIT_ERROR_CHECK(ret == 0, return -1, "Failed to get param %s", tmpName);
+ curr += valueLen;
+ left++;
+ if ((unsigned int)(left - symValue) >= symLen) {
+ break;
+ }
+ start = left;
+ } while (1);
+ return 0;
+}
+
+static void DoIfup(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ struct ifreq interface;
+ if (strncpy_s(interface.ifr_name, IFNAMSIZ - 1, ctx->argv[0], strlen(ctx->argv[0])) != EOK) {
+ INIT_LOGE("DoIfup failed to copy interface name");
+ return;
+ }
+
+ INIT_LOGD("interface name: %s", interface.ifr_name);
+ int fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ INIT_LOGE("DoIfup failed to create socket, err = %d", errno);
+ return;
+ }
+
+ if (ioctl(fd, SIOCGIFFLAGS, &interface) >= 0) {
+ interface.ifr_flags |= IFF_UP;
+ if (ioctl(fd, SIOCSIFFLAGS, &interface) < 0) {
+ INIT_LOGE("DoIfup failed to do ioctl with command \"SIOCSIFFLAGS\", err = %d", errno);
+ }
+ }
+ close(fd);
+}
+
+// format insmod [-f] [options]
+static void DoInsmod(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ int index = 0;
+ int flags = 0;
+ char *fileName = NULL;
+ if (ctx->argc > index) {
+ fileName = ctx->argv[index];
+ index++;
+ }
+ INIT_ERROR_CHECK(fileName != NULL, return, "Can not find file name from param %s", cmdContent);
+ INIT_LOGD("Install mode %s ", fileName);
+ char *realPath = GetRealPath(fileName);
+ INIT_ERROR_CHECK(realPath != NULL, return, "Can not get real file name from param %s", cmdContent);
+ if (ctx->argc > 1 && ctx->argv[1] != NULL && strcmp(ctx->argv[1], "-f") == 0) { // [-f]
+ flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS;
+ index++;
+ }
+ char *options = BuildStringFromCmdArg(ctx, index); // [options]
+ int fd = open(realPath, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
+ if (fd >= 0) {
+ int rc = syscall(__NR_finit_module, fd, options, flags);
+ if (rc == -1) {
+ INIT_LOGE("Failed to install mode for %s failed options %s err: %d", realPath, options, errno);
+ }
+ }
+ if (options != NULL) {
+ free(options);
+ }
+ if (fd >= 0) {
+ close(fd);
+ }
+ free(realPath);
+ return;
+}
+
+static void DoSetParam(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ INIT_LOGD("set param name: %s, value %s ", ctx->argv[0], ctx->argv[1]);
+ SystemWriteParam(ctx->argv[0], ctx->argv[1]);
+}
+
+static void DoLoadPersistParams(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(ctx);
+ INIT_LOGD("load persist params : %s", cmdContent);
+ LoadPersistParams();
+}
+
+static void DoTriggerCmd(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(ctx);
+ INIT_LOGD("DoTrigger :%s", cmdContent);
+ DoTriggerExec(cmdContent);
+}
+
+static void DoLoadDefaultParams(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ int mode = 0;
+ if (ctx->argc > 1 && strcmp(ctx->argv[1], "onlyadd") == 0) {
+ mode = LOAD_PARAM_ONLY_ADD;
+ }
+ INIT_LOGD("DoLoadDefaultParams args : %s %d", cmdContent, mode);
+ LoadDefaultParams(ctx->argv[0], mode);
+}
+
+static void DoExec(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ UNUSED(ctx);
+ // format: exec /xxx/xxx/xxx xxx
+ pid_t pid = fork();
+ if (pid < 0) {
+ INIT_LOGE("DoExec: failed to fork child process to exec \"%s\"", cmdContent);
+ return;
+ }
+ if (pid == 0) {
+ const struct CmdArgs *subCtx = GetCmdArg(cmdContent, " ", SUPPORT_MAX_ARG_FOR_EXEC);
+ if (subCtx == NULL || subCtx->argv[0] == NULL) {
+ INIT_LOGE("DoExec: invalid arguments :%s", cmdContent);
+ _exit(0x7f);
+ }
+ int ret = execv(subCtx->argv[0], subCtx->argv);
+ if (ret == -1) {
+ INIT_LOGE("DoExec: execute \"%s\" failed: %d.", cmdContent, errno);
+ }
+ FreeCmdArg((struct CmdArgs *)subCtx);
+ _exit(0x7f);
+ }
+ return;
+}
+
+static void DoSymlink(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ // format: symlink /xxx/xxx/xxx /xxx/xxx/xxx
+ int ret = symlink(ctx->argv[0], ctx->argv[1]);
+ if (ret != 0 && errno != EEXIST) {
+ INIT_LOGE("DoSymlink: link %s to %s failed: %d", ctx->argv[0], ctx->argv[1], errno);
+ }
+}
+
+static mode_t GetDeviceMode(const char *deviceStr)
+{
+ switch (*deviceStr) {
+ case 'b':
+ case 'B':
+ return S_IFBLK;
+ case 'c':
+ case 'C':
+ return S_IFCHR;
+ case 'f':
+ case 'F':
+ return S_IFIFO;
+ default:
+ return -1;
+ }
+}
+
+static void DoMakeNode(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ // format: mknod path b 0644 1 9
+ const int deviceTypePos = 1;
+ const int authorityPos = 2;
+ const int majorDevicePos = 3;
+ const int minorDevicePos = 4;
+ const int decimal = 10;
+ const int octal = 8;
+ if (!access(ctx->argv[1], F_OK)) {
+ INIT_LOGE("DoMakeNode failed, path has not sexisted");
+ return;
+ }
+ mode_t deviceMode = GetDeviceMode(ctx->argv[deviceTypePos]);
+ errno = 0;
+ unsigned int major = strtoul(ctx->argv[majorDevicePos], NULL, decimal);
+ INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[majorDevicePos]);
+ unsigned int minor = strtoul(ctx->argv[minorDevicePos], NULL, decimal);
+ INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[minorDevicePos]);
+ mode_t authority = strtoul(ctx->argv[authorityPos], NULL, octal);
+ INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[authorityPos]);
+ int ret = mknod(ctx->argv[0], deviceMode | authority, makedev(major, minor));
+ if (ret != 0) {
+ INIT_LOGE("DoMakeNode: path: %s failed: %d", ctx->argv[0], errno);
+ }
+}
+
+static void DoMakeDevice(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ // format: makedev major minor
+ const int decimal = 10;
+ errno = 0;
+ unsigned int major = strtoul(ctx->argv[0], NULL, decimal);
+ INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[0]);
+ unsigned int minor = strtoul(ctx->argv[1], NULL, decimal);
+ INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[1]);
+ dev_t deviceId = makedev(major, minor);
+ if (deviceId < 0) {
+ INIT_LOGE("DoMakedevice \" %s \" failed :%d ", cmdContent, errno);
+ }
+}
+
+static void DoMountFstabFile(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ INIT_LOGI("Mount partitions from fstab file \" %s \"", ctx->argv[0]);
+ int rc = MountAllWithFstabFile(ctx->argv[0], 0);
+ if (rc < 0) {
+ INIT_LOGE("Run command mount_fstab failed");
+ } else {
+ INIT_LOGI("Mount partitions from fstab done");
+ }
+}
+
+static void DoUmountFstabFile(const struct CmdArgs *ctx, const char *cmdContent)
+{
+ UNUSED(cmdContent);
+ INIT_LOGI("Umount partitions from fstab file \" %s \"", ctx->argv[0]);
+ int rc = UmountAllWithFstabFile(ctx->argv[0]);
+ if (rc < 0) {
+ INIT_LOGE("Run command umount_fstab failed");
+ } else {
+ INIT_LOGI("Umount partitions from fstab done");
+ }
+}
+
+static const struct CmdTable CMD_TABLE[] = {
+ { "exec ", 1, 10, DoExec },
+ { "mknode ", 1, 5, DoMakeNode },
+ { "makedev ", 2, 2, DoMakeDevice },
+ { "symlink ", 2, 2, DoSymlink },
+ { "trigger ", 1, 1, DoTriggerCmd },
+ { "insmod ", 1, 10, DoInsmod },
+ { "setparam ", 2, 2, DoSetParam },
+ { "load_persist_params ", 1, 1, DoLoadPersistParams },
+ { "load_param ", 1, 2, DoLoadDefaultParams },
+ { "ifup ", 1, 1, DoIfup },
+ { "mount_fstab ", 1, 1, DoMountFstabFile },
+ { "umount_fstab ", 1, 1, DoUmountFstabFile },
+};
+
+const struct CmdTable *GetCmdTable(int *number)
+{
+ *number = (int)ARRAY_LENGTH(CMD_TABLE);
+ return CMD_TABLE;
+}
diff --git a/services/include/init_reboot.h b/services/init/standard/init_jobs.c
old mode 100644
new mode 100755
similarity index 73%
rename from services/include/init_reboot.h
rename to services/init/standard/init_jobs.c
index 181d811..18d3ff1
--- a/services/include/init_reboot.h
+++ b/services/init/standard/init_jobs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -13,9 +13,10 @@
* limitations under the License.
*/
-#ifndef INIT_REBOOT_H
-#define INIT_REBOOT_H
+#include "init_jobs.h"
+#include "init_param.h"
-void DoReboot(const char *value);
-
-#endif
+void ParseAllJobs(const cJSON *fileRoot)
+{
+ ParseTriggerConfig(fileRoot);
+}
\ No newline at end of file
diff --git a/services/init/standard/init_mount.c b/services/init/standard/init_mount.c
new file mode 100755
index 0000000..f608c75
--- /dev/null
+++ b/services/init/standard/init_mount.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "device.h"
+#include "fs_manager/fs_manager.h"
+#include "init.h"
+#include "init_cmds.h"
+#include "init_log.h"
+#include "securec.h"
+
+// This function will malloc memory.
+// Do not forget to free it after used.
+static char *GetExpandFileName(const char *fileName)
+{
+ if (fileName == NULL) {
+ return NULL;
+ }
+ size_t expandSize = strlen(fileName) + PARAM_VALUE_LEN_MAX + 1;
+ char *expandName = (char *)calloc(sizeof(char), expandSize);
+ if (expandName == NULL) {
+ INIT_LOGE("Failed to allocate memory for file name \" %s \"", fileName);
+ return NULL;
+ }
+ int ret = GetParamValue(fileName, strlen(fileName), expandName, expandSize);
+ INIT_ERROR_CHECK(ret == 0, free(expandName);
+ return NULL, "Failed to get value for %s", fileName);
+ return expandName;
+}
+
+int MountRequriedPartitions(void)
+{
+ const char *fstabFiles[] = {"/etc/fstab.required", NULL};
+ int i = 0;
+ int rc = -1;
+ while (fstabFiles[i] != NULL) {
+ char *fstabFile = GetExpandFileName(fstabFiles[i]);
+ if (fstabFile != NULL) {
+ if (access(fstabFile, F_OK) == 0) {
+ INIT_LOGI("Mount required partition from %s", fstabFile);
+ rc = MountAllWithFstabFile(fstabFile, 1);
+ } else {
+ INIT_LOGE("Cannot access fstab file \" %s \"", fstabFile);
+ }
+ free(fstabFile);
+ fstabFile = NULL;
+ }
+ if (rc == 0) {
+ break;
+ }
+ i++;
+ }
+ return rc;
+}
\ No newline at end of file
diff --git a/services/include/init_import.h b/services/init/standard/init_mount.h
old mode 100644
new mode 100755
similarity index 80%
rename from services/include/init_import.h
rename to services/init/standard/init_mount.h
index 5def1ef..a2f9a3f
--- a/services/include/init_import.h
+++ b/services/init/standard/init_mount.h
@@ -12,10 +12,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#ifndef BASE_STARTUP_INITLITE_IMPORT_H
-#define BASE_STARTUP_INITLITE_IMPORT_H
-#include "cJSON.h"
-void ParseAllImports(const cJSON *root);
-
-#endif
+#ifndef BASE_STARTUP_INITLITE_MOUNT_H
+#define BASE_STARTUP_INITLITE_MOUNT_H
+int MountRequriedPartitions(void);
+#endif
\ No newline at end of file
diff --git a/services/init/standard/init_reboot.c b/services/init/standard/init_reboot.c
new file mode 100755
index 0000000..0d44131
--- /dev/null
+++ b/services/init/standard/init_reboot.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include
+#include
+#include
+#include
+#include
+
+#include "init_log.h"
+#include "init_service.h"
+#include "init_service_manager.h"
+#include "init_utils.h"
+#include "securec.h"
+
+#define MAX_VALUE_LENGTH 500
+#define MAX_COMMAND_SIZE 20
+#define MAX_UPDATE_SIZE 100
+
+struct RBMiscUpdateMessage {
+ char command[MAX_COMMAND_SIZE];
+ char update[MAX_UPDATE_SIZE];
+};
+
+static int RBMiscWriteUpdaterMessage(const char *path, const struct RBMiscUpdateMessage *boot)
+{
+ char *realPath = GetRealPath(path);
+ if (realPath == NULL) {
+ return -1;
+ }
+ int ret = 0;
+ FILE *fp = fopen(realPath, "rb+");
+ if (fp != NULL) {
+ size_t writeLen = fwrite(boot, sizeof(struct RBMiscUpdateMessage), 1, fp);
+ if (writeLen != 1) {
+ INIT_LOGE("Failed to write misc for reboot");
+ ret = -1;
+ }
+ } else {
+ ret = -1;
+ INIT_LOGE("Failed to open %s", path);
+ }
+ free(realPath);
+ realPath = NULL;
+ (void)fclose(fp);
+ return ret;
+}
+
+static int RBMiscReadUpdaterMessage(const char *path, struct RBMiscUpdateMessage *boot)
+{
+ char *realPath = GetRealPath(path);
+ if (realPath == NULL) {
+ return -1;
+ }
+
+ int ret = 0;
+ FILE *fp = fopen(realPath, "rb");
+ if (fp != NULL) {
+ size_t readLen = fread(boot, 1, sizeof(struct RBMiscUpdateMessage), fp);
+ if (readLen <= 0) {
+ ret = -1;
+ INIT_LOGE("Failed to read misc for reboot");
+ }
+ } else {
+ ret = -1;
+ INIT_LOGE("Failed to open %s", path);
+ }
+ free(realPath);
+ realPath = NULL;
+ (void)fclose(fp);
+ return ret;
+}
+
+static int GetMountStatusForMountPoint(const char *mountPoint)
+{
+ const int bufferMaxSize = 512;
+ char buffer[bufferMaxSize];
+ size_t n;
+ const char *mountFile = "/proc/mounts";
+ FILE *fp = fopen(mountFile, "r");
+ if (fp == NULL) {
+ return 1;
+ }
+
+ while (fgets(buffer, sizeof(buffer) - 1, fp) != NULL) {
+ n = strlen(buffer);
+ if (buffer[n - 1] == '\n') {
+ buffer[n - 1] = '\0';
+ }
+ if (strstr(buffer, mountPoint) != NULL) {
+ (void)fclose(fp);
+ return 1;
+ }
+ }
+ (void)fclose(fp);
+ return 0;
+}
+
+static int CheckAndRebootToUpdater(const char *valueData, const char *cmd, const char *cmdExt, const char *boot)
+{
+ // "updater" or "updater:"
+ const char *miscFile = "/dev/block/platform/soc/10100000.himci.eMMC/by-name/misc";
+ struct RBMiscUpdateMessage msg;
+ int ret = RBMiscReadUpdaterMessage(miscFile, &msg);
+ INIT_ERROR_CHECK(ret == 0, return -1, "Failed to get misc info for %s.", cmd);
+
+ if (boot != NULL) {
+ ret = snprintf_s(msg.command, MAX_COMMAND_SIZE, MAX_COMMAND_SIZE - 1, "%s", boot);
+ INIT_ERROR_CHECK(ret > 0, return -1, "Failed to format cmd for %s.", cmd);
+ msg.command[MAX_COMMAND_SIZE - 1] = 0;
+ } else {
+ ret = memset_s(msg.command, MAX_COMMAND_SIZE, 0, MAX_COMMAND_SIZE);
+ INIT_ERROR_CHECK(ret == 0, return -1, "Failed to format cmd for %s.", cmd);
+ }
+
+ if ((cmdExt != NULL) && (valueData != NULL) && (strncmp(valueData, cmdExt, strlen(cmdExt)) == 0)) {
+ const char *p = valueData + strlen(cmdExt);
+ ret = snprintf_s(msg.update, MAX_UPDATE_SIZE, MAX_UPDATE_SIZE - 1, "%s", p);
+ INIT_ERROR_CHECK(ret > 0, return -1, "Failed to format param for %s.", cmd);
+ msg.update[MAX_UPDATE_SIZE - 1] = 0;
+ }
+
+ if (RBMiscWriteUpdaterMessage(miscFile, &msg) == 0) {
+ return reboot(RB_AUTOBOOT);
+ }
+ return -1;
+}
+
+static int CheckRebootParam(const char *valueData)
+{
+ if (valueData == NULL) {
+ return 0;
+ }
+ static const char *cmdParams[] = {
+ "shutdown", "updater", "updater:", "flash", "flash:", "NoArgument", "bootloader"
+ };
+ size_t i = 0;
+ for (; i < ARRAY_LENGTH(cmdParams); i++) {
+ if (strncmp(valueData, cmdParams[i], strlen(cmdParams[i])) == 0) {
+ break;
+ }
+ }
+ if (i >= ARRAY_LENGTH(cmdParams)) {
+ return -1;
+ }
+ return 0;
+}
+
+void ExecReboot(const char *value)
+{
+ INIT_ERROR_CHECK(value != NULL && strlen(value) <= MAX_VALUE_LENGTH, return, "Invalid arg");
+ const char *valueData = NULL;
+ if (strncmp(value, "reboot,", strlen("reboot,")) == 0) {
+ valueData = value + strlen("reboot,");
+ } else if (strcmp(value, "reboot") != 0) {
+ INIT_LOGE("Reboot value = %s, must started with reboot", value);
+ return;
+ }
+ if (CheckRebootParam(valueData) != 0) {
+ INIT_LOGE("Invalid arg %s for reboot.", value);
+ return;
+ }
+
+ StopAllServices(SERVICE_ATTR_INVALID);
+ sync();
+ if (GetMountStatusForMountPoint("/vendor") != 0 && umount("/vendor") != 0) {
+ INIT_LOGE("Failed to umount vendor. errno = %d.", errno);
+ }
+ if (GetMountStatusForMountPoint("/data") != 0) {
+ if (umount("/data") != 0 && umount2("/data", MNT_FORCE) != 0) {
+ INIT_LOGE("Failed umount data. errno = %d.", errno);
+ }
+ } else {
+ INIT_LOGE("Failed to get mount point \"/data\"");
+ }
+
+ int ret = 0;
+ if (valueData == NULL) {
+ ret = CheckAndRebootToUpdater(NULL, "reboot", NULL, NULL);
+ } else if (strcmp(valueData, "shutdown") == 0) {
+ ret = reboot(RB_POWER_OFF);
+ } else if (strcmp(valueData, "bootloader") == 0) {
+ ret = reboot(RB_POWER_OFF);
+ } else if (strncmp(valueData, "updater", strlen("updater")) == 0) {
+ ret = CheckAndRebootToUpdater(valueData, "updater", "updater:", "boot_updater");
+ } else if (strncmp(valueData, "flash", strlen("flash")) == 0) {
+ ret = CheckAndRebootToUpdater(valueData, "flash", "flash:", "boot_flash");
+ }
+ INIT_LOGI("Reboot %s %s.", value, (ret == 0) ? "success" : "fail");
+ return;
+}
diff --git a/services/init/standard/init_service.c b/services/init/standard/init_service.c
new file mode 100755
index 0000000..533addb
--- /dev/null
+++ b/services/init/standard/init_service.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "init_service.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include "init.h"
+#include "init_log.h"
+#include "init_param.h"
+#include "securec.h"
+
+#define MIN_IMPORTANT_LEVEL (-20)
+#define MAX_IMPORTANT_LEVEL 19
+
+void NotifyServiceChange(const char *serviceName, const char *change)
+{
+ char paramName[PARAM_NAME_LEN_MAX] = { 0 };
+ if (snprintf_s(paramName, PARAM_NAME_LEN_MAX, PARAM_NAME_LEN_MAX - 1, "init.svc.%s", serviceName) < 0) {
+ INIT_LOGE("snprintf_s paramName error %d ", errno);
+ }
+ SystemWriteParam(paramName, change);
+}
+
+int IsForbidden(const char *fieldStr)
+{
+ UNUSED(fieldStr);
+ return 0;
+}
+
+int SetImportantValue(Service *service, const char *attrName, int value, int flag)
+{
+ UNUSED(attrName);
+ UNUSED(flag);
+ INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Set service attr failed! null ptr.");
+ if (value >= MIN_IMPORTANT_LEVEL && value <= MAX_IMPORTANT_LEVEL) { // -20~19
+ service->attribute |= SERVICE_ATTR_IMPORTANT;
+ service->importance = value;
+ } else {
+ INIT_LOGE("Importance level = %d, is not between -20 and 19, error", value);
+ return SERVICE_FAILURE;
+ }
+ return SERVICE_SUCCESS;
+}
+
+int ServiceExec(const Service *service)
+{
+ INIT_ERROR_CHECK(service != NULL && service->pathArgs.count > 0,
+ return SERVICE_FAILURE, "Exec service failed! null ptr.");
+ if (service->importance != 0) {
+ if (setpriority(PRIO_PROCESS, 0, service->importance) != 0) {
+ INIT_LOGE("setpriority failed for %s, importance = %d", service->name, service->importance);
+ _exit(0x7f); // 0x7f: user specified
+ }
+ }
+ // L2 Can not be reset env
+ if (execv(service->pathArgs.argv[0], service->pathArgs.argv) != 0) {
+ INIT_LOGE("service %s execve failed! err %d.", service->name, errno);
+ }
+ return SERVICE_SUCCESS;
+}
\ No newline at end of file
diff --git a/services/src/init_signal_handler.c b/services/init/standard/init_signal_handler.c
old mode 100644
new mode 100755
similarity index 62%
rename from services/src/init_signal_handler.c
rename to services/init/standard/init_signal_handler.c
index 81fdf42..9f70ada
--- a/services/src/init_signal_handler.c
+++ b/services/init/standard/init_signal_handler.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
+ * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -12,45 +12,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#include "init_signal_handler.h"
-
#include
#include
#include
-#ifdef __LINUX__
-#include
-#include
-#endif /* __LINUX__ */
+#include "init_adapter.h"
#include "init_log.h"
#include "init_service_manager.h"
-
-#ifndef OHOS_LITE
#include "uv.h"
-#endif
-#ifdef __LINUX__
-static pid_t g_waitPid = -1;
-static sem_t* g_waitSem = NULL;
-
-void SignalRegWaitSem(pid_t waitPid, sem_t* waitSem)
-{
- g_waitPid = waitPid;
- g_waitSem = waitSem;
-}
-
-static void CheckWaitPid(pid_t sigPID)
-{
- if (g_waitPid == sigPID && g_waitSem != NULL) {
- if (sem_post(g_waitSem) != 0) {
- INIT_LOGE("CheckWaitPid, sem_post failed, errno %d.", errno);
- }
- g_waitPid = -1;
- g_waitSem = NULL;
- }
-}
-#endif /* __LINUX__ */
+uv_signal_t g_sigchldHandler;
+uv_signal_t g_sigtermHandler;
static void SigHandler(int sig)
{
@@ -63,29 +35,22 @@ static void SigHandler(int sig)
if (sigPID <= 0) {
break;
}
-
-#ifndef OHOS_LITE
// check child process exit status
if (WIFSIGNALED(procStat)) {
INIT_LOGE("Child process %d exit with signal: %d", sigPID, WTERMSIG(procStat));
}
-
if (WIFEXITED(procStat)) {
- INIT_LOGE("Child process %d exit with code : %d", sigPID, WEXITSTATUS((unsigned int)procStat));
+ INIT_LOGE("Child process %d exit with code : %d", sigPID, WEXITSTATUS(procStat));
}
-#endif
-
INIT_LOGI("SigHandler, SIGCHLD received, sigPID = %d.", sigPID);
-#ifdef __LINUX__
CheckWaitPid(sigPID);
-#endif /* __LINUX__ */
- ReapServiceByPID((int)sigPID);
+ ServiceReap(GetServiceByPid(sigPID));
}
break;
}
case SIGTERM: {
INIT_LOGI("SigHandler, SIGTERM received.");
- StopAllServices();
+ StopAllServices(0);
break;
}
default:
@@ -94,27 +59,12 @@ static void SigHandler(int sig)
}
}
-#ifdef OHOS_LITE
-void SignalInitModule()
-{
- struct sigaction act;
- act.sa_handler = SigHandler;
- act.sa_flags = SA_RESTART;
- (void)sigfillset(&act.sa_mask);
-
- sigaction(SIGCHLD, &act, NULL);
- sigaction(SIGTERM, &act, NULL);
-}
-#else // L2 or above, use signal event in libuv
-uv_signal_t g_sigchldHandler;
-uv_signal_t g_sigtermHandler;
-
-static void UVSignalHandler(uv_signal_t* handle, int signum)
+static void UVSignalHandler(uv_signal_t *handle, int signum)
{
SigHandler(signum);
}
-void SignalInitModule()
+void SignalInit(void)
{
int ret = uv_signal_init(uv_default_loop(), &g_sigchldHandler);
int ret1 = uv_signal_init(uv_default_loop(), &g_sigtermHandler);
@@ -129,5 +79,4 @@ void SignalInitModule()
if (uv_signal_start(&g_sigtermHandler, UVSignalHandler, SIGTERM) != 0) {
INIT_LOGW("start SIGTERM handler failed");
}
-}
-#endif
+}
\ No newline at end of file
diff --git a/services/init/standard/switch_root.c b/services/init/standard/switch_root.c
new file mode 100755
index 0000000..c2a5bf9
--- /dev/null
+++ b/services/init/standard/switch_root.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "switch_root.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "init_log.h"
+#include "init_utils.h"
+#include "fs_manager/fs_manager.h"
+#include "securec.h"
+
+static void FreeOldRoot(DIR *dir, dev_t dev)
+{
+ if (dir == NULL) {
+ return;
+ }
+ int dfd = dirfd(dir);
+ bool isDir = false;
+ struct dirent *de = NULL;
+ while ((de = readdir(dir)) != NULL) {
+ if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) {
+ continue;
+ }
+
+ if (de->d_type == DT_DIR || de->d_type == DT_UNKNOWN) {
+ struct stat st = {};
+ if (fstatat(dfd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
+ INIT_LOGE("Failed to get stat of %s", de->d_name);
+ continue;
+ }
+
+ if (st.st_dev != dev) {
+ continue; // Not the same device, ignore.
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ int fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
+ isDir = true;
+ if (fd >= 0) {
+ DIR *subDir = fdopendir(fd);
+ if (subDir != NULL) {
+ FreeOldRoot(subDir, dev);
+ closedir(subDir);
+ } else {
+ close(fd);
+ }
+ }
+ }
+ }
+ if (unlinkat(dfd, de->d_name, isDir ? AT_REMOVEDIR : 0) < 0) {
+ INIT_LOGE("Failed to unlink %s, err = %d", de->d_name, errno);
+ }
+ }
+}
+
+static int MountToNewTarget(const char *target)
+{
+ if (target == NULL || *target == '\0') {
+ return -1;
+ }
+ Fstab *fstab = ReadFstabFromFile("/proc/mounts", true);
+ if (fstab == NULL) {
+ INIT_LOGE("Fatal error. Read mounts info from \" /proc/mounts \" failed");
+ return -1;
+ }
+
+ for (FstabItem *item = fstab->head; item != NULL; item = item->next) {
+ const char *mountPoint = item->mountPoint;
+ if (mountPoint == NULL || strcmp(mountPoint, "/") == 0 ||
+ strcmp(mountPoint, target) == 0) {
+ continue;
+ }
+ char newMountPoint[PATH_MAX] = {0};
+ if (snprintf_s(newMountPoint, PATH_MAX, PATH_MAX - 1, "%s%s", target, mountPoint) == -1) {
+ INIT_LOGW("Cannot build new mount point for old mount point \" %s \"", mountPoint);
+ // Just ignore this one or return error?
+ continue;
+ }
+ INIT_LOGI("new mount point is: %s", newMountPoint);
+ if (mount(mountPoint, newMountPoint, NULL, MS_MOVE, NULL) < 0) {
+ INIT_LOGE("Failed to mount moving %s to %s, err = %d", mountPoint, newMountPoint, errno);
+ // If one mount entry cannot move to new mountpoint, umount it.
+ umount2(mountPoint, MNT_FORCE);
+ continue;
+ }
+ }
+ ReleaseFstab(fstab);
+ fstab = NULL;
+ return 0;
+}
+
+// Switch root from ramdisk to system
+int SwitchRoot(const char *newRoot)
+{
+ if (newRoot == NULL || *newRoot == '\0') {
+ errno = EINVAL;
+ INIT_LOGE("Fatal error. Try to switch to new root with invalid new mount point");
+ return -1;
+ }
+
+ struct stat oldRootStat = {};
+ if (stat("/", &oldRootStat) != 0) {
+ INIT_LOGE("Failed to get old root \"/\" stat");
+ return -1;
+ }
+ DIR *oldRoot = opendir("/");
+ if (oldRoot == NULL) {
+ INIT_LOGE("Failed to open root dir \"/\"");
+ return -1;
+ }
+ struct stat newRootStat = {};
+ if (stat(newRoot, &newRootStat) != 0) {
+ INIT_LOGE("Failed to get new root \" %s \" stat", newRoot);
+ return -1;
+ }
+
+ if (oldRootStat.st_dev == newRootStat.st_dev) {
+ INIT_LOGW("Try to switch root in same device, skip switching root");
+ return 0;
+ }
+ if (MountToNewTarget(newRoot) < 0) {
+ INIT_LOGE("Failed to move mount to new root \" %s \" stat", newRoot);
+ return -1;
+ }
+ // OK, we've done move mount.
+ // Now mount new root.
+ if (chdir(newRoot) < 0) {
+ INIT_LOGE("Failed to change directory to %s, err = %d", newRoot, errno);
+ return -1;
+ }
+
+ if (mount(newRoot, "/", NULL, MS_MOVE, NULL) < 0) {
+ INIT_LOGE("Failed to mount moving %s to %s, err = %d", newRoot, "/", errno);
+ return -1;
+ }
+
+ if (chroot(".") < 0) {
+ INIT_LOGE("Failed to change root directory");
+ return -1;
+ }
+ FreeOldRoot(oldRoot, oldRootStat.st_dev);
+ closedir(oldRoot);
+ oldRoot = NULL;
+ return 0;
+}
diff --git a/services/log/BUILD.gn b/services/log/BUILD.gn
old mode 100644
new mode 100755
diff --git a/services/log/init_log.c b/services/log/init_log.c
old mode 100644
new mode 100755
index 36504d5..c408049
--- a/services/log/init_log.c
+++ b/services/log/init_log.c
@@ -14,7 +14,6 @@
*/
#include "init_log.h"
-
#include
#include
#include
@@ -34,22 +33,15 @@
static InitLogLevel g_logLevel = INIT_INFO;
static const char *LOG_LEVEL_STR[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" };
-void SetLogLevel(InitLogLevel logLevel)
+void SetInitLogLevel(InitLogLevel logLevel)
{
g_logLevel = logLevel;
}
#ifdef OHOS_LITE
-static LogLevel g_hiLogLevel = LOG_INFO;
-
-void SetHiLogLevel(LogLevel logLevel)
+void InitToHiLog(InitLogLevel logLevel, const char *fmt, ...)
{
- g_hiLogLevel = logLevel;
-}
-
-void InitToHiLog(LogLevel logLevel, const char *fmt, ...)
-{
- if (logLevel < g_hiLogLevel) {
+ if (logLevel < g_logLevel) {
return;
}
@@ -84,7 +76,7 @@ void EnableDevKmsg(void)
if (fd < 0) {
return;
}
- const char *kmsgStatus = "on";
+ char *kmsgStatus = "on";
write(fd, kmsgStatus, strlen(kmsgStatus) + 1);
close(fd);
fd = -1;
diff --git a/services/log/init_log.h b/services/log/init_log.h
old mode 100644
new mode 100755
index 2c0de5c..825c480
--- a/services/log/init_log.h
+++ b/services/log/init_log.h
@@ -19,13 +19,6 @@
#include
#include
#include
-#ifdef OHOS_LITE
-#include "hilog/log.h"
-#else
-#ifdef INIT_AGENT
-#include "hilog/log.h"
-#endif
-#endif
#ifdef __cplusplus
#if __cplusplus
@@ -41,6 +34,8 @@ typedef enum InitLogLevel {
INIT_FATAL
} InitLogLevel;
+void SetInitLogLevel(InitLogLevel logLevel);
+
#ifdef LABEL
#define INIT_LOG_TAG LABEL
#endif
@@ -50,22 +45,22 @@ typedef enum InitLogLevel {
#endif
#ifdef OHOS_LITE
+#include "hilog/log.h"
#undef LOG_DOMAIN
#define LOG_DOMAIN 0xD000719
-#define INIT_LOGD(fmt, ...) InitToHiLog(LOG_DEBUG, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
-#define INIT_LOGI(fmt, ...) InitToHiLog(LOG_INFO, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
-#define INIT_LOGW(fmt, ...) InitToHiLog(LOG_WARN, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
-#define INIT_LOGE(fmt, ...) InitToHiLog(LOG_ERROR, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
-#define INIT_LOGF(fmt, ...) InitToHiLog(LOG_FATAL, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
+#define INIT_LOGD(fmt, ...) InitToHiLog(INIT_DEBUG, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
+#define INIT_LOGI(fmt, ...) InitToHiLog(INIT_INFO, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
+#define INIT_LOGW(fmt, ...) InitToHiLog(INIT_WARN, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
+#define INIT_LOGE(fmt, ...) InitToHiLog(INIT_ERROR, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
+#define INIT_LOGF(fmt, ...) InitToHiLog(INIT_FATAL, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
-#define STARTUP_LOGD(LABEL, fmt, ...) InitToHiLog(LABEL, LOG_DEBUG, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
-#define STARTUP_LOGI(LABEL, fmt, ...) InitToHiLog(LABEL, LOG_INFO, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
-#define STARTUP_LOGE(LABEL, fmt, ...) InitToHiLog(LABEL, LOG_ERROR, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
+#define STARTUP_LOGD(LABEL, fmt, ...) InitToHiLog(LABEL, INIT_DEBUG, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
+#define STARTUP_LOGI(LABEL, fmt, ...) InitToHiLog(INIT_INFO, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
+#define STARTUP_LOGE(LABEL, fmt, ...) InitToHiLog(INIT_ERROR, "%s : "fmt, (__FUNCTION__), ##__VA_ARGS__)
-void InitToHiLog(LogLevel logLevel, const char *fmt, ...);
-void SetHiLogLevel(LogLevel logLevel);
+void InitToHiLog(InitLogLevel logLevel, const char *fmt, ...);
#else
#define FILE_NAME (strrchr((__FILE__), '/') ? strrchr((__FILE__), '/') + 1 : (__FILE__))
@@ -80,7 +75,11 @@ void SetHiLogLevel(LogLevel logLevel);
#define STARTUP_LOGI(LABEL, fmt, ...) InitLog(INIT_INFO, (FILE_NAME), (__LINE__), "<6>", fmt "\n", ##__VA_ARGS__)
#define STARTUP_LOGE(LABEL, fmt, ...) InitLog(INIT_ERROR, (FILE_NAME), (__LINE__), "<3>", fmt "\n", ##__VA_ARGS__)
#else
+#ifndef LABEL
+#define LABEL "ParamAgent"
+#endif
+#include "hilog/log.h"
#define PARAM_AGENT_LOG_PATH "/data/init_agent/init_agent.log"
#define STARTUP_LOGD(LABEL, fmt, ...) \
@@ -107,7 +106,6 @@ void SetHiLogLevel(LogLevel logLevel);
#endif
void InitLog(InitLogLevel logLevel, const char *fileName, int line, const char *kLevel, const char *fmt, ...);
-void SetLogLevel(InitLogLevel logLevel);
void OpenLogDevice(void);
void EnableDevKmsg(void);
#endif
diff --git a/services/param/BUILD.gn b/services/param/BUILD.gn
old mode 100644
new mode 100755
index 3249c34..ce86867
--- a/services/param/BUILD.gn
+++ b/services/param/BUILD.gn
@@ -14,6 +14,7 @@ import("//build/ohos.gni")
declare_args() {
param_security = "dac"
+ param_test = "false"
}
ohos_prebuilt_etc("param_watcher.rc") {
@@ -28,7 +29,8 @@ ohos_prebuilt_etc("param_watcher.rc") {
ohos_static_library("param_service") {
sources = [
- "//base/startup/init_lite/services/src/list.c",
+ "//base/startup/init_lite/services/utils/init_utils.c",
+ "//base/startup/init_lite/services/utils/list.c",
"adapter/param_libuvadp.c",
"adapter/param_persistadp.c",
"manager/param_manager.c",
@@ -47,6 +49,7 @@ ohos_static_library("param_service") {
"adapter",
"//base/startup/init_lite/services/include/param",
"//base/startup/init_lite/services/include",
+ "//base/startup/init_lite/services/init/include",
"//base/startup/init_lite/services/log",
"//third_party/libuv/include",
"//third_party/cJSON",
@@ -54,6 +57,10 @@ ohos_static_library("param_service") {
defines = [ "PARAM_SUPPORT_SAVE_PERSIST" ]
+ if (param_test == "true") {
+ defines += [ "PARAM_TEST" ]
+ }
+
if (param_security == "selinux") {
sources += [ "adapter/param_selinux.c" ]
defines += [ "PARAM_SUPPORT_SELINUX" ]
@@ -72,6 +79,7 @@ ohos_static_library("param_service") {
ohos_shared_library("param_client") {
sources = [
+ "//base/startup/init_lite/services/utils/init_utils.c",
"client/param_request.c",
"manager/param_manager.c",
"manager/param_message.c",
@@ -98,11 +106,19 @@ ohos_shared_library("param_client") {
defines += [ "PARAM_SUPPORT_DAC" ]
}
+ if (param_test == "true") {
+ defines += [ "PARAM_TEST" ]
+ }
+
deps = [
"//base/startup/init_lite/services/log:agent_log",
"//third_party/bounds_checking_function:libsec_static",
]
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
+ install_images = [
+ "system",
+ "updater",
+ ]
part_name = "init"
}
@@ -197,19 +213,25 @@ ohos_executable("param") {
"//base/update/updateservice/interfaces/innerkits/include",
]
- defines = [
- "PARAM_TEST",
- "INIT_AGENT",
- ]
+ defines = [ "INIT_AGENT" ]
deps = [
"//base/startup/init_lite/services/log:agent_log",
"//base/startup/init_lite/services/param:param_client",
- "//base/startup/init_lite/services/param:param_watcheragent",
- "//base/update/updateservice/interfaces/innerkits/engine:updateservicekits",
"//third_party/bounds_checking_function:libsec_static",
]
+
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
+
+ if (param_test == "true") {
+ defines += [ "PARAM_TEST" ]
+ deps += [ "//base/startup/init_lite/services/param:param_watcheragent" ]
+ } else {
+ install_images = [
+ "system",
+ "updater",
+ ]
+ }
install_enable = true
part_name = "init"
}
diff --git a/services/param/adapter/param_dac.c b/services/param/adapter/param_dac.c
index 9f59dde..8be0406 100755
--- a/services/param/adapter/param_dac.c
+++ b/services/param/adapter/param_dac.c
@@ -18,11 +18,11 @@
#include
#include
+#include "init_utils.h"
#include "param_security.h"
#include "param_utils.h"
#define OCT_BASE 8
-#define LABEL "PARAM_DAC"
static ParamSecurityLabel g_localSecurityLabel = {};
static void GetUserIdByName(FILE *fp, uid_t *uid, const char *name, uint32_t nameLen)
@@ -170,6 +170,7 @@ static int GetParamSecurityLabel(SecurityLabelFunc label, const char *path, void
if ((stat(path, &st) == 0) && !S_ISDIR(st.st_mode)) {
return ProcessParamFile(path, &cxt);
}
+ PARAM_LOGD("GetParamSecurityLabel %s ", path);
return ReadFileInDir(path, ".para.dac", ProcessParamFile, &cxt);
}
diff --git a/services/param/adapter/param_libuvadp.c b/services/param/adapter/param_libuvadp.c
index dce7492..7f4e949 100755
--- a/services/param/adapter/param_libuvadp.c
+++ b/services/param/adapter/param_libuvadp.c
@@ -15,7 +15,6 @@
#include "param_libuvadp.h"
#include
-#define LABEL "Libuvadp"
static LibuvWorkSpace libuv = { NULL };
static const uint32_t RECV_BUFFER_MAX = 5 * 1024;
diff --git a/services/param/adapter/param_persistadp.c b/services/param/adapter/param_persistadp.c
index 023130d..11a309c 100755
--- a/services/param/adapter/param_persistadp.c
+++ b/services/param/adapter/param_persistadp.c
@@ -21,8 +21,6 @@
#include "param_persist.h"
#include "param_utils.h"
-#define LABEL "PERSIST_ADP"
-
typedef struct {
void *context;
PersistParamGetPtr persistParamGet;
@@ -59,6 +57,12 @@ static int LoadPersistParam(PersistParamGetPtr persistParamGet, void *context)
return 0;
}
+static int SavePersistParam(const char *name, const char *value)
+{
+ PARAM_LOGD("SavePersistParam %s=%s", name, value);
+ return 0;
+}
+
static int BatchSavePersistParamBegin(PERSIST_SAVE_HANDLE *handle)
{
FILE *fp = fopen(PARAM_PERSIST_SAVE_TMP_PATH, "w");
@@ -88,7 +92,7 @@ static void BatchSavePersistParamEnd(PERSIST_SAVE_HANDLE handle)
int RegisterPersistParamOps(PersistParamOps *ops)
{
PARAM_CHECK(ops != NULL, return -1, "Invalid ops");
- ops->save = NULL;
+ ops->save = SavePersistParam;
ops->load = LoadPersistParam;
ops->batchSaveBegin = BatchSavePersistParamBegin;
ops->batchSave = BatchSavePersistParam;
diff --git a/services/param/adapter/param_selinux.c b/services/param/adapter/param_selinux.c
index 8b5c9d8..ecd25c8 100755
--- a/services/param/adapter/param_selinux.c
+++ b/services/param/adapter/param_selinux.c
@@ -15,10 +15,10 @@
#include
+#include "init_utils.h"
#include "param_security.h"
#include "param_utils.h"
-#define LABEL "PARAM_SELINUX"
#define SELINUX_LABEL_LEN 128
typedef struct SELinuxSecurityLabel {
ParamSecurityLabel securityLabel;
diff --git a/services/param/client/param_request.c b/services/param/client/param_request.c
old mode 100644
new mode 100755
index fba5486..b7606f8
--- a/services/param/client/param_request.c
+++ b/services/param/client/param_request.c
@@ -12,8 +12,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#include "param_request.h"
+
#include
#include
#include
@@ -26,7 +26,7 @@
#define INVALID_SOCKET (-1)
#define INIT_PROCESS_PID 1
-#define LABEL "Client"
+
static const uint32_t RECV_BUFFER_MAX = 5 * 1024;
static atomic_uint g_requestId = ATOMIC_VAR_INIT(1);
@@ -114,7 +114,7 @@ static int StartRequest(int *fd, ParamMessage *request, int timeout)
if (clientFd == INVALID_SOCKET) {
clientFd = socket(AF_UNIX, SOCK_STREAM, 0);
PARAM_CHECK(clientFd >= 0, return PARAM_CODE_FAIL_CONNECT, "Failed to create socket");
- ret = ConntectServer(clientFd, PIPE_NAME);
+ ret = ConntectServer(clientFd, CLIENT_PIPE_NAME);
PARAM_CHECK(ret == 0, close(clientFd);
return PARAM_CODE_FAIL_CONNECT, "Failed to connect server");
setsockopt(clientFd, SOL_SOCKET, SO_SNDTIMEO, (char *)&time, sizeof(struct timeval));
@@ -291,6 +291,12 @@ int SystemTraversalParameter(
void SystemDumpParameters(int verbose)
{
InitParamClient();
+ // check default dac
+ ParamHandle handle = 0;
+ int ret = ReadParamWithCheck(&g_clientSpace.paramSpace, "#", DAC_READ, &handle);
+ if (ret != PARAM_CODE_NOT_FOUND && ret != 0) {
+ PARAM_CHECK(ret == 0, return, "Forbid to dump parameters");
+ }
DumpParameters(&g_clientSpace.paramSpace, verbose);
}
@@ -308,7 +314,7 @@ int WatchParamCheck(const char *keyprefix)
return 0;
}
-#ifdef STARTUP_INIT_TEST
+#if (defined STARTUP_INIT_TEST || defined PARAM_TEST)
ParamWorkSpace *GetClientParamWorkSpace(void)
{
return &g_clientSpace.paramSpace;
diff --git a/services/param/cmd/param_cmd.c b/services/param/cmd/param_cmd.c
index 56630b2..0c46e9b 100755
--- a/services/param/cmd/param_cmd.c
+++ b/services/param/cmd/param_cmd.c
@@ -32,10 +32,10 @@
#define WAIT_TIMEOUT_INDEX 2
struct CmdArgs {
- char name[8];
+ char name[8]; // cmd name length
int minArg;
void (*DoFuncion)(int argc, char *argv[], int start);
- char help[128];
+ char help[128]; // cmd help length
};
static void ShowParam(ParamHandle handle, void *cookie)
@@ -100,17 +100,89 @@ static void ExeuteCmdParamWait(int argc, char *argv[], int start)
if (argc > (start + WAIT_TIMEOUT_INDEX)) {
timeout = atol(argv[start + WAIT_TIMEOUT_INDEX]);
}
- SystemWaitParameter(argv[start], value, timeout);
+ int ret = SystemWaitParameter(argv[start], value, timeout);
+ if (ret == 0) {
+ printf("Param wait success ");
+ } else {
+ printf("Param wait fail");
+ }
}
+#ifdef PARAM_TEST
+static void ExeuteCmdParamRead(int argc, char *argv[], int start)
+{
+ SystemSetParameter("test.randrom.test.start", "1");
+ char buffer[PARAM_NAME_LEN_MAX] = {0};
+ printf("SystemGetParameter start \n");
+ srand((unsigned)time(NULL));
+ while (1) {
+ int wait = rand() / READ_DURATION + READ_DURATION; // 100ms
+ uint32_t size = PARAM_NAME_LEN_MAX;
+ int ret = SystemGetParameter(argv[start], buffer, &size);
+ if (ret == 0) {
+ printf("SystemGetParameter value %s %d \n", buffer, wait);
+ } else {
+ printf("SystemGetParameter fail %d \n", wait);
+ }
+ usleep(wait);
+ }
+}
+
+static void HandleParamChange(const char *key, const char *value, void *context)
+{
+ if (key == NULL || value == NULL) {
+ return;
+ }
+ UNUSED(context);
+ printf("Receive parameter change %s %s \n", key, value);
+}
+
+static void ExeuteCmdParamWatch(int argc, char *argv[], int start)
+{
+ if (argc <= start) {
+ return;
+ }
+ int ret = SystemWatchParameter(argv[start], HandleParamChange, NULL);
+ if (ret != 0) {
+ return;
+ }
+ while (1) {
+ (void)pause();
+ }
+}
+#endif
+
int RunParamCommand(int argc, char *argv[])
{
static struct CmdArgs paramCmds[] = {
- { "set", 4, ExeuteCmdParamSet, USAGE_INFO_PARAM_SET },
- { "get", 2, ExeuteCmdParamGet, USAGE_INFO_PARAM_GET },
- { "wait", 3, ExeuteCmdParamWait, USAGE_INFO_PARAM_WAIT },
- { "dump", 2, ExeuteCmdParamDump, USAGE_INFO_PARAM_DUMP },
- };
+ { "set", 4, ExeuteCmdParamSet, USAGE_INFO_PARAM_SET }, // set param count
+ { "get", 2, ExeuteCmdParamGet, USAGE_INFO_PARAM_GET }, // get param count
+ { "wait", 3, ExeuteCmdParamWait, USAGE_INFO_PARAM_WAIT }, // wait param count
+ { "dump", 2, ExeuteCmdParamDump, USAGE_INFO_PARAM_DUMP }, // dump param count
+#ifdef PARAM_TEST
+ { "read", 2, ExeuteCmdParamRead, USAGE_INFO_PARAM_READ }, // read param count
+ { "watch", 2, ExeuteCmdParamWatch, USAGE_INFO_PARAM_WATCH }, // watch param count
+#endif
+ };
+#ifdef PARAM_TEST
+ ParamWorkSpace *space = GetClientParamWorkSpace();
+ if (space != NULL && space->securityLabel != NULL) {
+ const int testUid = 1000;
+ space->securityLabel->cred.uid = testUid;
+ space->securityLabel->cred.gid = testUid;
+ }
+#endif
+ if ((strcmp(argv[0], "./paramset") == 0) || (strcmp(argv[0], "paramset") == 0)) {
+ if (argc == (MIN_ARGC + 1)) {
+ ExeuteCmdParamSet(argc, argv, 1);
+ } else {
+ printf("param set key value \n");
+ }
+ return 0;
+ } else if ((strcmp(argv[0], "./paramget") == 0) || (strcmp(argv[0], "paramget") == 0)) {
+ ExeuteCmdParamSet(argc, argv, 1);
+ return 0;
+ }
if (argc < MIN_ARGC) {
printf("usage: \n");
for (size_t i = 0; i < sizeof(paramCmds) / sizeof(paramCmds[0]); i++) {
diff --git a/services/param/include/param_manager.h b/services/param/include/param_manager.h
old mode 100644
new mode 100755
diff --git a/services/param/include/param_persist.h b/services/param/include/param_persist.h
index 95b14f6..fedf317 100755
--- a/services/param/include/param_persist.h
+++ b/services/param/include/param_persist.h
@@ -40,8 +40,12 @@ typedef struct {
#ifdef PARAM_SUPPORT_SAVE_PERSIST
int RegisterPersistParamOps(PersistParamOps *ops);
+#ifdef STARTUP_INIT_TEST
#define PARAM_MUST_SAVE_PARAM_DIFF 10 // 10s
#else
+#define PARAM_MUST_SAVE_PARAM_DIFF 1
+#endif
+#else
#define PARAM_MUST_SAVE_PARAM_DIFF UINT32_MAX
#endif
#ifdef __cplusplus
diff --git a/services/param/include/param_request.h b/services/param/include/param_request.h
old mode 100644
new mode 100755
index f6d5ccf..a6b786f
--- a/services/param/include/param_request.h
+++ b/services/param/include/param_request.h
@@ -16,6 +16,7 @@
#ifndef BASE_STARTUP_PARAM_REQUEST_H
#define BASE_STARTUP_PARAM_REQUEST_H
+#include
#include "param_manager.h"
#include "sys_param.h"
#ifdef __cplusplus
diff --git a/services/param/include/param_service.h b/services/param/include/param_service.h
old mode 100644
new mode 100755
diff --git a/services/param/include/param_trie.h b/services/param/include/param_trie.h
old mode 100644
new mode 100755
diff --git a/services/param/include/param_utils.h b/services/param/include/param_utils.h
index 61decf0..54ae0e8 100755
--- a/services/param/include/param_utils.h
+++ b/services/param/include/param_utils.h
@@ -48,16 +48,17 @@ typedef enum {
#define OHOS_SERVICE_CTRL_PREFIX "ohos.servicectrl."
#define OHOS_BOOT "ohos.boot."
+#define CLIENT_PIPE_NAME "/dev/unix/socket/paramservice"
+#define CLIENT_PARAM_STORAGE_PATH "/dev/__parameters__/param_storage"
+
#ifdef STARTUP_INIT_TEST
#define PARAM_STATIC
-#define PARAM_DEFAULT_PATH ""
-#define PIPE_NAME "/data/paramservice"
-#define PARAM_STORAGE_PATH PARAM_DEFAULT_PATH"/__parameters__/param_storage"
-#define PARAM_PERSIST_SAVE_PATH PARAM_DEFAULT_PATH"/param/persist_parameters"
-#define PARAM_PERSIST_SAVE_TMP_PATH PARAM_DEFAULT_PATH"/param/tmp_persist_parameters"
+#define PARAM_DEFAULT_PATH "/data/init_ut"
+#define PIPE_NAME PARAM_DEFAULT_PATH"/param/paramservice"
+#define PARAM_STORAGE_PATH PARAM_DEFAULT_PATH "/__parameters__/param_storage"
+#define PARAM_PERSIST_SAVE_PATH PARAM_DEFAULT_PATH "/param/persist_parameters"
+#define PARAM_PERSIST_SAVE_TMP_PATH PARAM_DEFAULT_PATH "/param/tmp_persist_parameters"
#define PARAM_CMD_LINE PARAM_DEFAULT_PATH"/proc/cmdline"
-#define GROUP_FILE_PATH PARAM_DEFAULT_PATH"/etc/group"
-#define USER_FILE_PATH PARAM_DEFAULT_PATH"/etc/passwd"
#else
#define PARAM_DEFAULT_PATH ""
#define PARAM_STATIC static
@@ -66,9 +67,10 @@ typedef enum {
#define PARAM_PERSIST_SAVE_PATH "/data/parameters/persist_parameters"
#define PARAM_PERSIST_SAVE_TMP_PATH "/data/parameters/tmp_persist_parameters"
#define PARAM_CMD_LINE "/proc/cmdline"
+#endif
+
#define GROUP_FILE_PATH "/etc/group"
#define USER_FILE_PATH "/etc/passwd"
-#endif
#define WORKSPACE_FLAGS_INIT 0x01
#define WORKSPACE_FLAGS_LOADED 0x02
@@ -79,6 +81,10 @@ typedef enum {
#define PARAM_CLEAR_FLAG(node, flag) ((node) &= ~(flag))
#define PARAM_TEST_FLAG(node, flag) (((node) & (flag)) == (flag))
+#ifndef LABEL
+#define LABEL "Parameter"
+#endif
+
#define PARAM_LOGI(fmt, ...) STARTUP_LOGI(LABEL, fmt, ##__VA_ARGS__)
#define PARAM_LOGE(fmt, ...) STARTUP_LOGE(LABEL, fmt, ##__VA_ARGS__)
#define PARAM_LOGD(fmt, ...) STARTUP_LOGD(LABEL, fmt, ##__VA_ARGS__)
@@ -110,8 +116,6 @@ typedef struct {
#define MAX_DATA_BUFFER 2048
char *ReadFileData(const char *fileName);
void CheckAndCreateDir(const char *fileName);
-int ReadFileInDir(const char *dirPath, const char *includeExt,
- int (*processFile)(const char *fileName, void *context), void *context);
int GetSubStringInfo(const char *buff, uint32_t buffLen, char delimiter, SubStringInfo *info, int subStrNumber);
#ifdef __cplusplus
#if __cplusplus
diff --git a/services/param/include/trigger_checker.h b/services/param/include/trigger_checker.h
old mode 100644
new mode 100755
diff --git a/services/param/include/trigger_manager.h b/services/param/include/trigger_manager.h
old mode 100644
new mode 100755
diff --git a/services/param/manager/param_manager.c b/services/param/manager/param_manager.c
old mode 100644
new mode 100755
index abd7372..b2e36c0
--- a/services/param/manager/param_manager.c
+++ b/services/param/manager/param_manager.c
@@ -14,9 +14,9 @@
*/
#include "param_manager.h"
+
#include
-#define LABEL "Manager"
#if !defined PARAM_SUPPORT_SELINUX && !defined PARAM_SUPPORT_DAC
static ParamSecurityLabel g_defaultSecurityLabel;
#endif
@@ -64,7 +64,11 @@ int InitParamWorkSpace(ParamWorkSpace *workSpace, int onlyRead)
ret = paramSecurityOps->securityCheckFilePermission(workSpace->securityLabel, PARAM_STORAGE_PATH, op);
PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "No permission to read file %s", PARAM_STORAGE_PATH);
}
- ret = InitWorkSpace(PARAM_STORAGE_PATH, &workSpace->paramSpace, onlyRead);
+ if (onlyRead) {
+ ret = InitWorkSpace(CLIENT_PARAM_STORAGE_PATH, &workSpace->paramSpace, onlyRead);
+ } else {
+ ret = InitWorkSpace(PARAM_STORAGE_PATH, &workSpace->paramSpace, onlyRead);
+ }
PARAM_CHECK(ret == 0, return PARAM_CODE_INVALID_NAME, "Failed to init workspace");
PARAM_SET_FLAG(workSpace->flags, WORKSPACE_FLAGS_INIT);
return ret;
@@ -272,12 +276,14 @@ static void DumpWorkSpace(const ParamWorkSpace *workSpace, int verbose)
{
printf("workSpace information \n");
printf(" map file: %s \n", workSpace->paramSpace.fileName);
- printf(" total size: %d \n", workSpace->paramSpace.area->dataSize);
- printf(" first offset: %d \n", workSpace->paramSpace.area->firstNode);
- printf(" current offset: %d \n", workSpace->paramSpace.area->currOffset);
- printf(" total node: %d \n", workSpace->paramSpace.area->trieNodeCount);
- printf(" total param node: %d \n", workSpace->paramSpace.area->paramNodeCount);
- printf(" total security node: %d\n", workSpace->paramSpace.area->securityNodeCount);
+ if (workSpace->paramSpace.area != NULL) {
+ printf(" total size: %d \n", workSpace->paramSpace.area->dataSize);
+ printf(" first offset: %d \n", workSpace->paramSpace.area->firstNode);
+ printf(" current offset: %d \n", workSpace->paramSpace.area->currOffset);
+ printf(" total node: %d \n", workSpace->paramSpace.area->trieNodeCount);
+ printf(" total param node: %d \n", workSpace->paramSpace.area->paramNodeCount);
+ printf(" total security node: %d\n", workSpace->paramSpace.area->securityNodeCount);
+ }
printf(" node info: \n");
TraversalTrieNode(&workSpace->paramSpace, NULL, DumpTrieDataNodeTraversal, (void *)&verbose);
}
diff --git a/services/param/manager/param_message.c b/services/param/manager/param_message.c
index e1ff245..48dc528 100755
--- a/services/param/manager/param_message.c
+++ b/services/param/manager/param_message.c
@@ -14,6 +14,7 @@
*/
#include "param_message.h"
+
#include
#include
#include
@@ -21,7 +22,6 @@
#include
#include
-#define LABEL "PARAM_MSG"
int ConntectServer(int fd, const char *servername)
{
PARAM_CHECK(fd >= 0, return -1, "Invalid fd %d", fd);
diff --git a/services/param/manager/param_trie.c b/services/param/manager/param_trie.c
old mode 100644
new mode 100755
index af6c78d..94d7086
--- a/services/param/manager/param_trie.c
+++ b/services/param/manager/param_trie.c
@@ -27,8 +27,6 @@
#include "param_utils.h"
#include "sys_param.h"
-#define LABEL "Manager"
-
static int InitWorkSpace_(WorkSpace *workSpace, int mode, int prot, uint32_t spaceSize, int readOnly)
{
PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid workSpace");
diff --git a/services/param/manager/param_utils.c b/services/param/manager/param_utils.c
index ee0dadf..64ab646 100755
--- a/services/param/manager/param_utils.c
+++ b/services/param/manager/param_utils.c
@@ -26,7 +26,6 @@
#include
#include
-#define LABEL "PARAM_UTILS"
void CheckAndCreateDir(const char *fileName)
{
if (fileName == NULL || *fileName == '\0') {
@@ -39,45 +38,6 @@ void CheckAndCreateDir(const char *fileName)
free(path);
}
-int ReadFileInDir(const char *dirPath, const char *includeExt,
- int (*processFile)(const char *fileName, void *context), void *context)
-{
- if (dirPath == NULL || processFile == NULL) {
- return -1;
- }
- DIR *pDir = opendir(dirPath);
- PARAM_CHECK(pDir != NULL, return -1, "Read dir :%s failed.%d", dirPath, errno);
- char *fileName = malloc(PARAM_BUFFER_SIZE);
- PARAM_CHECK(fileName != NULL, closedir(pDir);
- return -1, "Failed to malloc for %s", dirPath);
-
- struct dirent *dp;
- while ((dp = readdir(pDir)) != NULL) {
- if (dp->d_type == DT_DIR) {
- continue;
- }
- PARAM_LOGD("ReadFileInDir %s", dp->d_name);
- if (includeExt != NULL) {
- char *tmp = strstr(dp->d_name, includeExt);
- if (tmp == NULL) {
- continue;
- }
- if (strcmp(tmp, includeExt) != 0) {
- continue;
- }
- }
- int ret = snprintf_s(fileName, PARAM_BUFFER_SIZE, PARAM_BUFFER_SIZE - 1, "%s/%s", dirPath, dp->d_name);
- PARAM_CHECK(ret > EOK, continue, "Failed to get file name for %s", dp->d_name);
- struct stat st;
- if (stat(fileName, &st) == 0) {
- processFile(fileName, context);
- }
- }
- free(fileName);
- closedir(pDir);
- return 0;
-}
-
char *ReadFileData(const char *fileName)
{
if (fileName == NULL) {
@@ -86,7 +46,7 @@ char *ReadFileData(const char *fileName)
char *buffer = NULL;
int fd = -1;
do {
- fd = open(fileName, O_RDONLY);
+ fd = open(fileName, O_RDONLY); // 阶段早,不能使用realpath
PARAM_CHECK(fd >= 0, break, "Failed to read file %s", fileName);
buffer = (char *)malloc(MAX_DATA_BUFFER);
diff --git a/services/param/service/param_persist.c b/services/param/service/param_persist.c
old mode 100644
new mode 100755
index a2d2b3b..1bfcff5
--- a/services/param/service/param_persist.c
+++ b/services/param/service/param_persist.c
@@ -12,8 +12,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#include "param_persist.h"
+
#include
#include
#include
@@ -24,8 +24,6 @@
#include "param_trie.h"
#include "sys_param.h"
-#define LABEL "Manager"
-
static ParamPersistWorkSpace g_persistWorkSpace = { 0, NULL, 0, { NULL, NULL, NULL, NULL, NULL } };
static int AddPersistParam(const char *name, const char *value, void *context)
@@ -110,10 +108,12 @@ int LoadPersistParam(ParamWorkSpace *workSpace)
PARAM_CHECK(workSpace != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid workSpace");
int ret = InitPersistParamWorkSpace(workSpace);
PARAM_CHECK(ret == 0, return ret, "Failed to init persist param");
+#ifndef STARTUP_INIT_TEST
if (PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED)) {
PARAM_LOGE("Persist param has been loaded");
return 0;
}
+#endif
if (g_persistWorkSpace.persistParamOps.load != NULL) {
ret = g_persistWorkSpace.persistParamOps.load(AddPersistParam, &workSpace->paramSpace);
PARAM_SET_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_LOADED);
@@ -124,10 +124,11 @@ int LoadPersistParam(ParamWorkSpace *workSpace)
return 0;
}
-static void TimerCallbackForSave(ParamTaskPtr timer, void *context)
+PARAM_STATIC void TimerCallbackForSave(ParamTaskPtr timer, void *context)
{
UNUSED(context);
- ParamTaskClose(timer);
+ UNUSED(timer);
+ ParamTaskClose(g_persistWorkSpace.saveTimer);
g_persistWorkSpace.saveTimer = NULL;
if (!PARAM_TEST_FLAG(g_persistWorkSpace.flags, WORKSPACE_FLAGS_UPDATE)) {
return;
diff --git a/services/param/service/param_service.c b/services/param/service/param_service.c
old mode 100644
new mode 100755
index 8f3c0a0..f78f663
--- a/services/param/service/param_service.c
+++ b/services/param/service/param_service.c
@@ -25,12 +25,12 @@
#include
#include "init_param.h"
+#include "init_utils.h"
#include "param_message.h"
#include "param_manager.h"
#include "param_request.h"
#include "trigger_manager.h"
-#define LABEL "ParamServer"
static ParamWorkSpace g_paramWorkSpace = { 0, {}, NULL, {}, NULL, NULL };
static void OnClose(ParamTaskPtr client)
@@ -133,6 +133,8 @@ PARAM_STATIC int AddSecurityLabel(const ParamAuditData *auditData, void *context
#ifdef STARTUP_INIT_TEST
ParamSecruityNode *label = (ParamSecruityNode *)GetTrieNode(&workSpace->paramSpace, node->labelIndex);
label->mode = auditData->dacData.mode;
+ label->uid = auditData->dacData.uid;
+ label->gid = auditData->dacData.gid;
#endif
PARAM_LOGE("Error, repeate to add label for name %s", auditData->name);
}
@@ -155,7 +157,7 @@ static char *GetServiceCtrlName(const char *name, const char *value)
};
char *key = NULL;
if (strcmp("sys.powerctrl", name) == 0) {
- for (size_t i = 0; i < sizeof(powerCtrlArg) / sizeof(powerCtrlArg[0]); i++) {
+ for (size_t i = 0; i < ARRAY_LENGTH(powerCtrlArg); i++) {
if (strncmp(value, powerCtrlArg[i][0], strlen(powerCtrlArg[i][0])) == 0) {
uint32_t keySize = strlen(powerCtrlArg[i][1]) + strlen(OHOS_SERVICE_CTRL_PREFIX) + 1;
key = (char *)malloc(keySize + 1);
@@ -167,7 +169,7 @@ static char *GetServiceCtrlName(const char *name, const char *value)
}
}
} else {
- for (size_t i = 0; i < sizeof(ctrlParam) / sizeof(ctrlParam[0]); i++) {
+ for (size_t i = 0; i < ARRAY_LENGTH(ctrlParam); i++) {
if (strcmp(name, ctrlParam[i]) == 0) {
uint32_t keySize = strlen(value) + strlen(OHOS_SERVICE_CTRL_PREFIX) + 1;
key = (char *)malloc(keySize + 1);
@@ -225,14 +227,15 @@ static int SystemSetParam(const char *name, const char *value, const ParamSecuri
free(key);
}
PARAM_CHECK(ret == 0, return ret, "Forbit to set parameter %s", name);
- uint32_t dataIndex = 0;
- ret = WriteParam(&g_paramWorkSpace.paramSpace, name, value, &dataIndex, 0);
- PARAM_CHECK(ret == 0, return ret, "Failed to set param %d name %s %s", ret, name, value);
- ret = WritePersistParam(&g_paramWorkSpace, name, value);
- PARAM_CHECK(ret == 0, return ret, "Failed to set persist param name %s", name);
+
if (serviceCtrl) {
PostParamTrigger(EVENT_TRIGGER_PARAM, name, value);
} else {
+ uint32_t dataIndex = 0;
+ ret = WriteParam(&g_paramWorkSpace.paramSpace, name, value, &dataIndex, 0);
+ PARAM_CHECK(ret == 0, return ret, "Failed to set param %d name %s %s", ret, name, value);
+ ret = WritePersistParam(&g_paramWorkSpace, name, value);
+ PARAM_CHECK(ret == 0, return ret, "Failed to set persist param name %s", name);
CheckAndSendTrigger(&g_paramWorkSpace, dataIndex, name, value);
}
return ret;
@@ -508,6 +511,97 @@ static void TimerCallback(ParamTaskPtr timer, void *context)
}
}
+static int GetParamValueFromBuffer(const char *name, const char *buffer, char *value, int length)
+{
+ char *endData = (char *)buffer + strlen(buffer);
+ size_t bootLen = strlen(OHOS_BOOT);
+ char *tmp = strstr(buffer, name + bootLen);
+ do {
+ if (tmp == NULL) {
+ return -1;
+ }
+ tmp = tmp + strlen(name) - bootLen;
+ while (tmp < endData && *tmp == ' ') {
+ tmp++;
+ }
+ if (*tmp == '=') {
+ break;
+ }
+ tmp = strstr(tmp + 1, name + bootLen);
+ } while (tmp < endData);
+ tmp++;
+ size_t i = 0;
+ size_t endIndex = 0;
+ while (tmp < endData && *tmp == ' ') {
+ tmp++;
+ }
+ for (; i < (size_t)length; tmp++) {
+ if (tmp >= endData) {
+ endIndex = i;
+ break;
+ }
+ if (*tmp == ' ') {
+ endIndex = i;
+ }
+ if (*tmp == '=') {
+ if (endIndex != 0) { // for root=uuid=xxxx
+ break;
+ }
+ i = 0;
+ endIndex = 0;
+ continue;
+ }
+ value[i++] = *tmp;
+ }
+ if (i >= (size_t)length) {
+ return -1;
+ }
+ value[endIndex] = '\0';
+ return 0;
+}
+
+static int LoadParamFromCmdLine(void)
+{
+ static const char *cmdLines[] = {
+ OHOS_BOOT"hardware",
+#ifdef STARTUP_INIT_TEST
+ OHOS_BOOT"mem",
+ OHOS_BOOT"console",
+ OHOS_BOOT"mmz",
+ OHOS_BOOT"androidboot.selinux",
+ OHOS_BOOT"init",
+ OHOS_BOOT"root",
+ OHOS_BOOT"uuid",
+ OHOS_BOOT"aaaaa",
+ OHOS_BOOT"rootfstype",
+ OHOS_BOOT"blkdevparts",
+#endif
+ };
+ char *data = ReadFileData(PARAM_CMD_LINE);
+ PARAM_CHECK(data != NULL, return -1, "Failed to read file %s", PARAM_CMD_LINE);
+ char *value = malloc(PARAM_CONST_VALUE_LEN_MAX);
+ PARAM_CHECK(value != NULL, free(data);
+ return -1, "Failed to read file %s", PARAM_CMD_LINE);
+
+ for (size_t i = 0; i < ARRAY_LENGTH(cmdLines); i++) {
+ int ret = GetParamValueFromBuffer(cmdLines[i], data, value, PARAM_CONST_VALUE_LEN_MAX);
+ if (ret == 0) {
+ PARAM_LOGD("Add param from cmdline %s %s", cmdLines[i], value);
+ ret = CheckParamName(cmdLines[i], 0);
+ PARAM_CHECK(ret == 0, return -1, "Invalid name %s", cmdLines[i]);
+ uint32_t dataIndex = 0;
+ ret = WriteParam(&g_paramWorkSpace.paramSpace, cmdLines[i], value, &dataIndex, 0);
+ PARAM_CHECK(ret == 0, return -1, "Failed to write param %s %s", cmdLines[i], value);
+ } else {
+ PARAM_LOGE("Can not find arrt %s", cmdLines[i]);
+ }
+ }
+ PARAM_LOGD("Parse cmdline finish %s", PARAM_CMD_LINE);
+ free(data);
+ free(value);
+ return 0;
+}
+
int SystemWriteParam(const char *name, const char *value)
{
PARAM_CHECK(name != NULL && value != NULL, return -1, "The name is null");
@@ -525,12 +619,6 @@ int SystemReadParam(const char *name, char *value, unsigned int *len)
return ret;
}
-int SystemTraversalParam(void (*traversalParameter)(ParamHandle handle, void *cookie), void *cookie)
-{
- PARAM_CHECK(traversalParameter != NULL, return -1, "The param is null");
- return TraversalParam(&g_paramWorkSpace, traversalParameter, cookie);
-}
-
int LoadPersistParams(void)
{
return LoadPersistParam(&g_paramWorkSpace);
@@ -540,7 +628,7 @@ static int ProcessParamFile(const char *fileName, void *context)
{
static const char *exclude[] = {"ctl.", "selinux.restorecon_recursive"};
uint32_t mode = *(int *)context;
- return LoadDefaultParam_(fileName, mode, exclude, sizeof(exclude) / sizeof(exclude[0]));
+ return LoadDefaultParam_(fileName, mode, exclude, ARRAY_LENGTH(exclude));
}
int LoadDefaultParams(const char *fileName, uint32_t mode)
@@ -602,6 +690,9 @@ void InitParamService(void)
auditData.dacData.mode = DAC_ALL_PERMISSION;
ret = AddSecurityLabel(&auditData, (void *)&g_paramWorkSpace);
PARAM_CHECK(ret == 0, return, "Failed to add default dac label");
+
+ // 读取cmdline的参数
+ LoadParamFromCmdLine();
}
static void OnPidDelete(pid_t pid)
@@ -628,3 +719,11 @@ ParamWorkSpace *GetParamWorkSpace(void)
{
return &g_paramWorkSpace;
}
+
+void DumpParametersAndTriggers(void)
+{
+ DumpParameters(&g_paramWorkSpace, 1);
+ if (GetTriggerWorkSpace() != NULL) {
+ DumpTrigger(GetTriggerWorkSpace());
+ }
+}
\ No newline at end of file
diff --git a/services/param/trigger/trigger_checker.c b/services/param/trigger/trigger_checker.c
old mode 100644
new mode 100755
index 2bd1e89..ee40975
--- a/services/param/trigger/trigger_checker.c
+++ b/services/param/trigger/trigger_checker.c
@@ -20,7 +20,6 @@
#include "trigger_manager.h"
#define MAX_CALC_PARAM 100
-#define LABEL "Trigger"
// 申请整块能存作为计算的节点
int CalculatorInit(LogicCalculator *calculator, int dataNumber, int dataUnit, int needCondition)
{
diff --git a/services/param/trigger/trigger_manager.c b/services/param/trigger/trigger_manager.c
old mode 100644
new mode 100755
index 97e4639..7602cdd
--- a/services/param/trigger/trigger_manager.c
+++ b/services/param/trigger/trigger_manager.c
@@ -27,7 +27,6 @@
#include "param_manager.h"
#include "trigger_checker.h"
-#define LABEL "Trigger"
int AddCommand(TriggerNode *trigger, uint32_t cmdKeyIndex, const char *content)
{
PARAM_CHECK(trigger != NULL, return -1, "trigger is null");
@@ -44,15 +43,14 @@ int AddCommand(TriggerNode *trigger, uint32_t cmdKeyIndex, const char *content)
int ret = memcpy_s(node->content, size, content, strlen(content));
node->content[strlen(content)] = '\0';
PARAM_CHECK(ret == EOK, free(node);
- return -1, "Failed to copy command");
+ return 0, "Failed to copy command");
}
// 插入队列
if (trigger->firstCmd == NULL) {
trigger->firstCmd = node;
trigger->lastCmd = node;
} else {
- PARAM_CHECK(trigger->lastCmd != NULL, free(node);
- return -1, "Invalid last cmd");
+ PARAM_CHECK(trigger->lastCmd != NULL, return 0, "Invalid last cmd");
trigger->lastCmd->next = node;
trigger->lastCmd = node;
}
@@ -257,6 +255,8 @@ static int CheckParamTriggerMatch(TriggerWorkSpace *workSpace, LogicCalculator *
static int CheckOtherTriggerMatch(TriggerWorkSpace *workSpace, LogicCalculator *calculator,
TriggerNode *trigger, const char *content, uint32_t contentSize)
{
+ UNUSED(content);
+ UNUSED(contentSize);
const char *condition = GetTriggerCondition(workSpace, trigger);
return ComputeCondition(calculator, condition);
}
diff --git a/services/param/trigger/trigger_processor.c b/services/param/trigger/trigger_processor.c
old mode 100644
new mode 100755
index e87efac..81260bb
--- a/services/param/trigger/trigger_processor.c
+++ b/services/param/trigger/trigger_processor.c
@@ -12,20 +12,58 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#include
-
+#include
#include "init_cmds.h"
+#include "init_param.h"
#include "init_service_manager.h"
+#include "init_utils.h"
#include "param_manager.h"
#include "param_utils.h"
#include "trigger_checker.h"
#include "trigger_manager.h"
-#define LABEL "Trigger"
#define MAX_TRIGGER_COUNT_RUN_ONCE 20
static TriggerWorkSpace g_triggerWorkSpace = {};
+#ifdef PARAM_TEST
+#define MAX_COUNT 1000
+#define READ_DURATION 100000
+#define TEST_PARAM_NAME "test.random.read.001"
+static void AddTestTrigger(const TriggerWorkSpace *workSpace)
+{
+ TriggerHeader *header = (TriggerHeader *)&workSpace->triggerHead[TRIGGER_PARAM];
+ TriggerNode *trigger = AddTrigger(header, "param:test.randrom.test.start=1", "test.randrom.test.start=1", 0);
+ PARAM_CHECK(trigger != NULL, return, "Failed to create test trigger");
+ int cmdKeyIndex = 0;
+ GetMatchCmd("setparam ", &cmdKeyIndex);
+ int ret = AddCommand(trigger, (uint32_t)CMD_INDEX_FOR_PARA_TEST, NULL);
+ PARAM_CHECK(ret == 0, return, "Failed to add command");
+}
+
+static void TestTimerCallback(ParamTaskPtr timer, void *context)
+{
+ srand((unsigned)time(NULL));
+ char buffer[32] = { 0 };
+ static int index = 0;
+ index++;
+ if (index >= MAX_COUNT) {
+ ParamTaskClose(timer);
+ }
+ static uint32_t value = 0;
+ int count = 0;
+ while (count < MAX_COUNT) {
+ int wait = rand() / READ_DURATION + READ_DURATION; // 100ms
+ sprintf_s(buffer, sizeof(buffer), "%u", value);
+ PARAM_LOGI("set param name: %s, value %s", TEST_PARAM_NAME, buffer);
+ SystemWriteParam(TEST_PARAM_NAME, buffer);
+ usleep(wait);
+ count++;
+ value++;
+ }
+}
+#endif
+
void DoTriggerExec(const char *triggerName)
{
PARAM_CHECK(triggerName != NULL, return, "Invalid param");
@@ -45,17 +83,16 @@ static void DoCmdExec(const TriggerNode *trigger, const CommandNode *cmd, const
extData->excuteCmd(extData, cmd->cmdKeyIndex, content);
}
return;
- }
- const char *cmdName = GetCmdKey(cmd->cmdKeyIndex);
- if (cmdName == NULL) {
- return;
- }
- if (strncmp(cmdName, TRIGGER_CMD, strlen(TRIGGER_CMD)) == 0) {
- DoTriggerExec(cmd->content);
+#ifdef PARAM_TEST
+ } else if (cmd->cmdKeyIndex == CMD_INDEX_FOR_PARA_TEST) {
+ ParamTaskPtr timer = NULL;
+ ParamTimerCreate(&timer, TestTimerCallback, NULL);
+ ParamTimerStart(timer, READ_DURATION, MAX_COUNT);
return;
+#endif
}
#ifndef STARTUP_INIT_TEST
- DoCmdByName(cmdName, cmd->content);
+ DoCmdByIndex(cmd->cmdKeyIndex, cmd->content);
#endif
}
@@ -162,7 +199,7 @@ static const char *GetCmdInfo(const char *content, uint32_t contentSize, char **
static const char *ctrlCmds[][2] = {
{"reboot", "reboot "}
};
- uint32_t index = 0;
+ int index = 0;
for (size_t i = 0; i < sizeof(ctrlCmds) / sizeof(ctrlCmds[0]); i++) {
if (strncmp(content, ctrlCmds[i][0], strlen(ctrlCmds[i][0])) == 0) {
*cmdParam = (char *)content;
@@ -231,7 +268,7 @@ static int GetTriggerType(const char *type)
"pre-init", "boot", "early-init", "init", "early-init", "late-init", "post-init",
"early-fs", "post-fs", "late-fs", "post-fs-data"
};
- for (size_t i = 0; i < sizeof(triggerTypeStr) / sizeof(char *); i++) {
+ for (size_t i = 0; i < ARRAY_LENGTH(triggerTypeStr); i++) {
if (strcmp(triggerTypeStr[i], type) == 0) {
return TRIGGER_BOOT;
}
@@ -267,7 +304,7 @@ static int ParseTrigger_(const TriggerWorkSpace *workSpace, const cJSON *trigger
PARAM_CHECK(cmdLinesCnt > 0, return -1, "Command array size must positive %s", name);
int ret;
- uint32_t cmdKeyIndex = 0;
+ int cmdKeyIndex = 0;
for (int i = 0; (i < cmdLinesCnt) && (i < TRIGGER_MAX_CMD); ++i) {
char *cmdLineStr = cJSON_GetStringValue(cJSON_GetArrayItem(cmdItems, i));
PARAM_CHECK(cmdLineStr != NULL, continue, "Command is null");
@@ -277,9 +314,9 @@ static int ParseTrigger_(const TriggerWorkSpace *workSpace, const cJSON *trigger
PARAM_CHECK(matchCmd != NULL, continue, "Command not support %s", cmdLineStr);
size_t matchLen = strlen(matchCmd);
if (matchLen == cmdLineLen) {
- ret = AddCommand(trigger, cmdKeyIndex, NULL);
+ ret = AddCommand(trigger, (uint32_t)cmdKeyIndex, NULL);
} else {
- ret = AddCommand(trigger, cmdKeyIndex, cmdLineStr + matchLen);
+ ret = AddCommand(trigger, (uint32_t)cmdKeyIndex, cmdLineStr + matchLen);
}
PARAM_CHECK(ret == 0, continue, "Failed to add command %s", cmdLineStr);
}
@@ -299,6 +336,10 @@ int ParseTriggerConfig(const cJSON *fileRoot)
cJSON *item = cJSON_GetArrayItem(triggers, i);
ParseTrigger_(&g_triggerWorkSpace, item);
}
+#ifdef PARAM_TEST
+ // for test
+ AddTestTrigger(&g_triggerWorkSpace);
+#endif
return 0;
}
@@ -312,15 +353,12 @@ int InitTriggerWorkSpace(void)
PARAM_CHECK(g_triggerWorkSpace.eventHandle != NULL, return -1, "Failed to event handle");
// executeQueue
- g_triggerWorkSpace.executeQueue.executeQueue = malloc(TRIGGER_EXECUTE_QUEUE * sizeof(TriggerNode *));
+ g_triggerWorkSpace.executeQueue.executeQueue = calloc(1, TRIGGER_EXECUTE_QUEUE * sizeof(TriggerNode *));
+ PARAM_CHECK(g_triggerWorkSpace.executeQueue.executeQueue != NULL,
+ return -1, "Failed to alloc memory for executeQueue");
g_triggerWorkSpace.executeQueue.queueCount = TRIGGER_EXECUTE_QUEUE;
g_triggerWorkSpace.executeQueue.startIndex = 0;
g_triggerWorkSpace.executeQueue.endIndex = 0;
- PARAM_CHECK(g_triggerWorkSpace.executeQueue.executeQueue != NULL,
- return -1, "Failed to alloc memory for executeQueue");
- int ret = memset_s(g_triggerWorkSpace.executeQueue.executeQueue,
- TRIGGER_EXECUTE_QUEUE * sizeof(TriggerNode *), 0, TRIGGER_EXECUTE_QUEUE * sizeof(TriggerNode *));
- PARAM_CHECK(ret == EOK, return -1, "Failed to memset for executeQueue");
// normal trigger
for (size_t i = 0; i < sizeof(g_triggerWorkSpace.triggerHead) / sizeof(g_triggerWorkSpace.triggerHead[0]); i++) {
diff --git a/services/param/watcher/agent/watcher_manager_kits.cpp b/services/param/watcher/agent/watcher_manager_kits.cpp
index 0a60e7d..fd452c1 100755
--- a/services/param/watcher/agent/watcher_manager_kits.cpp
+++ b/services/param/watcher/agent/watcher_manager_kits.cpp
@@ -88,7 +88,7 @@ WatcherManagerKits::ParamWatcherKitPtr WatcherManagerKits::GetParamWatcher(const
void WatcherManagerKits::SetParamWatcher(const std::string &keyPrefix, ParamWatcherKitPtr watcher)
{
std::lock_guard lock(mutex_);
- if (watchers_.find(keyPrefix) != watchers_.end()) {
+ if (watchers_.find(keyPrefix) == watchers_.end()) {
watchers_[keyPrefix] = watcher;
}
}
diff --git a/services/param/watcher/include/watcher_utils.h b/services/param/watcher/include/watcher_utils.h
index 1026e5c..09aa72b 100755
--- a/services/param/watcher/include/watcher_utils.h
+++ b/services/param/watcher/include/watcher_utils.h
@@ -28,7 +28,7 @@ namespace init_param {
#define UNUSED(x) (void)(x)
#ifndef LABEL
-#define LABEL "Watcher"
+#define LABEL "ParameterWatcher"
#endif
#define WATCHER_LOGI(fmt, ...) STARTUP_LOGI(LABEL, fmt, ##__VA_ARGS__)
diff --git a/services/param/watcher/proxy/watcher_manager.cpp b/services/param/watcher/proxy/watcher_manager.cpp
index 02991b9..a568c41 100755
--- a/services/param/watcher/proxy/watcher_manager.cpp
+++ b/services/param/watcher/proxy/watcher_manager.cpp
@@ -32,9 +32,9 @@ const static int32_t INVALID_SOCKET = -1;
uint32_t WatcherManager::AddWatcher(const std::string &keyPrefix, const sptr &watcher)
{
WATCHER_CHECK(watcher != nullptr, return 0, "Invalid remove watcher for %s", keyPrefix.c_str());
- if (watcherId_ == 0) {
- watcherId_++;
- }
+ watcherId_++;
+ WATCHER_LOGD("AddWatcher begin %s", keyPrefix.c_str());
+
ParamWatcherPtr paramWather = std::make_shared(watcherId_, watcher);
WATCHER_CHECK(paramWather != nullptr, return 0, "Failed to create watcher for %s", keyPrefix.c_str());
WatcherGroupPtr group = GetWatcherGroup(keyPrefix);
@@ -44,6 +44,7 @@ uint32_t WatcherManager::AddWatcher(const std::string &keyPrefix, const sptrEmptry()) {
StartLoop();
SendMessage(group, MSG_ADD_WATCHER);
@@ -76,19 +77,19 @@ int WatcherManager::SendMessage(WatcherGroupPtr group, int type)
PARAM_CHECK(request != NULL, return PARAM_CODE_ERROR, "Failed to malloc for watch");
request->id.watcherId = group->GetGroupId();
request->msgSize = sizeof(ParamMessage);
- do {
- int fd = GetServerFd(false);
- if (fd != INVALID_SOCKET) {
- ssize_t sendLen = send(serverFd_, (char *)request, request->msgSize, 0);
- if (sendLen > 0) {
- PARAM_LOGD("SendMessage key: %s %d success", group->GetKeyPrefix().c_str(), type);
- break;
- }
+
+ WATCHER_LOGD("SendMessage %s", group->GetKeyPrefix().c_str());
+ int fd = GetServerFd(false);
+ if (fd != INVALID_SOCKET) {
+ ssize_t sendLen = send(serverFd_, (char *)request, request->msgSize, 0);
+ if (sendLen > 0) {
+ PARAM_LOGD("SendMessage key: %s %d success", group->GetKeyPrefix().c_str(), type);
+ } else {
+ PARAM_LOGD("SendMessage key: %s %d fail", group->GetKeyPrefix().c_str(), type);
}
- // fail, try again
- PARAM_LOGE("Failed to connect server %s, try again", PIPE_NAME);
- fd = GetServerFd(true);
- } while (1);
+ } else {
+ PARAM_LOGD("SendMessage key: %s %d fail", group->GetKeyPrefix().c_str(), type);
+ }
free(request);
return 0;
}
@@ -97,6 +98,7 @@ void WatcherManager::ProcessWatcherMessage(const std::vector &buffer, uint
{
ParamMessage *msg = (ParamMessage *)buffer.data();
PARAM_CHECK(msg != NULL, return, "Invalid msg");
+ PARAM_LOGD("ProcessWatcherMessage %d", msg->type);
uint32_t offset = 0;
if (msg->type != MSG_NOTIFY_PARAM) {
return;
@@ -123,18 +125,22 @@ WatcherManager::WatcherGroupPtr WatcherManager::GetWatcherGroup(uint32_t groupId
WatcherManager::WatcherGroupPtr WatcherManager::GetWatcherGroup(const std::string &keyPrefix)
{
+ std::lock_guard lock(watcherMutex_);
if (groupMap_.find(keyPrefix) == groupMap_.end()) {
return nullptr;
}
- return GetWatcherGroup(groupMap_[keyPrefix]);
+ uint32_t groupId = groupMap_[keyPrefix];
+ if (watcherGroups_.find(groupId) != watcherGroups_.end()) {
+ return watcherGroups_[groupId];
+ }
+ return nullptr;
}
void WatcherManager::AddWatcherGroup(const std::string &keyPrefix, WatcherGroupPtr group)
{
uint32_t groupId = group->GetGroupId();
- groupMap_[keyPrefix] = groupId;
-
std::lock_guard lock(watcherMutex_);
+ groupMap_[keyPrefix] = groupId;
if (watcherGroups_.find(groupId) != watcherGroups_.end()) {
return;
}
@@ -143,9 +149,9 @@ void WatcherManager::AddWatcherGroup(const std::string &keyPrefix, WatcherGroupP
void WatcherManager::DelWatcherGroup(WatcherGroupPtr group)
{
- groupMap_[group->GetKeyPrefix()] = 0;
std::lock_guard lock(watcherMutex_);
- watcherGroups_[group->GetGroupId()] = nullptr;
+ groupMap_.erase(group->GetKeyPrefix());
+ watcherGroups_.erase(group->GetGroupId());
}
void WatcherManager::WatcherGroup::AddWatcher(const ParamWatcherPtr &watcher)
@@ -156,7 +162,7 @@ void WatcherManager::WatcherGroup::AddWatcher(const ParamWatcherPtr &watcher)
void WatcherManager::WatcherGroup::DelWatcher(uint32_t watcherId)
{
if (watchers_.find(watcherId) != watchers_.end()) {
- watchers_[watcherId] = nullptr;
+ watchers_.erase(watcherId);
}
}
@@ -191,6 +197,7 @@ void WatcherManager::SendLocalChange(const std::string &keyPrefix, ParamWatcherP
ParamWatcherPtr watcher;
std::string keyPrefix;
};
+ PARAM_LOGD("SendLocalChange key %s ", keyPrefix.c_str());
std::vector buffer(PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX);
struct Context context = {buffer.data(), watcher, keyPrefix};
// walk watcher
@@ -211,7 +218,7 @@ void WatcherManager::RunLoop()
{
const int32_t RECV_BUFFER_MAX = 5 * 1024;
std::vector buffer(RECV_BUFFER_MAX, 0);
- while (!stop) {
+ while (!stop_) {
int fd = GetServerFd(false);
ssize_t recvLen = recv(fd, buffer.data(), RECV_BUFFER_MAX, 0);
if (recvLen <= 0) {
@@ -222,6 +229,9 @@ void WatcherManager::RunLoop()
PARAM_LOGE("Failed to recv msg from server errno %d", errno);
}
PARAM_LOGD("Recv msg from server");
+ if (stop_) {
+ break;
+ }
if (recvLen >= (ssize_t)sizeof(ParamMessage)) {
ProcessWatcherMessage(buffer, recvLen);
}
@@ -240,6 +250,7 @@ void WatcherManager::StartLoop()
int WatcherManager::GetServerFd(bool retry)
{
const int32_t sleepTime = 2000;
+ const int32_t maxRetry = 10;
std::lock_guard lock(mutex_);
if (retry && serverFd_ != INVALID_SOCKET) {
close(serverFd_);
@@ -251,9 +262,10 @@ int WatcherManager::GetServerFd(bool retry)
struct timeval time {};
time.tv_sec = 1;
time.tv_usec = 0;
+ int32_t retryCount = 0;
do {
serverFd_ = socket(AF_UNIX, SOCK_STREAM, 0);
- int ret = ConntectServer(serverFd_, PIPE_NAME);
+ int ret = ConntectServer(serverFd_, CLIENT_PIPE_NAME);
if (ret != 0) {
close(serverFd_);
serverFd_ = INVALID_SOCKET;
@@ -262,7 +274,9 @@ int WatcherManager::GetServerFd(bool retry)
(void)setsockopt(serverFd_, SOL_SOCKET, SO_RCVTIMEO, &time, sizeof(struct timeval));
break;
}
- } while (1);
+ retryCount++;
+ } while (retryCount < maxRetry);
+ PARAM_LOGD("SendMessage retryCount %d", retryCount);
return serverFd_;
}
@@ -276,10 +290,10 @@ void WatcherManager::OnStart()
return;
}
-void WatcherManager::OnStop()
+void WatcherManager::StopLoop()
{
- PARAM_LOGI("WatcherManager OnStop");
- stop = true;
+ PARAM_LOGI("WatcherManager StopLoop");
+ stop_ = true;
{
std::lock_guard lock(mutex_);
close(serverFd_);
@@ -291,5 +305,10 @@ void WatcherManager::OnStop()
pRecvThread_ = nullptr;
}
}
+
+void WatcherManager::OnStop()
+{
+ StopLoop();
+}
} // namespace init_param
} // namespace OHOS
diff --git a/services/param/watcher/proxy/watcher_manager.h b/services/param/watcher/proxy/watcher_manager.h
index 8e769d8..78e3b7d 100755
--- a/services/param/watcher/proxy/watcher_manager.h
+++ b/services/param/watcher/proxy/watcher_manager.h
@@ -90,6 +90,7 @@ public:
uint32_t AddWatcher(const std::string &keyPrefix, const sptr &watcher) override;
int32_t DelWatcher(const std::string &keyPrefix, uint32_t watcherId) override;
+ void StopLoop();
protected:
void OnStart() override;
void OnStop() override;
@@ -111,7 +112,7 @@ private:
std::mutex watcherMutex_;
int serverFd_ { -1 };
std::thread *pRecvThread_ { nullptr };
- std::atomic stop { false };
+ std::atomic stop_ { false };
std::map groupMap_ {};
std::map watcherGroups_ {};
};
diff --git a/services/src/init_capability.c b/services/src/init_capability.c
deleted file mode 100644
index 7c2cf13..0000000
--- a/services/src/init_capability.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "init_capability.h"
-
-#include
-#include
-#if defined OHOS_LITE && !defined __LINUX__
-#include
-#else
-#include
-#endif
-#include
-
-#include "init_log.h"
-#include "init_perms.h"
-#include "init_utils.h"
-
-#define MAX_CAPS_CNT_FOR_ONE_SERVICE 100
-
-struct CapStrCapNum {
- char *capStr;
- int CapNum;
-};
-
-static const struct CapStrCapNum g_capStrCapNum[] = {
- {"CHOWN", CAP_CHOWN},
- {"DAC_OVERRIDE", CAP_DAC_OVERRIDE},
- {"DAC_READ_SEARCH", CAP_DAC_READ_SEARCH},
- {"FOWNER", CAP_FOWNER},
- {"FSETID", CAP_FSETID},
- {"KILL", CAP_KILL},
- {"SETGID", CAP_SETGID},
- {"SETUID", CAP_SETUID},
- {"SETPCAP", CAP_SETPCAP},
- {"LINUX_IMMUTABLE", CAP_LINUX_IMMUTABLE},
- {"NET_BIND_SERVICE", CAP_NET_BIND_SERVICE},
- {"NET_BROADCAST", CAP_NET_BROADCAST},
- {"NET_ADMIN", CAP_NET_ADMIN},
- {"NET_RAW", CAP_NET_RAW},
- {"IPC_LOCK", CAP_IPC_LOCK},
- {"IPC_OWNER", CAP_IPC_OWNER},
- {"SYS_MODULE", CAP_SYS_MODULE},
- {"SYS_RAWIO", CAP_SYS_RAWIO},
- {"SYS_CHROOT", CAP_SYS_CHROOT},
- {"SYS_PTRACE", CAP_SYS_PTRACE},
- {"SYS_PACCT", CAP_SYS_PACCT},
- {"SYS_ADMIN", CAP_SYS_ADMIN},
- {"SYS_BOOT", CAP_SYS_BOOT},
- {"SYS_NICE", CAP_SYS_NICE},
- {"SYS_RESOURCE", CAP_SYS_RESOURCE},
- {"SYS_TIME", CAP_SYS_TIME},
- {"SYS_TTY_CONFIG", CAP_SYS_TTY_CONFIG},
- {"MKNOD", CAP_MKNOD},
- {"LEASE", CAP_LEASE},
- {"AUDIT_WRITE", CAP_AUDIT_WRITE},
- {"AUDIT_CONTROL", CAP_AUDIT_CONTROL},
- {"SETFCAP", CAP_SETFCAP},
- {"MAC_OVERRIDE", CAP_MAC_OVERRIDE},
- {"MAC_ADMIN", CAP_MAC_ADMIN},
- {"SYSLOG", CAP_SYSLOG},
- {"WAKE_ALARM", CAP_WAKE_ALARM},
- {"BLOCK_SUSPEND", CAP_BLOCK_SUSPEND},
- {"AUDIT_READ", CAP_AUDIT_READ},
-};
-
-static int GetServiceStringCaps(const cJSON* filedJ, Service* curServ) // string form
-{
- unsigned int i = 0;
- for (; i < curServ->servPerm.capsCnt; ++i) {
- if (cJSON_GetArrayItem(filedJ, i) == NULL || !cJSON_GetStringValue(cJSON_GetArrayItem(filedJ, i))
- || strlen(cJSON_GetStringValue(cJSON_GetArrayItem(filedJ, i))) <= 0) { // check all errors
- INIT_LOGE("service=%s, parse item[%d] as string, error.", curServ->name, i);
- break;
- }
- char* fieldStr = cJSON_GetStringValue(cJSON_GetArrayItem(filedJ, i));
- if (fieldStr == NULL) {
- INIT_LOGE("fieldStr is NULL");
- break;
- }
- int mapSize = ARRAY_LENGTH(g_capStrCapNum); // search
- int j = 0;
- for (; j < mapSize; j++) {
- if (!strcmp(fieldStr, g_capStrCapNum[j].capStr)) {
- break;
- }
- }
- if (j < mapSize) {
- curServ->servPerm.caps[i] = g_capStrCapNum[j].CapNum;
- } else {
- INIT_LOGE("service=%s, CapbilityName=%s, error.", curServ->name, fieldStr);
- break;
- }
- if (curServ->servPerm.caps[i] > CAP_LAST_CAP && curServ->servPerm.caps[i] != FULL_CAP) {
- // resources will be released by function: ReleaseServiceMem
- INIT_LOGE("service=%s, cap = %d, error.", curServ->name, curServ->servPerm.caps[i]);
- return SERVICE_FAILURE;
- }
- }
- int ret = ((i == curServ->servPerm.capsCnt) ? SERVICE_SUCCESS : SERVICE_FAILURE);
- return ret;
-}
-
-int GetServiceCaps(const cJSON* curArrItem, Service* curServ)
-{
- if (curServ == NULL || curArrItem == NULL) {
- INIT_LOGE("GetServiceCaps failed, curServ or curArrItem is NULL.");
- return SERVICE_FAILURE;
- }
- curServ->servPerm.capsCnt = 0;
- curServ->servPerm.caps = NULL;
- cJSON* filedJ = cJSON_GetObjectItem(curArrItem, "caps");
- if (filedJ == NULL) {
- return SERVICE_SUCCESS;
- }
- if (!cJSON_IsArray(filedJ)) {
- INIT_LOGE("service=%s, caps is not a list, error.", curServ->name);
- return SERVICE_FAILURE;
- }
- // caps array does not exist, means do not need any capability
- int capsCnt = cJSON_GetArraySize(filedJ);
- if (capsCnt <= 0) {
- return SERVICE_SUCCESS;
- }
- if (capsCnt > MAX_CAPS_CNT_FOR_ONE_SERVICE) {
- INIT_LOGE("service=%s, too many caps[cnt %d] for one service, max is %d.",
- curServ->name, capsCnt, MAX_CAPS_CNT_FOR_ONE_SERVICE);
- return SERVICE_FAILURE;
- }
- curServ->servPerm.caps = (unsigned int*)malloc(sizeof(unsigned int) * capsCnt);
- if (curServ->servPerm.caps == NULL) {
- INIT_LOGE("GetServiceCaps, service=%s, malloc error.", curServ->name);
- return SERVICE_FAILURE;
- }
- curServ->servPerm.capsCnt = capsCnt;
- int i = 0;
- for (; i < capsCnt; ++i) { // number form
- cJSON* capJ = cJSON_GetArrayItem(filedJ, i);
- if (!cJSON_IsNumber(capJ) || cJSON_GetNumberValue(capJ) < 0) {
- // resources will be released by function: ReleaseServiceMem
- break;
- }
- curServ->servPerm.caps[i] = (unsigned int)cJSON_GetNumberValue(capJ);
- if (curServ->servPerm.caps[i] > CAP_LAST_CAP && curServ->servPerm.caps[i] != FULL_CAP) {
- // resources will be released by function: ReleaseServiceMem
- INIT_LOGE("service=%s, caps = %d, error.", curServ->name, curServ->servPerm.caps[i]);
- return SERVICE_FAILURE;
- }
- }
- if (i == capsCnt) {
- return SERVICE_SUCCESS;
- }
- int ret = GetServiceStringCaps(filedJ, curServ);
- return ret;
-}
-
diff --git a/services/src/init_cmds.c b/services/src/init_cmds.c
deleted file mode 100644
index 81b4097..0000000
--- a/services/src/init_cmds.c
+++ /dev/null
@@ -1,1293 +0,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 "init_cmds.h"
-
-#include
-#include
-#include
-#ifndef OHOS_LITE
-#include
-#endif
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "init_jobs.h"
-#include "init_log.h"
-#ifndef OHOS_LITE
-#include "init_param.h"
-#endif
-#include "init_reboot.h"
-#include "init_service_manager.h"
-#include "init_utils.h"
-#include "securec.h"
-
-#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 WAIT_MAX_COUNT 10
-
-static const char *g_supportCfg[] = {
- "/etc/patch.cfg",
- "/patch/fstab.cfg",
-};
-
-#ifndef OHOS_LITE
-int GetParamValue(const char *symValue, char *paramValue, unsigned int paramLen)
-{
- if ((symValue == NULL) || (paramValue == NULL) || (paramLen == 0)) {
- return -1;
- }
- char tmpName[MAX_PARAM_NAME_LEN] = {0};
- char tmpValue[MAX_PARAM_VALUE_LEN] = {0};
- char *p = NULL;
- char *tmpptr = NULL;
- p = strchr(symValue, '$');
- if (p == NULL) { // not has '$' copy the original string
- INIT_CHECK_RETURN_VALUE(strncpy_s(paramValue, paramLen, symValue, paramLen - 1) == EOK, -1);
- return 0;
- }
- unsigned int tmpLen = p - symValue;
- if (tmpLen > 0) { // copy '$' front string
- INIT_CHECK_RETURN_VALUE(strncpy_s(paramValue, paramLen, symValue, tmpLen) == EOK, -1);
- }
- p++;
- if (*p == '{') {
- p++;
- char *right = strchr(p, '}');
- if (right == NULL) {
- INIT_LOGE("Invalid cfg file name, miss '}'.");
- return -1;
- }
- tmpLen = right - p;
- if (tmpLen > MAX_PARAM_NAME_LEN) {
- INIT_LOGE("Parameter name longer than %d", MAX_PARAM_NAME_LEN);
- return -1;
- }
- INIT_CHECK_RETURN_VALUE(strncpy_s(tmpName, MAX_PARAM_NAME_LEN, p, tmpLen) == EOK, -1);
- tmpLen = MAX_PARAM_VALUE_LEN;
- int ret = SystemReadParam(tmpName, tmpValue, &tmpLen); // get param
- if (ret != 0) {
- INIT_LOGE("Failed to read parameter \" %s \"", tmpName);
- return -1;
- }
- // change param to new string
- INIT_CHECK_RETURN_VALUE(strncat_s(paramValue, paramLen, tmpValue, MAX_PARAM_VALUE_LEN) == EOK, -1);
- tmpptr = right + 1;
- tmpLen = paramLen - (tmpptr - symValue);
- if (*tmpptr != '\0') { // copy last string
- INIT_CHECK_RETURN_VALUE(strncat_s(paramValue, paramLen, tmpptr, tmpLen) == EOK, -1);
- }
- INIT_LOGI("paramValue is %s ", paramValue);
- return 0;
- } else {
- INIT_LOGE("Invalid cfg file name, miss '{'.");
- return -1;
- }
-}
-#else
-// For ite ohos, do not support parameter operation. just do string copy
-inline int GetParamValue(const char *symValue, char *paramValue, unsigned int paramLen)
-{
- return (strncpy_s(paramValue, paramLen, symValue, strlen(symValue)) == EOK) ? 0 : -1;
-}
-#endif
-
-static struct CmdArgs *CopyCmd(struct CmdArgs *ctx, const char *cmd, size_t allocSize)
-{
- if (cmd == NULL) {
- FreeCmd(ctx);
- return NULL;
- }
-
- ctx->argv[ctx->argc] = calloc(sizeof(char), allocSize);
- INIT_CHECK(ctx->argv[ctx->argc] != NULL, FreeCmd(ctx);
- return NULL);
- INIT_CHECK(GetParamValue(cmd, ctx->argv[ctx->argc], allocSize) == 0, FreeCmd(ctx);
- return NULL);
- ctx->argc += 1;
- ctx->argv[ctx->argc] = NULL;
- return ctx;
-}
-
-#define SKIP_SPACES(p) \
- do { \
- while (isspace(*(p))) { \
- (p)++; \
- } \
- } while (0)
-
-struct CmdArgs *GetCmd(const char *cmdContent, const char *delim, int argsCount)
-{
- INIT_CHECK_RETURN_VALUE(cmdContent != NULL && delim != NULL, NULL);
- struct CmdArgs *ctx = (struct CmdArgs *)calloc(sizeof(struct CmdArgs), 1);
- INIT_CHECK_RETURN_VALUE(ctx != NULL, NULL);
-
- ctx->argv = (char**)calloc(sizeof(char*), (size_t)(argsCount + 1));
- INIT_CHECK(ctx->argv != NULL, FreeCmd(ctx);
- return NULL);
-
- char tmpCmd[MAX_BUFFER] = {0};
- size_t cmdLength = strlen(cmdContent);
- if (cmdLength > MAX_BUFFER - 1) {
- FreeCmd(ctx);
- return NULL;
- }
-
- INIT_CHECK(strncpy_s(tmpCmd, MAX_BUFFER - 1, cmdContent, cmdLength) == EOK, FreeCmd(ctx);
- return NULL);
-
- char *p = tmpCmd;
- char *token = NULL;
- size_t allocSize = 0;
-
- // Skip lead whitespaces
- SKIP_SPACES(p);
- ctx->argc = 0;
- token = strstr(p, delim);
- if (token == NULL) { // No whitespaces
- // Make sure there is enough memory to store parameter value
- allocSize = (size_t)(cmdLength + MAX_PARAM_VALUE_LEN + 1);
- return CopyCmd(ctx, p, allocSize);
- }
-
- while (token != NULL) {
- // Too many arguments, treat rest of data as one argument
- if (ctx->argc == (argsCount - 1)) {
- break;
- }
- *token = '\0'; // replace it with '\0';
- allocSize = (size_t)((token - p) + MAX_PARAM_VALUE_LEN + 1);
- ctx = CopyCmd(ctx, p, allocSize);
- INIT_CHECK_RETURN_VALUE(ctx != NULL, NULL);
- p = token + 1; // skip '\0'
- // Skip lead whitespaces
- SKIP_SPACES(p);
- token = strstr(p, delim);
- }
-
- if (p < tmpCmd + cmdLength) {
- // no more white space or encounter max argument count
- size_t restSize = tmpCmd + cmdLength - p;
- allocSize = restSize + MAX_PARAM_VALUE_LEN + 1;
- ctx = CopyCmd(ctx, p, allocSize);
- INIT_CHECK_RETURN_VALUE(ctx != NULL, NULL);
- }
- return ctx;
-}
-
-void FreeCmd(struct CmdArgs *cmd)
-{
- INIT_CHECK_ONLY_RETURN(cmd != NULL);
- for (int i = 0; i < cmd->argc; ++i) {
- INIT_CHECK(cmd->argv[i] == NULL, free(cmd->argv[i]));
- }
- INIT_CHECK(cmd->argv == NULL, free(cmd->argv));
- free(cmd);
- return;
-}
-
-static void WriteCommon(const char *file, const char *buffer, int flags, mode_t mode)
-{
- if (file == NULL || *file == '\0' || buffer == NULL || *buffer == '\0') {
- INIT_LOGE("Invalid arugment");
- return;
- }
- char realPath[PATH_MAX] = {0};
- if (Realpath(file, realPath, sizeof(realPath)) != NULL) {
- int fd = open(realPath, flags, mode);
- if (fd >= 0) {
- size_t totalSize = strlen(buffer);
- size_t written = WriteAll(fd, buffer, totalSize);
- if (written != totalSize) {
- INIT_LOGE("Write %lu bytes to file %s failed", totalSize, file);
- }
- close(fd);
- }
- fd = -1;
- }
-}
-
-static void DoSetDomainname(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
-
- if ((ctx == NULL) || (ctx->argv == NULL) || (ctx->argc != maxArg)) {
- INIT_LOGE("Command setdomainname with invalid arugment");
- FreeCmd(ctx);
- return;
- }
-
- WriteCommon("/proc/sys/kernel/domainname", ctx->argv[0], O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC,
- S_IRUSR | S_IWUSR);
- FreeCmd(ctx);
- return;
-}
-
-static void DoSetHostname(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
-
- if ((ctx == NULL) || (ctx->argv == NULL) || (ctx->argc != maxArg)) {
- INIT_LOGE("Command sethostname with invalid arugment");
- FreeCmd(ctx);
- return;
- }
- WriteCommon("/proc/sys/kernel/hostname", ctx->argv[0], O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC,
- S_IRUSR | S_IWUSR);
- FreeCmd(ctx);
- return;
-}
-
-#ifndef OHOS_LITE
-static void DoIfup(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if ((ctx == NULL) || (ctx->argv == NULL) || (ctx->argc != maxArg)) {
- INIT_LOGE("Command ifup with invalid arguments");
- FreeCmd(ctx);
- return;
- }
-
- struct ifreq interface;
- if (strncpy_s(interface.ifr_name, IFNAMSIZ - 1, ctx->argv[0], strlen(ctx->argv[0])) != EOK) {
- INIT_LOGE("Failed to copy interface name");
- FreeCmd(ctx);
- return;
- }
-
- int fd = socket(AF_INET, SOCK_DGRAM, 0);
- if (fd >= 0) {
- do {
- if (ioctl(fd, SIOCGIFFLAGS, &interface) < 0) {
- INIT_LOGE("Failed to do ioctl with command \"SIOCGIFFLAGS\", err = %d", errno);
- break;
- }
- interface.ifr_flags |= IFF_UP;
- if (ioctl(fd, SIOCSIFFLAGS, &interface) < 0) {
- INIT_LOGE("Failed to do ioctl with command \"SIOCSIFFLAGS\", err = %d", errno);
- break;
- }
- } while (0);
- close(fd);
- fd = -1;
- }
-
- FreeCmd(ctx);
- return;
-}
-#endif
-
-static void DoSleep(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
-
- if ((ctx == NULL) || (ctx->argv == NULL) || (ctx->argc != maxArg)) {
- INIT_LOGE("Command sleep with invalid arguments");
- FreeCmd(ctx);
- return;
- }
-
- unsigned long sleepTime = strtoul(ctx->argv[0], NULL, DECIMAL_BASE);
- // Limit sleep time in 5 seconds
- const unsigned long sleepTimeLimit = 5;
- if (sleepTime > sleepTimeLimit) {
- sleepTime = sleepTimeLimit;
- }
- INIT_LOGI("Sleeping %d second(s)", sleepTime);
- sleep((unsigned int)sleepTime);
-
- FreeCmd(ctx);
- return;
-}
-
-static void DoStart(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command start with invalid arguments");
- FreeCmd(ctx);
- return;
- }
- INIT_LOGD("Starting service \" %s \"", ctx->argv[0]);
- StartServiceByName(ctx->argv[0], true);
-
- FreeCmd(ctx);
- return;
-}
-
-static void DoStop(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command stop with invalid arguments");
- FreeCmd(ctx);
- return;
- }
- INIT_LOGD("Stopping service \" %s \"", ctx->argv[0]);
- StopServiceByName(ctx->argv[0]);
-
- FreeCmd(ctx);
- return;
-}
-
-static void DoReset(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command reset with invalid arguments");
- FreeCmd(ctx);
- return;
- }
- INIT_LOGD("Reseting service %s", ctx->argv[0]);
- DoStop(ctx->argv[0], maxArg);
- DoStart(ctx->argv[0], maxArg);
-
- FreeCmd(ctx);
- return;
-}
-
-static void DoCopyInernal(const char *source, const char *target)
-{
- if (source == NULL || target == NULL) {
- INIT_LOGE("Copy file with invalid arguments");
- return;
- }
-
- struct stat st = {0};
- int srcFd = open(source, O_RDONLY | O_CLOEXEC, S_IRUSR | S_IWUSR);
- if (srcFd < 0) {
- INIT_LOGE("Open \" %s \" failed, err = %d", source, errno);
- return;
- }
-
- if (fstat(srcFd, &st) < 0) {
- INIT_LOGE("Failed to get file \" %s \" stat", source);
- close(srcFd);
- srcFd = -1;
- return;
- }
- int dstFd = open(target, O_WRONLY | O_TRUNC | O_CREAT | O_CLOEXEC, st.st_mode);
- if (dstFd >= 0) {
- char buf[MAX_COPY_BUF_SIZE] = {0};
- ssize_t readn = -1;
- bool isSuccess = true;
- while ((readn = read(srcFd, buf, MAX_COPY_BUF_SIZE - 1)) > 0) {
- ssize_t writen = WriteAll(dstFd, buf, (size_t)readn);
- if (writen != readn) {
- isSuccess = false;
- break;
- }
- }
- if (!isSuccess) {
- INIT_LOGE("Copy from \" %s \" to \" %s \" failed", source, target);
- } else {
- fsync(dstFd);
- }
- close(dstFd);
- dstFd = -1;
- }
- close(srcFd);
- srcFd = -1;
-}
-
-static void DoCopy(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != DEFAULT_COPY_ARGS_CNT) {
- INIT_LOGE("Command copy with invalid arguments");
- FreeCmd(ctx);
- return;
- }
- char srcPath[PATH_MAX] = {0};
- char dstPath[PATH_MAX] = {0};
- if ((Realpath(ctx->argv[0], srcPath, sizeof(srcPath)) == NULL) ||
- (Realpath(ctx->argv[1], dstPath, sizeof(dstPath)) == NULL)) {
- FreeCmd(ctx);
- ctx = NULL;
- return;
- }
-
- DoCopyInernal(srcPath, dstPath);
- FreeCmd(ctx);
- ctx = NULL;
- return;
-}
-
-static int Chown(const char *path, const char *uid, const char *gid)
-{
- if (path == NULL || uid == NULL || gid == NULL) {
- return -1;
- }
- uid_t user = DecodeUid(uid);
- gid_t group = DecodeUid(gid);
- if (user == (uid_t) -1 || group == (uid_t)-1) {
- INIT_LOGE("Change path owner with invalid user/group");
- return -1;
- }
-
- int rc = chown(path, user, group);
- if (rc < 0) {
- INIT_LOGE("Change path \" %s \" ower to user: %s group: %s failed",
- path, uid, gid);
- return -1;
- }
- return 0;
-}
-
-static void DoChown(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command chown with invalid arguments");
- FreeCmd(ctx);
- return;
- }
- const int uidPos = 0;
- const int gidPos = 1;
- const int pathPos = 2;
- int ret = Chown(ctx->argv[pathPos], ctx->argv[uidPos], ctx->argv[gidPos]);
- if (ret < 0) {
- INIT_LOGE("Run command chown failed");
- }
- FreeCmd(ctx);
- return;
-}
-
-static void DoMkDir(const char *cmdContent, int maxArg)
-{
- // mkdir support format:
- // 1.mkdir path
- // 2.mkdir path mode
- // 3.mkdir path mode owner group
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc < 1) {
- INIT_LOGE("Command mkdir with invalid arguments");
- FreeCmd(ctx);
- return;
- }
- int rc;
- do {
- int index = 0;
- rc = mkdir(ctx->argv[index], DEFAULT_DIR_MODE);
- if (rc < 0) {
- if (errno == EEXIST) {
- INIT_LOGE("Path \" %s \" already exist", ctx->argv[0]);
- rc = 0;
- }
- break;
- }
-
- if (ctx->argv[++index] != NULL) { // mkdir with specific mode
- mode_t mode = strtoul(ctx->argv[1], NULL, OCTAL_BASE);
- rc = chmod(ctx->argv[0], mode);
- if (rc < 0) {
- INIT_LOGE("Change path \" %s \" mode to %04o failed", ctx->argv[0], mode);
- break;
- }
- index = index + 1;
- if (ctx->argv[index] == NULL) {
- break;
- }
- if (ctx->argv[index + 1] != NULL) {
- rc = Chown(ctx->argv[0], ctx->argv[index], ctx->argv[index + 1]);
- } else {
- rc = -1;
- }
- }
- } while (0);
-
- if (rc < 0) {
- INIT_LOGE("Run command mkdir %s failed err = %d ", ctx->argv[0], errno);
- (void)rmdir(ctx->argv[0]);
- }
- FreeCmd(ctx);
-}
-
-static void DoChmod(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command chmod with invalid arguments");
- FreeCmd(ctx);
- return;
- }
-
- mode_t mode = strtoul(ctx->argv[0], NULL, OCTAL_BASE);
- if (mode != 0) {
- if (chmod(ctx->argv[1], mode) != 0) {
- INIT_LOGE("Failed to change file \" %s \" mode to %04o, err = %d", ctx->argv[1], mode, errno);
- }
- }
- FreeCmd(ctx);
- return;
-}
-
-static char* CopySubStr(const char *srcStr, size_t startPos, size_t endPos)
-{
- if (endPos <= startPos) {
- INIT_LOGE("DoMount, invalid params<%zu, %zu> for %s.", endPos, startPos, srcStr);
- return NULL;
- }
-
- size_t mallocLen = endPos - startPos + 1;
- char* retStr = (char*)malloc(mallocLen);
- if (retStr == NULL) {
- INIT_LOGE("DoMount, malloc failed! malloc size %zu, for %s.", mallocLen, srcStr);
- return NULL;
- }
-
- const char* copyStart = srcStr + startPos;
- if (memcpy_s(retStr, mallocLen, copyStart, endPos - startPos) != EOK) {
- INIT_LOGE("DoMount, memcpy_s failed for %s.", srcStr);
- free(retStr);
- return NULL;
- }
- retStr[mallocLen - 1] = '\0';
-
- // for example, source may be none
- if (strncmp(retStr, "none", strlen("none")) == 0) {
- retStr[0] = '\0';
- }
- return retStr;
-}
-
-static int GetMountFlag(unsigned long *mountflags, const char *targetStr, const char *source)
-{
- if (targetStr == NULL) {
- return 0;
- }
-
- if (strncmp(targetStr, "nodev", strlen("nodev")) == 0) {
- (*mountflags) |= MS_NODEV;
- } else if (strncmp(targetStr, "noexec", strlen("noexec")) == 0) {
- (*mountflags) |= MS_NOEXEC;
- } else if (strncmp(targetStr, "nosuid", strlen("nosuid")) == 0) {
- (*mountflags) |= MS_NOSUID;
- } else if (strncmp(targetStr, "rdonly", strlen("rdonly")) == 0) {
- (*mountflags) |= MS_RDONLY;
- } else if (strncmp(targetStr, "noatime", strlen("noatime")) == 0) {
- (*mountflags) |= MS_NOATIME;
- } else if (strncmp(targetStr, "wait", strlen("wait")) == 0) {
- WaitForFile(source, WAIT_MAX_COUNT);
- } else {
- return 0;
- }
- return 1;
-}
-
-static int CountSpaces(const char *cmdContent, size_t *spaceCnt, size_t *spacePosArr, size_t spacePosArrLen)
-{
- *spaceCnt = 0;
- size_t strLen = strlen(cmdContent);
- for (size_t i = 0; i < strLen; ++i) {
- if (cmdContent[i] == ' ') {
- ++(*spaceCnt);
- if ((*spaceCnt) > spacePosArrLen) {
- INIT_LOGE("DoMount, too many spaces, bad format for %s.", cmdContent);
- return 0;
- }
- spacePosArr[(*spaceCnt) - 1] = i;
- }
- }
-
- if ((*spaceCnt) < SPACES_CNT_IN_CMD_MIN || // spaces count should not less than 2(at least 3 items)
- spacePosArr[0] == 0 || // should not start with space
- spacePosArr[(*spaceCnt) - 1] == strLen - 1) { // should not end with space
- INIT_LOGE("DoMount, bad format for %s.", cmdContent);
- return 0;
- }
-
- // spaces should not be adjacent
- for (size_t i = 1; i < (*spaceCnt); ++i) {
- if (spacePosArr[i] == spacePosArr[i - 1] + 1) {
- INIT_LOGE("DoMount, bad format for %s.", cmdContent);
- return 0;
- }
- }
- return 1;
-}
-
-static void DoMount(const char *cmdContent, int maxArg)
-{
- size_t spaceCnt = 0;
- size_t spacePosArr[SPACES_CNT_IN_CMD_MAX] = {0};
- if (!CountSpaces(cmdContent, &spaceCnt, spacePosArr, SPACES_CNT_IN_CMD_MAX)) {
- return;
- }
-
- // format: fileSystemType source target mountFlag1 mountFlag2... data
- unsigned long mountflags = 0;
- size_t strLen = strlen(cmdContent);
- size_t indexOffset = 0;
- char* fileSysType = CopySubStr(cmdContent, 0, spacePosArr[indexOffset]);
- if (fileSysType == NULL) {
- return;
- }
-
- char* source = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, spacePosArr[indexOffset + 1]);
- if (source == NULL) {
- free(fileSysType);
- return;
- }
- ++indexOffset;
-
- // maybe only has "filesystype source target", 2 spaces
- size_t targetEndPos = (indexOffset == spaceCnt - 1) ? strLen : spacePosArr[indexOffset + 1];
- char* target = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, targetEndPos);
- if (target == NULL) {
- free(fileSysType);
- free(source);
- return;
- }
- ++indexOffset;
-
- // get mountflags, if fail, the rest part of string will be data
- while (indexOffset < spaceCnt) {
- size_t tmpStrEndPos = (indexOffset == spaceCnt - 1) ? strLen : spacePosArr[indexOffset + 1];
- char* tmpStr = CopySubStr(cmdContent, spacePosArr[indexOffset] + 1, tmpStrEndPos);
- int ret = GetMountFlag(&mountflags, tmpStr, source);
- free(tmpStr);
- tmpStr = NULL;
-
- // get flag failed, the rest part of string will be data
- if (ret == 0) {
- break;
- }
- ++indexOffset;
- }
-
- int mountRet;
- if (indexOffset >= spaceCnt) { // no data
- mountRet = mount(source, target, fileSysType, mountflags, NULL);
- } else {
- const char* dataStr = cmdContent + spacePosArr[indexOffset] + 1;
- mountRet = mount(source, target, fileSysType, mountflags, dataStr);
- }
-
- if (mountRet != 0) {
- INIT_LOGE("DoMount, failed for %s, err %d.", cmdContent, errno);
- }
-
- free(fileSysType);
- free(source);
- free(target);
-}
-
-#ifndef OHOS_LITE
-#define OPTIONS_SIZE 128u
-static void DoInsmodInternal(const char *fileName, const char *secondPtr, const char *restPtr, int flags)
-{
- char options[OPTIONS_SIZE] = {0};
- if (flags == 0) { // '-f' option
- if (restPtr != NULL && secondPtr != NULL) { // Reset arugments, combine then all.
- if (snprintf_s(options, sizeof(options), OPTIONS_SIZE -1, "%s %s", secondPtr, restPtr) == -1) {
- return;
- }
- } else if (secondPtr != NULL) {
- if (strncpy_s(options, OPTIONS_SIZE - 1, secondPtr, strlen(secondPtr)) != 0) {
- return;
- }
- }
- } else { // Only restPtr is option
- if (restPtr != NULL) {
- if (strncpy_s(options, OPTIONS_SIZE - 1, restPtr, strlen(restPtr)) != 0) {
- return;
- }
- }
- }
- if (fileName == NULL) {
- return;
- }
- char realPath[PATH_MAX] = {0};
- if (Realpath(fileName, realPath, sizeof(realPath)) == NULL) {
- return;
- }
- int fd = open(realPath, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
- if (fd < 0) {
- INIT_LOGE("failed to open %s: %d", realPath, errno);
- return;
- }
- int rc = syscall(__NR_finit_module, fd, options, flags);
- if (rc == -1) {
- INIT_LOGE("finit_module for %s failed: %d", realPath, errno);
- }
- if (fd >= 0) {
- close(fd);
- }
- return;
-}
-
-// format insmod [-f] [options]
-static void DoInsmod(const char *cmdContent, int maxArg)
-{
- char *p = NULL;
- char *restPtr = NULL;
- char *fileName = NULL;
- char *line = NULL;
- int flags = 0;
-
- size_t count = strlen(cmdContent);
- if (count > OPTIONS_SIZE) {
- INIT_LOGE("DoInsmod options too long, maybe lost some of options");
- }
- line = (char *)malloc(count + 1);
- if (line == NULL) {
- INIT_LOGE("DoInsmod allocate memory failed.");
- return;
- }
-
- if (memcpy_s(line, count + 1, cmdContent, count) != EOK) {
- INIT_LOGE("DoInsmod memcpy failed");
- free(line);
- return;
- }
- line[count] = '\0';
- do {
- if ((p = strtok_r(line, " ", &restPtr)) == NULL) {
- INIT_LOGE("DoInsmod cannot get filename.");
- free(line);
- return;
- }
- fileName = p;
- INIT_LOGI("DoInsmod fileName is [%s].", fileName);
- if ((p = strtok_r(NULL, " ", &restPtr)) == NULL) {
- break;
- }
- if (!strcmp(p, "-f")) {
- flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS;
- }
- } while (0);
- DoInsmodInternal(fileName, p, restPtr, flags);
- if (line != NULL) {
- free(line);
- }
- return;
-}
-
-static void DoSetParam(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command setparam with invalid arguments");
- FreeCmd(ctx);
- return;
- }
- INIT_LOGD("param name: %s, value %s ", ctx->argv[0], ctx->argv[1]);
- SystemWriteParam(ctx->argv[0], ctx->argv[1]);
-
- FreeCmd(ctx);
- return;
-}
-
-
-static void DoLoadPersistParams(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command load_persist_params with invalid arguments");
- FreeCmd(ctx);
- return;
- }
- INIT_LOGD("load persist params : %s", cmdContent);
- LoadPersistParams();
- FreeCmd(ctx);
- return;
-}
-
-static void DoTriggerCmd(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command trigger with invalid arguments");
- FreeCmd(ctx);
- return;
- }
- INIT_LOGD("Trigger job :%s", ctx->argv[0]);
- DoTriggerExec(ctx->argv[0]);
- FreeCmd(ctx);
- return;
-}
-
-static void DoLoadDefaultParams(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command load_param with invalid arguments");
- FreeCmd(ctx);
- return;
- }
- int mode = 0;
- if (strcmp(ctx->argv[1], "onlyadd") == 0) {
- mode = LOAD_PARAM_ONLY_ADD;
- }
- LoadDefaultParams(ctx->argv[0], mode);
- FreeCmd(ctx);
- return;
-}
-
-#endif // OHOS_LITE
-
-static bool CheckValidCfg(const char *path)
-{
- size_t cfgCnt = ARRAY_LENGTH(g_supportCfg);
- struct stat fileStat = {0};
-
- if (stat(path, &fileStat) != 0 || fileStat.st_size <= 0 || fileStat.st_size > LOADCFG_MAX_FILE_LEN) {
- return false;
- }
-
- for (size_t i = 0; i < cfgCnt; ++i) {
- if (strcmp(path, g_supportCfg[i]) == 0) {
- return true;
- }
- }
- return false;
-}
-
-static void DoLoadCfg(const char *path, int maxArg)
-{
- char buf[LOADCFG_BUF_SIZE] = {0};
- FILE *fp = NULL;
- size_t maxLoop = 0;
- CmdLine *cmdLine = NULL;
- size_t len;
- INIT_CHECK_ONLY_RETURN(path != NULL);
- INIT_LOGI("DoLoadCfg cfg file %s", path);
- if (!CheckValidCfg(path)) {
- INIT_LOGE("CheckCfg file %s Failed", path);
- return;
- }
- INIT_ERROR_CHECK(path != NULL, return, "CheckCfg path is NULL.");
- char realPath[PATH_MAX] = {0};
- if (Realpath(path, realPath, sizeof(realPath)) == NULL) {
- return;
- }
- fp = fopen(realPath, "r");
- if (fp == NULL) {
- INIT_LOGE("open cfg error = %d", errno);
- return;
- }
-
- cmdLine = (CmdLine *)malloc(sizeof(CmdLine));
- if (cmdLine == NULL) {
- INIT_LOGE("malloc cmdline error");
- fclose(fp);
- return;
- }
-
- while (fgets(buf, LOADCFG_BUF_SIZE - 1, fp) != NULL && maxLoop < LOADCFG_MAX_LOOP) {
- maxLoop++;
- len = strlen(buf);
- if (len < 1) {
- continue;
- }
- if (buf[len - 1] == '\n') {
- buf[len - 1] = '\0'; // we replace '\n' with '\0'
- }
- (void)memset_s(cmdLine, sizeof(CmdLine), 0, sizeof(CmdLine));
- ParseCmdLine(buf, cmdLine);
- DoCmd(cmdLine);
- (void)memset_s(buf, sizeof(char) * LOADCFG_BUF_SIZE, 0, sizeof(char) * LOADCFG_BUF_SIZE);
- }
- free(cmdLine);
- fclose(fp);
-}
-
-static void DoWrite(const char *cmdContent, int maxArg)
-{
- // format: write path content
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argv[0] == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command write with invalid arguments");
- FreeCmd(ctx);
- return;
- }
-
- WriteCommon(ctx->argv[0], ctx->argv[1], O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC,
- S_IRUSR | S_IWUSR);
-
- FreeCmd(ctx);
- return;
-}
-
-static void DoRmdir(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command rmdir with invalid arguments");
- FreeCmd(ctx);
- return;
- }
-
- int ret = rmdir(ctx->argv[0]);
- if (ret == -1) {
- INIT_LOGE("Remove directory \" %s \" failed, err = %d", ctx->argv[0], errno);
- }
- FreeCmd(ctx);
- return;
-}
-
-static void DoRebootCmd(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command reboot with invalid arguments");
- FreeCmd(ctx);
- return;
- }
- DoReboot(cmdContent);
- FreeCmd(ctx);
- return;
-}
-
-static void DoSetrlimit(const char *cmdContent, int maxArg)
-{
- static const char *resource[] = {
- "RLIMIT_CPU", "RLIMIT_FSIZE", "RLIMIT_DATA", "RLIMIT_STACK", "RLIMIT_CORE", "RLIMIT_RSS",
- "RLIMIT_NPROC", "RLIMIT_NOFILE", "RLIMIT_MEMLOCK", "RLIMIT_AS", "RLIMIT_LOCKS", "RLIMIT_SIGPENDING",
- "RLIMIT_MSGQUEUE", "RLIMIT_NICE", "RLIMIT_RTPRIO", "RLIMIT_RTTIME", "RLIM_NLIMITS"
- };
- // format: setrlimit resource curValue maxValue
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- const int rlimMaxPos = 2;
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command setrlimit with invalid arguments");
- FreeCmd(ctx);
- return;
- }
-
- struct rlimit limit;
- limit.rlim_cur = (rlim_t)atoi(ctx->argv[1]);
- limit.rlim_max = (rlim_t)atoi(ctx->argv[rlimMaxPos]);
- int rcs = -1;
- for (unsigned int i = 0; i < ARRAY_LENGTH(resource); ++i) {
- if (strcmp(ctx->argv[0], resource[i]) == 0) {
- rcs = (int)i;
- }
- }
- if (rcs == -1) {
- INIT_LOGE("Set limit with unsupported resource \" %s \"", ctx->argv[0]);
- } else {
- int ret = setrlimit(rcs, &limit);
- if (ret) {
- INIT_LOGE("Set limit with resource %s, value : %lu, max value: %lu failed, err = %d",
- ctx->argv[0], limit.rlim_cur, limit.rlim_max, errno);
- }
- }
- FreeCmd(ctx);
- return;
-}
-
-static void DoRm(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command rm with invalid arguments");
- FreeCmd(ctx);
- return;
- }
- int ret = unlink(ctx->argv[0]);
- if (ret == -1) {
- INIT_LOGE("Unlink %s failed, err = %d", ctx->argv[0], errno);
- }
- FreeCmd(ctx);
- return;
-}
-
-static void DoExport(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command export with invalid arguments");
- FreeCmd(ctx);
- return;
- }
- int ret = setenv(ctx->argv[0], ctx->argv[1], 1);
- if (ret != 0) {
- INIT_LOGE("export env name \" %s \", value \" %s \" failed, err = %d ",
- ctx->argv[0], ctx->argv[1], errno);
- }
-
- FreeCmd(ctx);
- return;
-}
-
-static void DoExec(const char *cmdContent, int maxArg)
-{
- 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 *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argv[0] == NULL) {
- INIT_LOGE("Command exec with invalid arguments");
- _exit(0x7f);
- }
-#ifdef OHOS_LITE
- int ret = execve(ctx->argv[0], ctx->argv, NULL);
-#else
- int ret = execv(ctx->argv[0], ctx->argv);
-#endif
- if (ret == -1) {
- INIT_LOGE("DoExec: execute \"%s\" failed: %d.", cmdContent, errno);
- }
- FreeCmd(ctx);
- _exit(0x7f);
- }
- return;
-}
-
-#ifndef __LITEOS__
-static void DoSymlink(const char *cmdContent, int maxArg)
-{
- // format: symlink /xxx/xxx/xxx /xxx/xxx/xxx
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command symlink with invalid arguments");
- FreeCmd(ctx);
- return;
- }
-
- int ret = symlink(ctx->argv[0], ctx->argv[1]);
- if (ret != 0) {
- INIT_LOGE("Link \" %s \" to target \" %s \" failed, err = %d", ctx->argv[0], ctx->argv[1], errno);
- }
-
- FreeCmd(ctx);
- return;
-}
-
-static mode_t GetDeviceMode(const char *deviceStr)
-{
- switch (*deviceStr) {
- case 'b':
- case 'B':
- return S_IFBLK;
- case 'c':
- case 'C':
- return S_IFCHR;
- case 'f':
- case 'F':
- return S_IFIFO;
- default:
- return -1;
- }
-}
-
-static void DoMakeNode(const char *cmdContent, int maxArg)
-{
- // format: mknod path b 0644 1 9
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
- const int deviceTypePos = 1;
- const int authorityPos = 2;
- const int majorDevicePos = 3;
- const int minorDevicePos = 4;
-
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command mknode with invalid arguments");
- FreeCmd(ctx);
- return;
- }
-
- if (!access(ctx->argv[1], F_OK)) {
- INIT_LOGE("Cannot access \" %s \", err = %d", ctx->argv[1], errno);
- } else {
- mode_t deviceMode = GetDeviceMode(ctx->argv[deviceTypePos]);
- unsigned int major = strtoul(ctx->argv[majorDevicePos], NULL, DECIMAL_BASE);
- unsigned int minor = strtoul(ctx->argv[minorDevicePos], NULL, DECIMAL_BASE);
- mode_t mode = strtoul(ctx->argv[authorityPos], NULL, OCTAL_BASE);
-
- int ret = mknod(ctx->argv[0], deviceMode | mode, makedev(major, minor));
- if (ret != 0) {
- INIT_LOGE("Create device node \" %s \" failed, err = %d", ctx->argv[0], errno);
- }
- }
-
- FreeCmd(ctx);
- return;
-}
-
-static void DoMakeDevice(const char *cmdContent, int maxArg)
-{
- struct CmdArgs *ctx = GetCmd(cmdContent, " ", maxArg);
-
- if (ctx == NULL || ctx->argv == NULL || ctx->argc != maxArg) {
- INIT_LOGE("Command makedev with invalid arguments");
- FreeCmd(ctx);
- return;
- }
- unsigned int major = strtoul(ctx->argv[0], NULL, DECIMAL_BASE);
- unsigned int minor = strtoul(ctx->argv[1], NULL, DECIMAL_BASE);
- if (major == 0 || minor == 0) {
- FreeCmd(ctx);
- return;
- }
- dev_t deviceId = makedev(major, minor);
- if (deviceId < 0) {
- INIT_LOGE("Make device with major %u, minor %u failed :%d ", major, minor, errno);
- }
-
- FreeCmd(ctx);
- return;
-}
-#endif // __LITEOS__
-
-void DoCmd(const CmdLine *curCmd)
-{
- // null curCmd or empty command, just quit.
- if (curCmd == NULL || curCmd->name[0] == '\0') {
- return;
- }
- DoCmdByName(curCmd->name, curCmd->cmdContent);
-}
-
-struct CmdTable {
- char name[MAX_CMD_NAME_LEN];
- int maxArg;
- void (*DoFuncion)(const char *cmdContent, int maxArg);
-};
-
-static const struct CmdTable CMD_TABLE[] = {
- { "start ", 1, DoStart },
- { "mkdir ", 4, DoMkDir },
- { "chmod ", 2, DoChmod },
- { "chown ", 3, DoChown },
- { "mount ", 10, DoMount },
- { "export ", 2, DoExport },
- { "loadcfg ", 1, DoLoadCfg },
- { "rm ", 1, DoRm },
- { "rmdir ", 1, DoRmdir },
- { "write ", 2, DoWrite },
- { "exec ", 10, DoExec },
-#ifndef OHOS_LITE
- { "mknode ", 5, DoMakeNode },
- { "makedev ", 2, DoMakeDevice },
- { "symlink ", 2, DoSymlink },
- { "trigger ", 1, DoTriggerCmd },
- { "insmod ", 10, DoInsmod },
- { "setparam ", 2, DoSetParam },
- { "load_persist_params ", 1, DoLoadPersistParams },
- { "load_param ", 2, DoLoadDefaultParams },
- { "ifup ", 1, DoIfup },
-#endif
- { "stop ", 1, DoStop },
- { "reset ", 1, DoReset },
- { "copy ", 2, DoCopy },
- { "reboot ", 1, DoRebootCmd },
- { "setrlimit ", 3, DoSetrlimit },
- { "sleep ", 1, DoSleep },
- { "hostname ", 1, DoSetHostname },
- { "domainname ", 1, DoSetDomainname }
-};
-
-void DoCmdByName(const char *name, const char *cmdContent)
-{
- if (name == NULL || cmdContent == NULL) {
- return;
- }
-
- size_t cmdCnt = ARRAY_LENGTH(CMD_TABLE);
- unsigned int i = 0;
- for (; i < cmdCnt; ++i) {
- if (strncmp(name, CMD_TABLE[i].name, strlen(CMD_TABLE[i].name)) == 0) {
- CMD_TABLE[i].DoFuncion(cmdContent, CMD_TABLE[i].maxArg);
- break;
- }
- }
- if (i == cmdCnt) {
- INIT_LOGE("DoCmd, unknown cmd name %s.", name);
- }
-}
-
-void ParseCmdLine(const char *cmdStr, CmdLine *resCmd)
-{
- size_t cmdLineLen = 0;
- if (cmdStr == NULL || resCmd == NULL || (cmdLineLen = strlen(cmdStr)) == 0) {
- return;
- }
-
- size_t supportCmdCnt = ARRAY_LENGTH(CMD_TABLE);
- int foundAndSucceed = 0;
- for (size_t i = 0; i < supportCmdCnt; ++i) {
- size_t curCmdNameLen = strlen(CMD_TABLE[i].name);
- if (cmdLineLen > curCmdNameLen && cmdLineLen <= (curCmdNameLen + MAX_CMD_CONTENT_LEN) &&
- strncmp(CMD_TABLE[i].name, cmdStr, curCmdNameLen) == 0) {
- if (memcpy_s(resCmd->name, MAX_CMD_NAME_LEN, cmdStr, curCmdNameLen) != EOK) {
- break;
- }
- resCmd->name[curCmdNameLen] = '\0';
-
- const char* cmdContent = cmdStr + curCmdNameLen;
- size_t cmdContentLen = cmdLineLen - curCmdNameLen;
- if (memcpy_s(resCmd->cmdContent, MAX_CMD_CONTENT_LEN, cmdContent, cmdContentLen) != EOK) {
- break;
- }
- resCmd->cmdContent[cmdContentLen] = '\0';
- foundAndSucceed = 1;
- break;
- }
- }
-
- if (!foundAndSucceed) {
- INIT_LOGE("Cannot parse command: %s", cmdStr);
- (void)memset_s(resCmd, sizeof(*resCmd), 0, sizeof(*resCmd));
- }
-}
-
-const char *GetMatchCmd(const char *cmdStr, unsigned int *index)
-{
- if (cmdStr == NULL || index == NULL) {
- return NULL;
- }
- size_t supportCmdCnt = ARRAY_LENGTH(CMD_TABLE);
- for (size_t i = 0; i < supportCmdCnt; ++i) {
- size_t curCmdNameLen = strlen(CMD_TABLE[i].name);
- if (strncmp(CMD_TABLE[i].name, cmdStr, curCmdNameLen) == 0) {
- *index = (unsigned int)i;
- return CMD_TABLE[i].name;
- }
- }
- return NULL;
-}
-
-const char *GetCmdKey(unsigned int index)
-{
- size_t supportCmdCnt = ARRAY_LENGTH(CMD_TABLE);
- if (index >= supportCmdCnt) {
- return NULL;
- }
- return CMD_TABLE[index].name;
-}
diff --git a/services/src/init_import.c b/services/src/init_import.c
deleted file mode 100644
index 6ce17de..0000000
--- a/services/src/init_import.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2021 Huawei Device Co., Ltd.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "init_import.h"
-
-#include
-#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;
-}
diff --git a/services/src/init_read_cfg.c b/services/src/init_read_cfg.c
deleted file mode 100644
index 732f7db..0000000
--- a/services/src/init_read_cfg.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (c) 2020 Huawei Device Co., Ltd.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "init_read_cfg.h"
-
-#include
-#include
-#include
-#include
-#include