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