1d9f0492fSopenharmony_ci/*
2d9f0492fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License.
5d9f0492fSopenharmony_ci * You may obtain a copy of the License at
6d9f0492fSopenharmony_ci *
7d9f0492fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8d9f0492fSopenharmony_ci *
9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and
13d9f0492fSopenharmony_ci * limitations under the License.
14d9f0492fSopenharmony_ci */
15d9f0492fSopenharmony_ci
16d9f0492fSopenharmony_ci#include <errno.h>
17d9f0492fSopenharmony_ci#include <stdlib.h>
18d9f0492fSopenharmony_ci#include <string.h>
19d9f0492fSopenharmony_ci#include <stdbool.h>
20d9f0492fSopenharmony_ci#include <sys/mount.h>
21d9f0492fSopenharmony_ci#include <sys/stat.h>
22d9f0492fSopenharmony_ci#include <sys/wait.h>
23d9f0492fSopenharmony_ci#include <unistd.h>
24d9f0492fSopenharmony_ci#include <linux/limits.h>
25d9f0492fSopenharmony_ci#include "beget_ext.h"
26d9f0492fSopenharmony_ci#include "fs_manager/fs_manager.h"
27d9f0492fSopenharmony_ci#include "init_utils.h"
28d9f0492fSopenharmony_ci#include "param/init_param.h"
29d9f0492fSopenharmony_ci#include "securec.h"
30d9f0492fSopenharmony_ci#include "switch_root.h"
31d9f0492fSopenharmony_ci#ifdef SUPPORT_HVB
32d9f0492fSopenharmony_ci#include "fs_dm.h"
33d9f0492fSopenharmony_ci#include "dm_verity.h"
34d9f0492fSopenharmony_ci#endif
35d9f0492fSopenharmony_ci#include "init_filesystems.h"
36d9f0492fSopenharmony_ci#ifdef EROFS_OVERLAY
37d9f0492fSopenharmony_ci#include "erofs_mount_overlay.h"
38d9f0492fSopenharmony_ci#endif
39d9f0492fSopenharmony_ci#ifdef __cplusplus
40d9f0492fSopenharmony_ci#if __cplusplus
41d9f0492fSopenharmony_ciextern "C" {
42d9f0492fSopenharmony_ci#endif
43d9f0492fSopenharmony_ci#endif
44d9f0492fSopenharmony_ci
45d9f0492fSopenharmony_ci#define FS_MANAGER_BUFFER_SIZE 512
46d9f0492fSopenharmony_ci#define BLOCK_SIZE_BUFFER (64)
47d9f0492fSopenharmony_ci#define RESIZE_BUFFER_SIZE 1024
48d9f0492fSopenharmony_ciconst off_t PARTITION_ACTIVE_SLOT_OFFSET = 1024;
49d9f0492fSopenharmony_ciconst off_t PARTITION_ACTIVE_SLOT_SIZE = 4;
50d9f0492fSopenharmony_ci
51d9f0492fSopenharmony_ci__attribute__((weak)) void InitPostMount(const char *mountPoint, int rc)
52d9f0492fSopenharmony_ci{
53d9f0492fSopenharmony_ci}
54d9f0492fSopenharmony_ci
55d9f0492fSopenharmony_ci__attribute__((weak)) void InitTimerControl(bool isSuspend)
56d9f0492fSopenharmony_ci{
57d9f0492fSopenharmony_ci}
58d9f0492fSopenharmony_ci
59d9f0492fSopenharmony_ci__attribute__((weak)) bool NeedDoAllResize(void)
60d9f0492fSopenharmony_ci{
61d9f0492fSopenharmony_ci    return true;
62d9f0492fSopenharmony_ci}
63d9f0492fSopenharmony_ci
64d9f0492fSopenharmony_cistatic const SUPPORTED_FILE_SYSTEM supportedFileSystems[] = {
65d9f0492fSopenharmony_ci    { "ext4", 0 },
66d9f0492fSopenharmony_ci    { "f2fs", 1 },
67d9f0492fSopenharmony_ci    { "overlay", 0 },
68d9f0492fSopenharmony_ci    { NULL, 0 }
69d9f0492fSopenharmony_ci};
70d9f0492fSopenharmony_ci
71d9f0492fSopenharmony_cistatic void **extendedFileSystems_ = NULL;
72d9f0492fSopenharmony_ci
73d9f0492fSopenharmony_civoid InitSetExtendedFileSystems(const SUPPORTED_FILE_SYSTEM *extendedFileSystems[])
74d9f0492fSopenharmony_ci{
75d9f0492fSopenharmony_ci    extendedFileSystems_ = (void **)extendedFileSystems;
76d9f0492fSopenharmony_ci}
77d9f0492fSopenharmony_ci
78d9f0492fSopenharmony_cistatic const SUPPORTED_FILE_SYSTEM *GetSupportedFileSystemInfo(const char *fsType)
79d9f0492fSopenharmony_ci{
80d9f0492fSopenharmony_ci    return (const SUPPORTED_FILE_SYSTEM *)OH_ExtendableStrDictGet((void **)supportedFileSystems,
81d9f0492fSopenharmony_ci           sizeof(SUPPORTED_FILE_SYSTEM), fsType, 0, extendedFileSystems_);
82d9f0492fSopenharmony_ci}
83d9f0492fSopenharmony_ci
84d9f0492fSopenharmony_cistatic bool IsSupportedDataType(const char *fsType)
85d9f0492fSopenharmony_ci{
86d9f0492fSopenharmony_ci    const SUPPORTED_FILE_SYSTEM *item = GetSupportedFileSystemInfo(fsType);
87d9f0492fSopenharmony_ci    if (item == NULL) {
88d9f0492fSopenharmony_ci        return false;
89d9f0492fSopenharmony_ci    }
90d9f0492fSopenharmony_ci    if (item->for_userdata) {
91d9f0492fSopenharmony_ci        return true;
92d9f0492fSopenharmony_ci    }
93d9f0492fSopenharmony_ci    return false;
94d9f0492fSopenharmony_ci}
95d9f0492fSopenharmony_ci
96d9f0492fSopenharmony_cibool IsSupportedFilesystem(const char *fsType)
97d9f0492fSopenharmony_ci{
98d9f0492fSopenharmony_ci    const SUPPORTED_FILE_SYSTEM *item = GetSupportedFileSystemInfo(fsType);
99d9f0492fSopenharmony_ci    if (item == NULL) {
100d9f0492fSopenharmony_ci        return false;
101d9f0492fSopenharmony_ci    }
102d9f0492fSopenharmony_ci    return true;
103d9f0492fSopenharmony_ci}
104d9f0492fSopenharmony_ci
105d9f0492fSopenharmony_ci/* 1024(stdout buffer size) - 256(log tag max size approximately) */
106d9f0492fSopenharmony_ci#define LOG_LINE_SZ 768
107d9f0492fSopenharmony_ci#define PIPE_FDS 2
108d9f0492fSopenharmony_ci
109d9f0492fSopenharmony_cistatic void LogToKmsg(int fd)
110d9f0492fSopenharmony_ci{
111d9f0492fSopenharmony_ci    char buffer[LOG_LINE_SZ] = {0};
112d9f0492fSopenharmony_ci    int lineMaxSize = LOG_LINE_SZ - 1;
113d9f0492fSopenharmony_ci    int pos = 0;
114d9f0492fSopenharmony_ci
115d9f0492fSopenharmony_ci    do {
116d9f0492fSopenharmony_ci        ssize_t lineSize = read(fd, buffer, lineMaxSize);
117d9f0492fSopenharmony_ci        if (lineSize < 0) {
118d9f0492fSopenharmony_ci            BEGET_LOGE("Failed to read, errno: %d", errno);
119d9f0492fSopenharmony_ci            break;
120d9f0492fSopenharmony_ci        }
121d9f0492fSopenharmony_ci        if (!lineSize) {
122d9f0492fSopenharmony_ci            /* No more lines, just break */
123d9f0492fSopenharmony_ci            break;
124d9f0492fSopenharmony_ci        }
125d9f0492fSopenharmony_ci        if (lineSize > lineMaxSize) {
126d9f0492fSopenharmony_ci            BEGET_LOGE("Invalid read size, ret: %d is larger than buffer size: %d", lineSize, lineMaxSize);
127d9f0492fSopenharmony_ci            lineSize = lineMaxSize;
128d9f0492fSopenharmony_ci        }
129d9f0492fSopenharmony_ci        /* Make sure that each line terminates with '\0' */
130d9f0492fSopenharmony_ci        buffer[lineSize] = '\0';
131d9f0492fSopenharmony_ci        int posStart = 0;
132d9f0492fSopenharmony_ci        for (pos = posStart; pos < lineSize; pos++) {
133d9f0492fSopenharmony_ci            if (buffer[pos] == '\n') {
134d9f0492fSopenharmony_ci                buffer[pos] = '\0';
135d9f0492fSopenharmony_ci                BEGET_LOGI("%s", &buffer[posStart]);
136d9f0492fSopenharmony_ci                posStart = pos + 1;
137d9f0492fSopenharmony_ci            }
138d9f0492fSopenharmony_ci        }
139d9f0492fSopenharmony_ci        if (posStart < pos) {
140d9f0492fSopenharmony_ci            BEGET_LOGI("%s", &buffer[posStart]);
141d9f0492fSopenharmony_ci        }
142d9f0492fSopenharmony_ci    } while (1);
143d9f0492fSopenharmony_ci    (void)close(fd);
144d9f0492fSopenharmony_ci}
145d9f0492fSopenharmony_ci
146d9f0492fSopenharmony_cistatic void RedirectToStdFd(int fd)
147d9f0492fSopenharmony_ci{
148d9f0492fSopenharmony_ci    if (dup2(fd, STDOUT_FILENO) < 0) {
149d9f0492fSopenharmony_ci        BEGET_LOGE("Failed to dup2 stdout, errno: %d, just continue", errno);
150d9f0492fSopenharmony_ci    }
151d9f0492fSopenharmony_ci    if (dup2(fd, STDERR_FILENO) < 0) {
152d9f0492fSopenharmony_ci        BEGET_LOGE("Failed to dup2 stderr, errno: %d, just continue", errno);
153d9f0492fSopenharmony_ci    }
154d9f0492fSopenharmony_ci    (void)close(fd);
155d9f0492fSopenharmony_ci}
156d9f0492fSopenharmony_ci
157d9f0492fSopenharmony_cistatic int ExecCommand(int argc, char **argv)
158d9f0492fSopenharmony_ci{
159d9f0492fSopenharmony_ci    BEGET_CHECK(!(argc == 0 || argv == NULL || argv[0] == NULL), return -1);
160d9f0492fSopenharmony_ci
161d9f0492fSopenharmony_ci    bool logToKmsg = false;
162d9f0492fSopenharmony_ci    int pipeFds[PIPE_FDS];
163d9f0492fSopenharmony_ci    if (pipe2(pipeFds, O_CLOEXEC) < 0) {
164d9f0492fSopenharmony_ci        BEGET_LOGE("Failed to create pipe, errno: %d, just continue", errno);
165d9f0492fSopenharmony_ci    } else {
166d9f0492fSopenharmony_ci        logToKmsg = true;
167d9f0492fSopenharmony_ci    }
168d9f0492fSopenharmony_ci
169d9f0492fSopenharmony_ci    BEGET_LOGI("Execute %s begin", argv[0]);
170d9f0492fSopenharmony_ci    pid_t pid = fork();
171d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(pid >= 0, return -1, "Fork new process to format failed: %d", errno);
172d9f0492fSopenharmony_ci    if (pid == 0) {
173d9f0492fSopenharmony_ci        if (logToKmsg) {
174d9f0492fSopenharmony_ci            (void)close(pipeFds[0]);
175d9f0492fSopenharmony_ci            RedirectToStdFd(pipeFds[1]);
176d9f0492fSopenharmony_ci        }
177d9f0492fSopenharmony_ci        execv(argv[0], argv);
178d9f0492fSopenharmony_ci        BEGET_LOGE("Failed to execv, errno: %d", errno);
179d9f0492fSopenharmony_ci        exit(-1);
180d9f0492fSopenharmony_ci    }
181d9f0492fSopenharmony_ci    if (logToKmsg) {
182d9f0492fSopenharmony_ci        (void)close(pipeFds[1]);
183d9f0492fSopenharmony_ci        LogToKmsg(pipeFds[0]);
184d9f0492fSopenharmony_ci    }
185d9f0492fSopenharmony_ci    int status = 0;
186d9f0492fSopenharmony_ci    waitpid(pid, &status, 0);
187d9f0492fSopenharmony_ci    if (WIFEXITED(status)) {
188d9f0492fSopenharmony_ci        BEGET_LOGI("Execute success, status: %d, command: %s", WEXITSTATUS(status), argv[0]);
189d9f0492fSopenharmony_ci        return WEXITSTATUS(status);
190d9f0492fSopenharmony_ci    }
191d9f0492fSopenharmony_ci    BEGET_LOGE("Failed to execute %s", argv[0]);
192d9f0492fSopenharmony_ci    return -1;
193d9f0492fSopenharmony_ci}
194d9f0492fSopenharmony_ci
195d9f0492fSopenharmony_ciint DoFormat(const char *devPath, const char *fsType)
196d9f0492fSopenharmony_ci{
197d9f0492fSopenharmony_ci    if (devPath == NULL || fsType == NULL) {
198d9f0492fSopenharmony_ci        return -1;
199d9f0492fSopenharmony_ci    }
200d9f0492fSopenharmony_ci
201d9f0492fSopenharmony_ci    if (!IsSupportedFilesystem(fsType)) {
202d9f0492fSopenharmony_ci        BEGET_LOGE("Do not support filesystem \" %s \"", fsType);
203d9f0492fSopenharmony_ci        return -1;
204d9f0492fSopenharmony_ci    }
205d9f0492fSopenharmony_ci    int ret = 0;
206d9f0492fSopenharmony_ci    if (strcmp(fsType, "ext4") == 0) {
207d9f0492fSopenharmony_ci        char blockSizeBuffer[BLOCK_SIZE_BUFFER] = {0};
208d9f0492fSopenharmony_ci        const unsigned int blockSize = 4096;
209d9f0492fSopenharmony_ci        ret = snprintf_s(blockSizeBuffer, BLOCK_SIZE_BUFFER, BLOCK_SIZE_BUFFER - 1, "%u", blockSize);
210d9f0492fSopenharmony_ci        BEGET_ERROR_CHECK(ret != -1, return -1, "Failed to build block size buffer");
211d9f0492fSopenharmony_ci
212d9f0492fSopenharmony_ci        char *formatCmds[] = {
213d9f0492fSopenharmony_ci            "/bin/mke2fs", "-F", "-t", (char *)fsType, "-b", blockSizeBuffer, (char *)devPath, NULL
214d9f0492fSopenharmony_ci        };
215d9f0492fSopenharmony_ci        int argc = ARRAY_LENGTH(formatCmds);
216d9f0492fSopenharmony_ci        char **argv = (char **)formatCmds;
217d9f0492fSopenharmony_ci        ret = ExecCommand(argc, argv);
218d9f0492fSopenharmony_ci    } else if (IsSupportedDataType(fsType)) {
219d9f0492fSopenharmony_ci#ifdef __MUSL__
220d9f0492fSopenharmony_ci        char *formatCmds[] = {
221d9f0492fSopenharmony_ci            "/bin/mkfs.f2fs", "-d1", "-O", "encrypt", "-O", "quota", "-O", "verity", "-O", "project_quota,extra_attr",
222d9f0492fSopenharmony_ci            "-O", "sb_checksum", (char *)devPath, NULL
223d9f0492fSopenharmony_ci        };
224d9f0492fSopenharmony_ci#else
225d9f0492fSopenharmony_ci        char *formatCmds[] = {
226d9f0492fSopenharmony_ci            "/bin/make_f2fs", "-d1", "-O", "encrypt", "-O", "quota", "-O", "verity",  "-O", "project_quota,extra_attr",
227d9f0492fSopenharmony_ci            "-O", "sb_checksum", (char *)devPath, NULL
228d9f0492fSopenharmony_ci        };
229d9f0492fSopenharmony_ci#endif
230d9f0492fSopenharmony_ci        int argc = ARRAY_LENGTH(formatCmds);
231d9f0492fSopenharmony_ci        char **argv = (char **)formatCmds;
232d9f0492fSopenharmony_ci        ret = ExecCommand(argc, argv);
233d9f0492fSopenharmony_ci    }
234d9f0492fSopenharmony_ci    return ret;
235d9f0492fSopenharmony_ci}
236d9f0492fSopenharmony_ci
237d9f0492fSopenharmony_ciMountStatus GetMountStatusForMountPoint(const char *mp)
238d9f0492fSopenharmony_ci{
239d9f0492fSopenharmony_ci    if (mp == NULL) {
240d9f0492fSopenharmony_ci        return MOUNT_ERROR;
241d9f0492fSopenharmony_ci    }
242d9f0492fSopenharmony_ci    char buffer[FS_MANAGER_BUFFER_SIZE] = {0};
243d9f0492fSopenharmony_ci    const int expectedItems = 6;
244d9f0492fSopenharmony_ci    int count = 0;
245d9f0492fSopenharmony_ci    char **mountItems = NULL;
246d9f0492fSopenharmony_ci    MountStatus status = MOUNT_ERROR;
247d9f0492fSopenharmony_ci    bool found = false;
248d9f0492fSopenharmony_ci
249d9f0492fSopenharmony_ci    FILE *fp = fopen("/proc/mounts", "r");
250d9f0492fSopenharmony_ci    BEGET_CHECK(fp != NULL, return status);
251d9f0492fSopenharmony_ci
252d9f0492fSopenharmony_ci    while (fgets(buffer, sizeof(buffer) - 1, fp) != NULL) {
253d9f0492fSopenharmony_ci        size_t n = strlen(buffer);
254d9f0492fSopenharmony_ci        if (buffer[n - 1] == '\n') {
255d9f0492fSopenharmony_ci            buffer[n - 1] = '\0';
256d9f0492fSopenharmony_ci        }
257d9f0492fSopenharmony_ci        mountItems = SplitStringExt(buffer, " ", &count, expectedItems);
258d9f0492fSopenharmony_ci        if (mountItems != NULL && count == expectedItems) {
259d9f0492fSopenharmony_ci            // Second item in /proc/mounts is mount point
260d9f0492fSopenharmony_ci            if (strcmp(mountItems[1], mp) == 0) {
261d9f0492fSopenharmony_ci                FreeStringVector(mountItems, count);
262d9f0492fSopenharmony_ci                found = true;
263d9f0492fSopenharmony_ci                break;
264d9f0492fSopenharmony_ci            }
265d9f0492fSopenharmony_ci            FreeStringVector(mountItems, count);
266d9f0492fSopenharmony_ci        }
267d9f0492fSopenharmony_ci    }
268d9f0492fSopenharmony_ci    if (found) {
269d9f0492fSopenharmony_ci        status = MOUNT_MOUNTED;
270d9f0492fSopenharmony_ci    } else if (feof(fp) > 0) {
271d9f0492fSopenharmony_ci        status = MOUNT_UMOUNTED;
272d9f0492fSopenharmony_ci    }
273d9f0492fSopenharmony_ci    (void)fclose(fp);
274d9f0492fSopenharmony_ci    fp = NULL;
275d9f0492fSopenharmony_ci    return status;
276d9f0492fSopenharmony_ci}
277d9f0492fSopenharmony_ci
278d9f0492fSopenharmony_ci#define MAX_RESIZE_PARAM_NUM 20
279d9f0492fSopenharmony_cistatic int DoResizeF2fs(const char* device, const unsigned long long size, const unsigned int fsManagerFlags)
280d9f0492fSopenharmony_ci{
281d9f0492fSopenharmony_ci    char *file = "/system/bin/resize.f2fs";
282d9f0492fSopenharmony_ci    char sizeStr[RESIZE_BUFFER_SIZE] = {0};
283d9f0492fSopenharmony_ci    char *argv[MAX_RESIZE_PARAM_NUM] = {NULL};
284d9f0492fSopenharmony_ci    int argc = 0;
285d9f0492fSopenharmony_ci
286d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(NeedDoAllResize(), return -1, "no need do resize, bucause kdump has done");
287d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(access(file, F_OK) == 0, return -1, "resize.f2fs is not exists.");
288d9f0492fSopenharmony_ci
289d9f0492fSopenharmony_ci    argv[argc++] = file;
290d9f0492fSopenharmony_ci    if (fsManagerFlags & FS_MANAGER_PROJQUOTA) {
291d9f0492fSopenharmony_ci        argv[argc++] = "-O";
292d9f0492fSopenharmony_ci        argv[argc++] = "extra_attr,project_quota";
293d9f0492fSopenharmony_ci    }
294d9f0492fSopenharmony_ci    if (fsManagerFlags & FS_MANAGER_CASEFOLD) {
295d9f0492fSopenharmony_ci        argv[argc++] = "-O";
296d9f0492fSopenharmony_ci        argv[argc++] = "casefold";
297d9f0492fSopenharmony_ci        argv[argc++] = "-C";
298d9f0492fSopenharmony_ci        argv[argc++] = "utf8";
299d9f0492fSopenharmony_ci    }
300d9f0492fSopenharmony_ci    if (fsManagerFlags & FS_MANAGER_COMPRESSION) {
301d9f0492fSopenharmony_ci        argv[argc++] = "-O";
302d9f0492fSopenharmony_ci        argv[argc++] = "extra_attr,compression";
303d9f0492fSopenharmony_ci    }
304d9f0492fSopenharmony_ci    if (fsManagerFlags & FS_MANAGER_DEDUP) {
305d9f0492fSopenharmony_ci        argv[argc++] = "-O";
306d9f0492fSopenharmony_ci        argv[argc++] = "extra_attr,dedup";
307d9f0492fSopenharmony_ci    }
308d9f0492fSopenharmony_ci
309d9f0492fSopenharmony_ci    if (size != 0) {
310d9f0492fSopenharmony_ci        unsigned long long realSize = size *
311d9f0492fSopenharmony_ci            ((unsigned long long)RESIZE_BUFFER_SIZE * RESIZE_BUFFER_SIZE / FS_MANAGER_BUFFER_SIZE);
312d9f0492fSopenharmony_ci        int len = sprintf_s(sizeStr, RESIZE_BUFFER_SIZE, "%llu", realSize);
313d9f0492fSopenharmony_ci        if (len <= 0) {
314d9f0492fSopenharmony_ci            BEGET_LOGE("Write buffer size failed.");
315d9f0492fSopenharmony_ci        }
316d9f0492fSopenharmony_ci        argv[argc++] = "-t";
317d9f0492fSopenharmony_ci        argv[argc++] = sizeStr;
318d9f0492fSopenharmony_ci    }
319d9f0492fSopenharmony_ci
320d9f0492fSopenharmony_ci    argv[argc++] = (char*)device;
321d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(argc <= MAX_RESIZE_PARAM_NUM, return -1, "argc: %d is too big.", argc);
322d9f0492fSopenharmony_ci    return ExecCommand(argc, argv);
323d9f0492fSopenharmony_ci}
324d9f0492fSopenharmony_ci
325d9f0492fSopenharmony_cistatic int DoFsckF2fs(const char* device)
326d9f0492fSopenharmony_ci{
327d9f0492fSopenharmony_ci    char *file = "/system/bin/fsck.f2fs";
328d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(access(file, F_OK) == 0, return -1, "fsck.f2fs is not exists.");
329d9f0492fSopenharmony_ci
330d9f0492fSopenharmony_ci    char *cmd[] = {
331d9f0492fSopenharmony_ci        file, "-p1", (char *)device, NULL
332d9f0492fSopenharmony_ci    };
333d9f0492fSopenharmony_ci
334d9f0492fSopenharmony_ci    int argc = ARRAY_LENGTH(cmd);
335d9f0492fSopenharmony_ci    char **argv = (char **)cmd;
336d9f0492fSopenharmony_ci    InitTimerControl(true);
337d9f0492fSopenharmony_ci    int ret = ExecCommand(argc, argv);
338d9f0492fSopenharmony_ci    InitTimerControl(false);
339d9f0492fSopenharmony_ci    return ret;
340d9f0492fSopenharmony_ci}
341d9f0492fSopenharmony_ci
342d9f0492fSopenharmony_cistatic int DoResizeExt(const char* device, const unsigned long long size)
343d9f0492fSopenharmony_ci{
344d9f0492fSopenharmony_ci    char *file = "/system/bin/resize2fs";
345d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(access(file, F_OK) == 0, return -1, "resize2fs is not exists.");
346d9f0492fSopenharmony_ci
347d9f0492fSopenharmony_ci    int ret = 0;
348d9f0492fSopenharmony_ci    if (size == 0) {
349d9f0492fSopenharmony_ci        char *cmd[] = {
350d9f0492fSopenharmony_ci            file, "-f", (char *)device, NULL
351d9f0492fSopenharmony_ci        };
352d9f0492fSopenharmony_ci        int argc = ARRAY_LENGTH(cmd);
353d9f0492fSopenharmony_ci        char **argv = (char **)cmd;
354d9f0492fSopenharmony_ci        ret = ExecCommand(argc, argv);
355d9f0492fSopenharmony_ci    } else {
356d9f0492fSopenharmony_ci        char sizeStr[RESIZE_BUFFER_SIZE] = {0};
357d9f0492fSopenharmony_ci        int len = sprintf_s(sizeStr, RESIZE_BUFFER_SIZE, "%lluM", size);
358d9f0492fSopenharmony_ci        if (len <= 0) {
359d9f0492fSopenharmony_ci            BEGET_LOGE("Write buffer size failed.");
360d9f0492fSopenharmony_ci        }
361d9f0492fSopenharmony_ci        char *cmd[] = {
362d9f0492fSopenharmony_ci            file, "-f", (char *)device, sizeStr, NULL
363d9f0492fSopenharmony_ci        };
364d9f0492fSopenharmony_ci        int argc = ARRAY_LENGTH(cmd);
365d9f0492fSopenharmony_ci        char **argv = (char **)cmd;
366d9f0492fSopenharmony_ci        ret = ExecCommand(argc, argv);
367d9f0492fSopenharmony_ci    }
368d9f0492fSopenharmony_ci    return ret;
369d9f0492fSopenharmony_ci}
370d9f0492fSopenharmony_ci
371d9f0492fSopenharmony_cistatic int DoFsckExt(const char* device)
372d9f0492fSopenharmony_ci{
373d9f0492fSopenharmony_ci    char *file = "/system/bin/e2fsck";
374d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(access(file, F_OK) == 0, return -1, "e2fsck is not exists.");
375d9f0492fSopenharmony_ci
376d9f0492fSopenharmony_ci    char *cmd[] = {
377d9f0492fSopenharmony_ci        file, "-y", (char *)device, NULL
378d9f0492fSopenharmony_ci    };
379d9f0492fSopenharmony_ci    int argc = ARRAY_LENGTH(cmd);
380d9f0492fSopenharmony_ci    char **argv = (char **)cmd;
381d9f0492fSopenharmony_ci    return ExecCommand(argc, argv);
382d9f0492fSopenharmony_ci}
383d9f0492fSopenharmony_ci
384d9f0492fSopenharmony_cistatic int Mount(const char *source, const char *target, const char *fsType,
385d9f0492fSopenharmony_ci    unsigned long flags, const char *data)
386d9f0492fSopenharmony_ci{
387d9f0492fSopenharmony_ci    struct stat st = {};
388d9f0492fSopenharmony_ci    int rc = -1;
389d9f0492fSopenharmony_ci
390d9f0492fSopenharmony_ci    bool isTrue = source == NULL || target == NULL || fsType == NULL;
391d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(!isTrue, return -1, "Invalid argument for mount.");
392d9f0492fSopenharmony_ci
393d9f0492fSopenharmony_ci    isTrue = stat(target, &st) != 0 && errno != ENOENT;
394d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(!isTrue, return -1, "Cannot get stat of \" %s \", err = %d", target, errno);
395d9f0492fSopenharmony_ci
396d9f0492fSopenharmony_ci    BEGET_CHECK((st.st_mode & S_IFMT) != S_IFLNK, unlink(target)); // link, delete it.
397d9f0492fSopenharmony_ci
398d9f0492fSopenharmony_ci    if (mkdir(target, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) {
399d9f0492fSopenharmony_ci        BEGET_ERROR_CHECK(errno == EEXIST, return -1, "Failed to create dir \" %s \", err = %d", target, errno);
400d9f0492fSopenharmony_ci    }
401d9f0492fSopenharmony_ci    errno = 0;
402d9f0492fSopenharmony_ci    if ((rc = mount(source, target, fsType, flags, data)) != 0) {
403d9f0492fSopenharmony_ci        BEGET_WARNING_CHECK(errno != EBUSY, rc = 0, "Mount %s to %s busy, ignore", source, target);
404d9f0492fSopenharmony_ci    }
405d9f0492fSopenharmony_ci    return rc;
406d9f0492fSopenharmony_ci}
407d9f0492fSopenharmony_ci
408d9f0492fSopenharmony_cistatic int GetSlotInfoFromCmdLine(const char *slotInfoName)
409d9f0492fSopenharmony_ci{
410d9f0492fSopenharmony_ci    char value[MAX_BUFFER_LEN] = {0};
411d9f0492fSopenharmony_ci    BEGET_INFO_CHECK(GetParameterFromCmdLine(slotInfoName, value, MAX_BUFFER_LEN) == 0,
412d9f0492fSopenharmony_ci        return -1, "Failed to get %s value from cmdline", slotInfoName);
413d9f0492fSopenharmony_ci    return atoi(value);
414d9f0492fSopenharmony_ci}
415d9f0492fSopenharmony_ci
416d9f0492fSopenharmony_cistatic int GetSlotInfoFromBootctrl(off_t offset, off_t size)
417d9f0492fSopenharmony_ci{
418d9f0492fSopenharmony_ci    char bootctrlDev[MAX_BUFFER_LEN] = {0};
419d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(GetBlockDevicePath("/bootctrl", bootctrlDev, MAX_BUFFER_LEN) == 0,
420d9f0492fSopenharmony_ci        return -1, "Failed to get bootctrl device");
421d9f0492fSopenharmony_ci    char *realPath = GetRealPath(bootctrlDev);
422d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(realPath != NULL, return -1, "Failed to get bootctrl device real path");
423d9f0492fSopenharmony_ci    int fd = open(realPath, O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
424d9f0492fSopenharmony_ci    free(realPath);
425d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(fd >= 0, return -1, "Failed to open bootctrl device, errno %d", errno);
426d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(lseek(fd, offset, SEEK_SET) >= 0, close(fd); return -1,
427d9f0492fSopenharmony_ci        "Failed to lseek bootctrl device fd, errno %d", errno);
428d9f0492fSopenharmony_ci    int slotInfo = 0;
429d9f0492fSopenharmony_ci    BEGET_INFO_CHECK(read(fd, &slotInfo, sizeof(slotInfo)) == size, close(fd); return -1,
430d9f0492fSopenharmony_ci        "Failed to read current slot from bootctrl, errno %d", errno);
431d9f0492fSopenharmony_ci    close(fd);
432d9f0492fSopenharmony_ci    return slotInfo;
433d9f0492fSopenharmony_ci}
434d9f0492fSopenharmony_ci
435d9f0492fSopenharmony_ciint GetBootSlots(void)
436d9f0492fSopenharmony_ci{
437d9f0492fSopenharmony_ci    return GetSlotInfoFromCmdLine("bootslots");
438d9f0492fSopenharmony_ci}
439d9f0492fSopenharmony_ci
440d9f0492fSopenharmony_ciint GetCurrentSlot(void)
441d9f0492fSopenharmony_ci{
442d9f0492fSopenharmony_ci    // get current slot from cmdline
443d9f0492fSopenharmony_ci    int currentSlot = GetSlotInfoFromCmdLine("currentslot");
444d9f0492fSopenharmony_ci    BEGET_CHECK_RETURN_VALUE(currentSlot <= 0, currentSlot);
445d9f0492fSopenharmony_ci    BEGET_LOGI("No valid slot value found from cmdline, try to get it from bootctrl");
446d9f0492fSopenharmony_ci
447d9f0492fSopenharmony_ci    // get current slot from bootctrl
448d9f0492fSopenharmony_ci    return GetSlotInfoFromBootctrl(PARTITION_ACTIVE_SLOT_OFFSET, PARTITION_ACTIVE_SLOT_SIZE);
449d9f0492fSopenharmony_ci}
450d9f0492fSopenharmony_ci
451d9f0492fSopenharmony_cistatic int DoMountOneItem(FstabItem *item)
452d9f0492fSopenharmony_ci{
453d9f0492fSopenharmony_ci    BEGET_LOGI("Mount device %s to %s", item->deviceName, item->mountPoint);
454d9f0492fSopenharmony_ci    unsigned long mountFlags;
455d9f0492fSopenharmony_ci    char fsSpecificData[FS_MANAGER_BUFFER_SIZE] = {0};
456d9f0492fSopenharmony_ci
457d9f0492fSopenharmony_ci    mountFlags = GetMountFlags(item->mountOptions, fsSpecificData, sizeof(fsSpecificData),
458d9f0492fSopenharmony_ci        item->mountPoint);
459d9f0492fSopenharmony_ci
460d9f0492fSopenharmony_ci    int retryCount = 3;
461d9f0492fSopenharmony_ci    int rc = 0;
462d9f0492fSopenharmony_ci    while (retryCount-- > 0) {
463d9f0492fSopenharmony_ci        rc = Mount(item->deviceName, item->mountPoint, item->fsType, mountFlags, fsSpecificData);
464d9f0492fSopenharmony_ci        if (rc == 0) {
465d9f0492fSopenharmony_ci            return rc;
466d9f0492fSopenharmony_ci        }
467d9f0492fSopenharmony_ci
468d9f0492fSopenharmony_ci        if (FM_MANAGER_FORMATTABLE_ENABLED(item->fsManagerFlags)) {
469d9f0492fSopenharmony_ci            BEGET_LOGI("Device is formattable");
470d9f0492fSopenharmony_ci            int ret = DoFormat(item->deviceName, item->fsType);
471d9f0492fSopenharmony_ci            BEGET_LOGI("End format image ret %d", ret);
472d9f0492fSopenharmony_ci            if (ret != 0) {
473d9f0492fSopenharmony_ci                continue;
474d9f0492fSopenharmony_ci            }
475d9f0492fSopenharmony_ci            rc = Mount(item->deviceName, item->mountPoint, item->fsType, mountFlags, fsSpecificData);
476d9f0492fSopenharmony_ci            if (rc == 0) {
477d9f0492fSopenharmony_ci                return rc;
478d9f0492fSopenharmony_ci            }
479d9f0492fSopenharmony_ci        }
480d9f0492fSopenharmony_ci        BEGET_LOGE("Mount device %s to %s failed, err = %d, retry", item->deviceName, item->mountPoint, errno);
481d9f0492fSopenharmony_ci    }
482d9f0492fSopenharmony_ci    return rc;
483d9f0492fSopenharmony_ci}
484d9f0492fSopenharmony_ci
485d9f0492fSopenharmony_ci#ifdef EROFS_OVERLAY
486d9f0492fSopenharmony_cistatic int MountItemByFsType(FstabItem *item)
487d9f0492fSopenharmony_ci{
488d9f0492fSopenharmony_ci    if (CheckIsErofs(item->deviceName)) {
489d9f0492fSopenharmony_ci        if (strcmp(item->fsType, "erofs") == 0) {
490d9f0492fSopenharmony_ci            if (IsOverlayEnable()) {
491d9f0492fSopenharmony_ci                return DoMountOverlayDevice(item);
492d9f0492fSopenharmony_ci            }
493d9f0492fSopenharmony_ci            int rc = DoMountOneItem(item);
494d9f0492fSopenharmony_ci            if (rc == 0 && strcmp(item->mountPoint, "/usr") == 0) {
495d9f0492fSopenharmony_ci                SwitchRoot("/usr");
496d9f0492fSopenharmony_ci            }
497d9f0492fSopenharmony_ci            return rc;
498d9f0492fSopenharmony_ci        } else {
499d9f0492fSopenharmony_ci            BEGET_LOGI("fsType not erofs system, device [%s] skip erofs mount process", item->deviceName);
500d9f0492fSopenharmony_ci            return 0;
501d9f0492fSopenharmony_ci        }
502d9f0492fSopenharmony_ci    }
503d9f0492fSopenharmony_ci
504d9f0492fSopenharmony_ci    if (strcmp(item->fsType, "erofs") != 0) {
505d9f0492fSopenharmony_ci        int rc = DoMountOneItem(item);
506d9f0492fSopenharmony_ci        if (rc == 0 && strcmp(item->mountPoint, "/usr") == 0) {
507d9f0492fSopenharmony_ci            SwitchRoot("/usr");
508d9f0492fSopenharmony_ci        }
509d9f0492fSopenharmony_ci        return rc;
510d9f0492fSopenharmony_ci    }
511d9f0492fSopenharmony_ci
512d9f0492fSopenharmony_ci    BEGET_LOGI("fsType is erofs system, device [%s] skip ext4 or hms mount process", item->deviceName);
513d9f0492fSopenharmony_ci    return 0;
514d9f0492fSopenharmony_ci}
515d9f0492fSopenharmony_ci#endif
516d9f0492fSopenharmony_ci
517d9f0492fSopenharmony_ciint MountOneItem(FstabItem *item)
518d9f0492fSopenharmony_ci{
519d9f0492fSopenharmony_ci    if (item == NULL) {
520d9f0492fSopenharmony_ci        return -1;
521d9f0492fSopenharmony_ci    }
522d9f0492fSopenharmony_ci
523d9f0492fSopenharmony_ci    if (FM_MANAGER_WAIT_ENABLED(item->fsManagerFlags)) {
524d9f0492fSopenharmony_ci        WaitForFile(item->deviceName, WAIT_MAX_SECOND);
525d9f0492fSopenharmony_ci    }
526d9f0492fSopenharmony_ci
527d9f0492fSopenharmony_ci    if (strcmp(item->mountPoint, "/data") == 0 && IsSupportedDataType(item->fsType)) {
528d9f0492fSopenharmony_ci        int ret = DoResizeF2fs(item->deviceName, 0, item->fsManagerFlags);
529d9f0492fSopenharmony_ci        if (ret != 0) {
530d9f0492fSopenharmony_ci            BEGET_LOGE("Failed to resize.f2fs dir %s , ret = %d", item->deviceName, ret);
531d9f0492fSopenharmony_ci        }
532d9f0492fSopenharmony_ci
533d9f0492fSopenharmony_ci        ret = DoFsckF2fs(item->deviceName);
534d9f0492fSopenharmony_ci        if (ret != 0) {
535d9f0492fSopenharmony_ci            BEGET_LOGE("Failed to fsck.f2fs dir %s , ret = %d", item->deviceName, ret);
536d9f0492fSopenharmony_ci        }
537d9f0492fSopenharmony_ci    } else if (strcmp(item->fsType, "ext4") == 0 && strcmp(item->mountPoint, "/data") == 0) {
538d9f0492fSopenharmony_ci        int ret = DoResizeExt(item->deviceName, 0);
539d9f0492fSopenharmony_ci        if (ret != 0) {
540d9f0492fSopenharmony_ci            BEGET_LOGE("Failed to resize2fs dir %s , ret = %d", item->deviceName, ret);
541d9f0492fSopenharmony_ci        }
542d9f0492fSopenharmony_ci        ret = DoFsckExt(item->deviceName);
543d9f0492fSopenharmony_ci        if (ret != 0) {
544d9f0492fSopenharmony_ci            BEGET_LOGE("Failed to e2fsck dir %s , ret = %d", item->deviceName, ret);
545d9f0492fSopenharmony_ci        }
546d9f0492fSopenharmony_ci    }
547d9f0492fSopenharmony_ci
548d9f0492fSopenharmony_ci    int rc = 0;
549d9f0492fSopenharmony_ci#ifdef EROFS_OVERLAY
550d9f0492fSopenharmony_ci    rc = MountItemByFsType(item);
551d9f0492fSopenharmony_ci#else
552d9f0492fSopenharmony_ci    rc = DoMountOneItem(item);
553d9f0492fSopenharmony_ci    if (rc == 0 && (strcmp(item->mountPoint, "/usr") == 0)) {
554d9f0492fSopenharmony_ci        SwitchRoot("/usr");
555d9f0492fSopenharmony_ci    }
556d9f0492fSopenharmony_ci#endif
557d9f0492fSopenharmony_ci    InitPostMount(item->mountPoint, rc);
558d9f0492fSopenharmony_ci    if (rc != 0) {
559d9f0492fSopenharmony_ci        if (FM_MANAGER_NOFAIL_ENABLED(item->fsManagerFlags)) {
560d9f0492fSopenharmony_ci            BEGET_LOGE("Mount no fail device %s to %s failed, err = %d", item->deviceName, item->mountPoint, errno);
561d9f0492fSopenharmony_ci        } else {
562d9f0492fSopenharmony_ci            BEGET_LOGW("Mount %s to %s failed, err = %d. Ignore failure", item->deviceName, item->mountPoint, errno);
563d9f0492fSopenharmony_ci            rc = 0;
564d9f0492fSopenharmony_ci        }
565d9f0492fSopenharmony_ci    } else {
566d9f0492fSopenharmony_ci        BEGET_LOGI("Mount %s to %s successful", item->deviceName, item->mountPoint);
567d9f0492fSopenharmony_ci    }
568d9f0492fSopenharmony_ci    return rc;
569d9f0492fSopenharmony_ci}
570d9f0492fSopenharmony_ci
571d9f0492fSopenharmony_ci#if defined EROFS_OVERLAY && defined SUPPORT_HVB
572d9f0492fSopenharmony_cistatic bool NeedDmVerity(FstabItem *item)
573d9f0492fSopenharmony_ci{
574d9f0492fSopenharmony_ci    if (CheckIsErofs(item->deviceName)) {
575d9f0492fSopenharmony_ci        if (strcmp(item->fsType, "erofs") == 0) {
576d9f0492fSopenharmony_ci            return true;
577d9f0492fSopenharmony_ci        }
578d9f0492fSopenharmony_ci    } else {
579d9f0492fSopenharmony_ci        if (strcmp(item->fsType, "erofs") != 0) {
580d9f0492fSopenharmony_ci            return true;
581d9f0492fSopenharmony_ci        }
582d9f0492fSopenharmony_ci    }
583d9f0492fSopenharmony_ci    return false;
584d9f0492fSopenharmony_ci}
585d9f0492fSopenharmony_ci#endif
586d9f0492fSopenharmony_ci
587d9f0492fSopenharmony_cistatic void AdjustPartitionNameByPartitionSlot(FstabItem *item)
588d9f0492fSopenharmony_ci{
589d9f0492fSopenharmony_ci    BEGET_CHECK_ONLY_RETURN(strstr(item->deviceName, "/system") != NULL ||
590d9f0492fSopenharmony_ci        strstr(item->deviceName, "/vendor") != NULL);
591d9f0492fSopenharmony_ci    char buffer[MAX_BUFFER_LEN] = {0};
592d9f0492fSopenharmony_ci    int slot = GetCurrentSlot();
593d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(slot > 0 && slot <= MAX_SLOT, slot = 1, "slot value %d is invalid, set default value", slot);
594d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(sprintf_s(buffer, sizeof(buffer), "%s_%c", item->deviceName, 'a' + slot - 1) > 0,
595d9f0492fSopenharmony_ci        return, "Failed to format partition name suffix, use default partition name");
596d9f0492fSopenharmony_ci    free(item->deviceName);
597d9f0492fSopenharmony_ci    item->deviceName = strdup(buffer);
598d9f0492fSopenharmony_ci    if (item->deviceName == NULL) {
599d9f0492fSopenharmony_ci        BEGET_LOGE("failed dup devicename");
600d9f0492fSopenharmony_ci        return;
601d9f0492fSopenharmony_ci    }
602d9f0492fSopenharmony_ci    BEGET_LOGI("partition name with slot suffix: %s", item->deviceName);
603d9f0492fSopenharmony_ci}
604d9f0492fSopenharmony_ci
605d9f0492fSopenharmony_cistatic int CheckRequiredAndMount(FstabItem *item, bool required)
606d9f0492fSopenharmony_ci{
607d9f0492fSopenharmony_ci    int rc = 0;
608d9f0492fSopenharmony_ci    if (item == NULL) {
609d9f0492fSopenharmony_ci        return -1;
610d9f0492fSopenharmony_ci    }
611d9f0492fSopenharmony_ci
612d9f0492fSopenharmony_ci    // Mount partition during second startup.
613d9f0492fSopenharmony_ci    if (!required) {
614d9f0492fSopenharmony_ci        if (!FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) {
615d9f0492fSopenharmony_ci            rc = MountOneItem(item);
616d9f0492fSopenharmony_ci        }
617d9f0492fSopenharmony_ci        return rc;
618d9f0492fSopenharmony_ci    }
619d9f0492fSopenharmony_ci
620d9f0492fSopenharmony_ci    // Mount partition during one startup.
621d9f0492fSopenharmony_ci    if (FM_MANAGER_REQUIRED_ENABLED(item->fsManagerFlags)) {
622d9f0492fSopenharmony_ci        int bootSlots = GetBootSlots();
623d9f0492fSopenharmony_ci        BEGET_INFO_CHECK(bootSlots <= 1, AdjustPartitionNameByPartitionSlot(item),
624d9f0492fSopenharmony_ci            "boot slots is %d, now adjust partition name according to current slot", bootSlots);
625d9f0492fSopenharmony_ci#ifdef SUPPORT_HVB
626d9f0492fSopenharmony_ci#ifdef EROFS_OVERLAY
627d9f0492fSopenharmony_ci        if (!NeedDmVerity(item)) {
628d9f0492fSopenharmony_ci            BEGET_LOGI("not need dm verity, do mount item %s", item->deviceName);
629d9f0492fSopenharmony_ci            return MountOneItem(item);
630d9f0492fSopenharmony_ci        }
631d9f0492fSopenharmony_ci#endif
632d9f0492fSopenharmony_ci        rc = HvbDmVeritySetUp(item);
633d9f0492fSopenharmony_ci        if (rc != 0) {
634d9f0492fSopenharmony_ci            BEGET_LOGE("set dm_verity err, ret = 0x%x", rc);
635d9f0492fSopenharmony_ci            if (!FM_MANAGER_NOFAIL_ENABLED(item->fsManagerFlags)) {
636d9f0492fSopenharmony_ci                rc = 0;
637d9f0492fSopenharmony_ci                BEGET_LOGW("DmVeritySetUp fail for %s, ignore error and do not mount", item->deviceName);
638d9f0492fSopenharmony_ci            } else {
639d9f0492fSopenharmony_ci                BEGET_LOGE("DmVeritySetUp fail for no fail devices %s, error!", item->deviceName);
640d9f0492fSopenharmony_ci            }
641d9f0492fSopenharmony_ci            return rc;
642d9f0492fSopenharmony_ci        }
643d9f0492fSopenharmony_ci#endif
644d9f0492fSopenharmony_ci        rc = MountOneItem(item);
645d9f0492fSopenharmony_ci    }
646d9f0492fSopenharmony_ci    return rc;
647d9f0492fSopenharmony_ci}
648d9f0492fSopenharmony_ci
649d9f0492fSopenharmony_ciint MountAllWithFstab(const Fstab *fstab, bool required)
650d9f0492fSopenharmony_ci{
651d9f0492fSopenharmony_ci    BEGET_CHECK(fstab != NULL, return -1);
652d9f0492fSopenharmony_ci
653d9f0492fSopenharmony_ci    FstabItem *item = NULL;
654d9f0492fSopenharmony_ci    int rc = -1;
655d9f0492fSopenharmony_ci
656d9f0492fSopenharmony_ci#ifdef SUPPORT_HVB
657d9f0492fSopenharmony_ci    if (required) {
658d9f0492fSopenharmony_ci        rc = HvbDmVerityinit(fstab);
659d9f0492fSopenharmony_ci        if (rc != 0) {
660d9f0492fSopenharmony_ci            BEGET_LOGE("set dm_verity init, ret = 0x%x", rc);
661d9f0492fSopenharmony_ci            return rc;
662d9f0492fSopenharmony_ci        }
663d9f0492fSopenharmony_ci    }
664d9f0492fSopenharmony_ci#endif
665d9f0492fSopenharmony_ci
666d9f0492fSopenharmony_ci    for (item = fstab->head; item != NULL; item = item->next) {
667d9f0492fSopenharmony_ci        rc = CheckRequiredAndMount(item, required);
668d9f0492fSopenharmony_ci        if (required && (rc < 0)) { // Init fail to mount in the first stage and exit directly.
669d9f0492fSopenharmony_ci            break;
670d9f0492fSopenharmony_ci        }
671d9f0492fSopenharmony_ci    }
672d9f0492fSopenharmony_ci
673d9f0492fSopenharmony_ci#ifdef SUPPORT_HVB
674d9f0492fSopenharmony_ci    if (required)
675d9f0492fSopenharmony_ci        HvbDmVerityFinal();
676d9f0492fSopenharmony_ci#endif
677d9f0492fSopenharmony_ci
678d9f0492fSopenharmony_ci    return rc;
679d9f0492fSopenharmony_ci}
680d9f0492fSopenharmony_ci
681d9f0492fSopenharmony_ciint MountAllWithFstabFile(const char *fstabFile, bool required)
682d9f0492fSopenharmony_ci{
683d9f0492fSopenharmony_ci    bool isFile = fstabFile == NULL || *fstabFile == '\0';
684d9f0492fSopenharmony_ci    BEGET_CHECK(!isFile, return -1);
685d9f0492fSopenharmony_ci
686d9f0492fSopenharmony_ci    Fstab *fstab = NULL;
687d9f0492fSopenharmony_ci    if ((fstab = ReadFstabFromFile(fstabFile, false)) == NULL) {
688d9f0492fSopenharmony_ci        BEGET_LOGE("[fs_manager][error] Read fstab file \" %s \" failed\n", fstabFile);
689d9f0492fSopenharmony_ci        return -1;
690d9f0492fSopenharmony_ci    }
691d9f0492fSopenharmony_ci
692d9f0492fSopenharmony_ci    int rc = MountAllWithFstab(fstab, required);
693d9f0492fSopenharmony_ci    if (rc != 0) {
694d9f0492fSopenharmony_ci        BEGET_LOGE("[startup_failed]MountAllWithFstab failed %s %d %d %d", fstabFile, FSTAB_MOUNT_FAILED, required, rc);
695d9f0492fSopenharmony_ci    }
696d9f0492fSopenharmony_ci    ReleaseFstab(fstab);
697d9f0492fSopenharmony_ci    fstab = NULL;
698d9f0492fSopenharmony_ci    return rc;
699d9f0492fSopenharmony_ci}
700d9f0492fSopenharmony_ci
701d9f0492fSopenharmony_ciint UmountAllWithFstabFile(const char *fstabFile)
702d9f0492fSopenharmony_ci{
703d9f0492fSopenharmony_ci    bool isFile = fstabFile == NULL || *fstabFile == '\0';
704d9f0492fSopenharmony_ci    BEGET_CHECK(!isFile, return -1);
705d9f0492fSopenharmony_ci
706d9f0492fSopenharmony_ci    Fstab *fstab = NULL;
707d9f0492fSopenharmony_ci    fstab = ReadFstabFromFile(fstabFile, false);
708d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(fstab != NULL, return -1, "Read fstab file \" %s \" failed.", fstabFile);
709d9f0492fSopenharmony_ci
710d9f0492fSopenharmony_ci    FstabItem *item = NULL;
711d9f0492fSopenharmony_ci    int rc = -1;
712d9f0492fSopenharmony_ci    for (item = fstab->head; item != NULL; item = item->next) {
713d9f0492fSopenharmony_ci        BEGET_LOGI("Umount %s.", item->mountPoint);
714d9f0492fSopenharmony_ci        MountStatus status = GetMountStatusForMountPoint(item->mountPoint);
715d9f0492fSopenharmony_ci        if (status == MOUNT_ERROR) {
716d9f0492fSopenharmony_ci            BEGET_LOGW("Cannot get mount status of mount point \" %s \"", item->mountPoint);
717d9f0492fSopenharmony_ci            continue; // Cannot get mount status, just ignore it and try next one.
718d9f0492fSopenharmony_ci        } else if (status == MOUNT_UMOUNTED) {
719d9f0492fSopenharmony_ci            BEGET_LOGI("Mount point \" %s \" already unmounted. device path: %s, fs type: %s.",
720d9f0492fSopenharmony_ci                item->mountPoint, item->deviceName, item->fsType);
721d9f0492fSopenharmony_ci            continue;
722d9f0492fSopenharmony_ci        } else {
723d9f0492fSopenharmony_ci            rc = umount(item->mountPoint);
724d9f0492fSopenharmony_ci            if (rc == -1) {
725d9f0492fSopenharmony_ci                BEGET_LOGE("Umount %s failed, device path: %s, fs type: %s, err = %d.",
726d9f0492fSopenharmony_ci                    item->mountPoint, item->deviceName, item->fsType, errno);
727d9f0492fSopenharmony_ci            } else {
728d9f0492fSopenharmony_ci                BEGET_LOGE("Umount %s successfully.", item->mountPoint);
729d9f0492fSopenharmony_ci            }
730d9f0492fSopenharmony_ci        }
731d9f0492fSopenharmony_ci    }
732d9f0492fSopenharmony_ci    ReleaseFstab(fstab);
733d9f0492fSopenharmony_ci    fstab = NULL;
734d9f0492fSopenharmony_ci    return rc;
735d9f0492fSopenharmony_ci}
736d9f0492fSopenharmony_ci
737d9f0492fSopenharmony_ciint FsManagerDmRemoveDevice(const char *devName)
738d9f0492fSopenharmony_ci{
739d9f0492fSopenharmony_ci#ifdef SUPPORT_HVB
740d9f0492fSopenharmony_ci    return FsDmRemoveDevice(devName);
741d9f0492fSopenharmony_ci#endif
742d9f0492fSopenharmony_ci    return 0;
743d9f0492fSopenharmony_ci}
744d9f0492fSopenharmony_ci
745d9f0492fSopenharmony_ciint MountOneWithFstabFile(const char *fstabFile, const char *devName, bool required)
746d9f0492fSopenharmony_ci{
747d9f0492fSopenharmony_ci    bool isFile = fstabFile == NULL || *fstabFile == '\0';
748d9f0492fSopenharmony_ci    BEGET_CHECK(!isFile, return -1);
749d9f0492fSopenharmony_ci
750d9f0492fSopenharmony_ci    Fstab *fstab = NULL;
751d9f0492fSopenharmony_ci    fstab = ReadFstabFromFile(fstabFile, false);
752d9f0492fSopenharmony_ci    BEGET_ERROR_CHECK(fstab != NULL, return -1, "Read fstab file \" %s \" failed.", fstabFile);
753d9f0492fSopenharmony_ci
754d9f0492fSopenharmony_ci    FstabItem *item = NULL;
755d9f0492fSopenharmony_ci    int rc = -1;
756d9f0492fSopenharmony_ci
757d9f0492fSopenharmony_ci#ifdef SUPPORT_HVB
758d9f0492fSopenharmony_ci    if (required) {
759d9f0492fSopenharmony_ci        rc = HvbDmVerityinit(fstab);
760d9f0492fSopenharmony_ci        if (rc != 0) {
761d9f0492fSopenharmony_ci            BEGET_LOGE("set dm_verity init, ret = 0x%x", rc);
762d9f0492fSopenharmony_ci            return rc;
763d9f0492fSopenharmony_ci        }
764d9f0492fSopenharmony_ci    }
765d9f0492fSopenharmony_ci#endif
766d9f0492fSopenharmony_ci
767d9f0492fSopenharmony_ci    for (item = fstab->head; item != NULL; item = item->next) {
768d9f0492fSopenharmony_ci        if (strcmp(item->mountPoint, devName) == 0) {
769d9f0492fSopenharmony_ci            rc = CheckRequiredAndMount(item, required);
770d9f0492fSopenharmony_ci            break;
771d9f0492fSopenharmony_ci        }
772d9f0492fSopenharmony_ci    }
773d9f0492fSopenharmony_ci
774d9f0492fSopenharmony_ci#ifdef SUPPORT_HVB
775d9f0492fSopenharmony_ci    if (required) {
776d9f0492fSopenharmony_ci        HvbDmVerityFinal();
777d9f0492fSopenharmony_ci    }
778d9f0492fSopenharmony_ci#endif
779d9f0492fSopenharmony_ci
780d9f0492fSopenharmony_ci    ReleaseFstab(fstab);
781d9f0492fSopenharmony_ci    fstab = NULL;
782d9f0492fSopenharmony_ci    return rc;
783d9f0492fSopenharmony_ci}
784d9f0492fSopenharmony_ci
785d9f0492fSopenharmony_ci#ifdef __cplusplus
786d9f0492fSopenharmony_ci#if __cplusplus
787d9f0492fSopenharmony_ci}
788d9f0492fSopenharmony_ci#endif
789d9f0492fSopenharmony_ci#endif
790