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