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