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
InitPostMount(const char * mountPoint,int rc,const char * fsType)51 __attribute__((weak)) void InitPostMount(const char *mountPoint, int rc, const char *fsType)
52 {
53 }
54
InitTimerControl(bool isSuspend)55 __attribute__((weak)) void InitTimerControl(bool isSuspend)
56 {
57 }
58
NeedDoAllResize(void)59 __attribute__((weak)) bool NeedDoAllResize(void)
60 {
61 BEGET_LOGE("kdump: static\n");
62 return true;
63 }
64
65 static const SUPPORTED_FILE_SYSTEM supportedFileSystems[] = {
66 { "ext4", 0 },
67 { "f2fs", 1 },
68 { "overlay", 0 },
69 { NULL, 0 }
70 };
71
72 static void **extendedFileSystems_ = NULL;
73
InitSetExtendedFileSystems(const SUPPORTED_FILE_SYSTEM * extendedFileSystems[])74 void InitSetExtendedFileSystems(const SUPPORTED_FILE_SYSTEM *extendedFileSystems[])
75 {
76 extendedFileSystems_ = (void **)extendedFileSystems;
77 }
78
GetSupportedFileSystemInfo(const char * fsType)79 static const SUPPORTED_FILE_SYSTEM *GetSupportedFileSystemInfo(const char *fsType)
80 {
81 return (const SUPPORTED_FILE_SYSTEM *)OH_ExtendableStrDictGet((void **)supportedFileSystems,
82 sizeof(SUPPORTED_FILE_SYSTEM), fsType, 0, extendedFileSystems_);
83 }
84
IsSupportedDataType(const char * fsType)85 static bool IsSupportedDataType(const char *fsType)
86 {
87 const SUPPORTED_FILE_SYSTEM *item = GetSupportedFileSystemInfo(fsType);
88 if (item == NULL) {
89 return false;
90 }
91 if (item->for_userdata) {
92 return true;
93 }
94 return false;
95 }
96
IsSupportedFilesystem(const char * fsType)97 bool IsSupportedFilesystem(const char *fsType)
98 {
99 const SUPPORTED_FILE_SYSTEM *item = GetSupportedFileSystemInfo(fsType);
100 if (item == NULL) {
101 return false;
102 }
103 return true;
104 }
105
106 /* 1024(stdout buffer size) - 256(log tag max size approximately) */
107 #define LOG_LINE_SZ 768
108 #define PIPE_FDS 2
109
LogToKmsg(int fd)110 static void LogToKmsg(int fd)
111 {
112 char buffer[LOG_LINE_SZ] = {0};
113 int lineMaxSize = LOG_LINE_SZ - 1;
114 int pos = 0;
115
116 do {
117 ssize_t lineSize = read(fd, buffer, lineMaxSize);
118 if (lineSize < 0) {
119 BEGET_LOGE("Failed to read, errno: %d", errno);
120 break;
121 }
122 if (!lineSize) {
123 /* No more lines, just break */
124 break;
125 }
126 if (lineSize > lineMaxSize) {
127 BEGET_LOGE("Invalid read size, ret: %d is larger than buffer size: %d", lineSize, lineMaxSize);
128 lineSize = lineMaxSize;
129 }
130 /* Make sure that each line terminates with '\0' */
131 buffer[lineSize] = '\0';
132 int posStart = 0;
133 for (pos = posStart; pos < lineSize; pos++) {
134 if (buffer[pos] == '\n') {
135 buffer[pos] = '\0';
136 BEGET_LOGI("%s", &buffer[posStart]);
137 posStart = pos + 1;
138 }
139 }
140 if (posStart < pos) {
141 BEGET_LOGI("%s", &buffer[posStart]);
142 }
143 } while (1);
144 (void)close(fd);
145 }
146
RedirectToStdFd(int fd)147 static void RedirectToStdFd(int fd)
148 {
149 if (dup2(fd, STDOUT_FILENO) < 0) {
150 BEGET_LOGE("Failed to dup2 stdout, errno: %d, just continue", errno);
151 }
152 if (dup2(fd, STDERR_FILENO) < 0) {
153 BEGET_LOGE("Failed to dup2 stderr, errno: %d, just continue", errno);
154 }
155 (void)close(fd);
156 }
157
ExecCommand(int argc,char ** argv)158 static int ExecCommand(int argc, char **argv)
159 {
160 BEGET_CHECK(!(argc == 0 || argv == NULL || argv[0] == NULL), return -1);
161
162 bool logToKmsg = false;
163 int pipeFds[PIPE_FDS];
164 if (pipe2(pipeFds, O_CLOEXEC) < 0) {
165 BEGET_LOGE("Failed to create pipe, errno: %d, just continue", errno);
166 } else {
167 logToKmsg = true;
168 }
169
170 BEGET_LOGI("Execute %s begin", argv[0]);
171 pid_t pid = fork();
172 BEGET_ERROR_CHECK(pid >= 0, return -1, "Fork new process to format failed: %d", errno);
173 if (pid == 0) {
174 if (logToKmsg) {
175 (void)close(pipeFds[0]);
176 RedirectToStdFd(pipeFds[1]);
177 }
178 execv(argv[0], argv);
179 BEGET_LOGE("Failed to execv, errno: %d", errno);
180 exit(-1);
181 }
182 if (logToKmsg) {
183 (void)close(pipeFds[1]);
184 LogToKmsg(pipeFds[0]);
185 }
186 int status = 0;
187 waitpid(pid, &status, 0);
188 if (WIFEXITED(status)) {
189 BEGET_LOGI("Execute success, status: %d, command: %s", WEXITSTATUS(status), argv[0]);
190 return WEXITSTATUS(status);
191 }
192 BEGET_LOGE("Failed to execute %s", argv[0]);
193 return -1;
194 }
195
DoFormat(const char * devPath,const char * fsType)196 int DoFormat(const char *devPath, const char *fsType)
197 {
198 if (devPath == NULL || fsType == NULL) {
199 return -1;
200 }
201
202 if (!IsSupportedFilesystem(fsType)) {
203 BEGET_LOGE("Do not support filesystem \" %s \"", fsType);
204 return -1;
205 }
206 int ret = 0;
207 if (strcmp(fsType, "ext4") == 0) {
208 char blockSizeBuffer[BLOCK_SIZE_BUFFER] = {0};
209 const unsigned int blockSize = 4096;
210 ret = snprintf_s(blockSizeBuffer, BLOCK_SIZE_BUFFER, BLOCK_SIZE_BUFFER - 1, "%u", blockSize);
211 BEGET_ERROR_CHECK(ret != -1, return -1, "Failed to build block size buffer");
212
213 char *formatCmds[] = {
214 "/bin/mke2fs", "-F", "-t", (char *)fsType, "-b", blockSizeBuffer, (char *)devPath, NULL
215 };
216 int argc = ARRAY_LENGTH(formatCmds);
217 char **argv = (char **)formatCmds;
218 ret = ExecCommand(argc, argv);
219 } else if (IsSupportedDataType(fsType)) {
220 #ifdef __MUSL__
221 char *formatCmds[] = {
222 "/bin/mkfs.f2fs", "-d1", "-O", "encrypt", "-O", "quota", "-O", "verity", "-O", "project_quota,extra_attr",
223 "-O", "sb_checksum", (char *)devPath, NULL
224 };
225 #else
226 char *formatCmds[] = {
227 "/bin/make_f2fs", "-d1", "-O", "encrypt", "-O", "quota", "-O", "verity", "-O", "project_quota,extra_attr",
228 "-O", "sb_checksum", (char *)devPath, NULL
229 };
230 #endif
231 int argc = ARRAY_LENGTH(formatCmds);
232 char **argv = (char **)formatCmds;
233 ret = ExecCommand(argc, argv);
234 }
235 return ret;
236 }
237
GetMountStatusForMountPoint(const char * mp)238 MountStatus GetMountStatusForMountPoint(const char *mp)
239 {
240 if (mp == NULL) {
241 return MOUNT_ERROR;
242 }
243 char buffer[FS_MANAGER_BUFFER_SIZE] = {0};
244 const int expectedItems = 6;
245 int count = 0;
246 char **mountItems = NULL;
247 MountStatus status = MOUNT_ERROR;
248 bool found = false;
249
250 FILE *fp = fopen("/proc/mounts", "r");
251 BEGET_CHECK(fp != NULL, return status);
252
253 while (fgets(buffer, sizeof(buffer) - 1, fp) != NULL) {
254 size_t n = strlen(buffer);
255 if (buffer[n - 1] == '\n') {
256 buffer[n - 1] = '\0';
257 }
258 mountItems = SplitStringExt(buffer, " ", &count, expectedItems);
259 if (mountItems != NULL && count == expectedItems) {
260 // Second item in /proc/mounts is mount point
261 if (strcmp(mountItems[1], mp) == 0) {
262 FreeStringVector(mountItems, count);
263 found = true;
264 break;
265 }
266 FreeStringVector(mountItems, count);
267 }
268 }
269 if (found) {
270 status = MOUNT_MOUNTED;
271 } else if (feof(fp) > 0) {
272 status = MOUNT_UMOUNTED;
273 }
274 (void)fclose(fp);
275 fp = NULL;
276 return status;
277 }
278
279 #define MAX_RESIZE_PARAM_NUM 20
DoResizeF2fs(const char * device,const unsigned long long size,const unsigned int fsManagerFlags)280 static int DoResizeF2fs(const char* device, const unsigned long long size, const unsigned int fsManagerFlags)
281 {
282 char *file = "/system/bin/resize.f2fs";
283 char sizeStr[RESIZE_BUFFER_SIZE] = {0};
284 char *argv[MAX_RESIZE_PARAM_NUM] = {NULL};
285 int argc = 0;
286
287 BEGET_ERROR_CHECK(NeedDoAllResize(), return -1, "no need do resize, bucause kdump has done");
288 BEGET_ERROR_CHECK(access(file, F_OK) == 0, return -1, "resize.f2fs is not exists.");
289
290 argv[argc++] = file;
291 if (fsManagerFlags & FS_MANAGER_PROJQUOTA) {
292 argv[argc++] = "-O";
293 argv[argc++] = "extra_attr,project_quota";
294 }
295 if (fsManagerFlags & FS_MANAGER_CASEFOLD) {
296 argv[argc++] = "-O";
297 argv[argc++] = "casefold";
298 argv[argc++] = "-C";
299 argv[argc++] = "utf8";
300 }
301 if (fsManagerFlags & FS_MANAGER_COMPRESSION) {
302 argv[argc++] = "-O";
303 argv[argc++] = "extra_attr,compression";
304 }
305 if (fsManagerFlags & FS_MANAGER_DEDUP) {
306 argv[argc++] = "-O";
307 argv[argc++] = "extra_attr,dedup";
308 }
309
310 if (size != 0) {
311 unsigned long long realSize = size *
312 ((unsigned long long)RESIZE_BUFFER_SIZE * RESIZE_BUFFER_SIZE / FS_MANAGER_BUFFER_SIZE);
313 int len = sprintf_s(sizeStr, RESIZE_BUFFER_SIZE, "%llu", realSize);
314 if (len <= 0) {
315 BEGET_LOGE("Write buffer size failed.");
316 }
317 argv[argc++] = "-t";
318 argv[argc++] = sizeStr;
319 }
320
321 argv[argc++] = (char*)device;
322 BEGET_ERROR_CHECK(argc <= MAX_RESIZE_PARAM_NUM, return -1, "argc: %d is too big.", argc);
323 return ExecCommand(argc, argv);
324 }
325
DoFsckF2fs(const char * device)326 static int DoFsckF2fs(const char* device)
327 {
328 char *file = "/system/bin/fsck.f2fs";
329 BEGET_ERROR_CHECK(access(file, F_OK) == 0, return -1, "fsck.f2fs is not exists.");
330
331 char *cmd[] = {
332 file, "-p1", (char *)device, NULL
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
DoResizeExt(const char * device,const unsigned long long size)342 static 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
DoFsckExt(const char * device)371 static 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
Mount(const char * source,const char * target,const char * fsType,unsigned long flags,const char * data)384 static 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
GetSlotInfoFromCmdLine(const char * slotInfoName)408 static 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
GetSlotInfoFromBootctrl(off_t offset,off_t size)416 static 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
GetBootSlots(void)435 int GetBootSlots(void)
436 {
437 return GetSlotInfoFromCmdLine("bootslots");
438 }
439
GetCurrentSlot(void)440 int 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
DoMountOneItem(FstabItem * item)451 static 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
MountItemByFsType(FstabItem * item)486 static 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
MountOneItem(FstabItem * item)517 int 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, item->fsType);
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
NeedDmVerity(FstabItem * item)572 static 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
AdjustPartitionNameByPartitionSlot(FstabItem * item)587 static 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
CheckRequiredAndMount(FstabItem * item,bool required)605 static 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
MountAllWithFstab(const Fstab * fstab,bool required)649 int 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
MountAllWithFstabFile(const char * fstabFile,bool required)681 int 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,
695 FSTAB_MOUNT_FAILED, required, rc);
696 }
697 ReleaseFstab(fstab);
698 fstab = NULL;
699 return rc;
700 }
701
UmountAllWithFstabFile(const char * fstabFile)702 int UmountAllWithFstabFile(const char *fstabFile)
703 {
704 bool isFile = fstabFile == NULL || *fstabFile == '\0';
705 BEGET_CHECK(!isFile, return -1);
706
707 Fstab *fstab = NULL;
708 fstab = ReadFstabFromFile(fstabFile, false);
709 BEGET_ERROR_CHECK(fstab != NULL, return -1, "Read fstab file \" %s \" failed.", fstabFile);
710
711 FstabItem *item = NULL;
712 int rc = -1;
713 for (item = fstab->head; item != NULL; item = item->next) {
714 BEGET_LOGI("Umount %s.", item->mountPoint);
715 MountStatus status = GetMountStatusForMountPoint(item->mountPoint);
716 if (status == MOUNT_ERROR) {
717 BEGET_LOGW("Cannot get mount status of mount point \" %s \"", item->mountPoint);
718 continue; // Cannot get mount status, just ignore it and try next one.
719 } else if (status == MOUNT_UMOUNTED) {
720 BEGET_LOGI("Mount point \" %s \" already unmounted. device path: %s, fs type: %s.",
721 item->mountPoint, item->deviceName, item->fsType);
722 continue;
723 } else {
724 rc = umount(item->mountPoint);
725 if (rc == -1) {
726 BEGET_LOGE("Umount %s failed, device path: %s, fs type: %s, err = %d.",
727 item->mountPoint, item->deviceName, item->fsType, errno);
728 } else {
729 BEGET_LOGE("Umount %s successfully.", item->mountPoint);
730 }
731 }
732 }
733 ReleaseFstab(fstab);
734 fstab = NULL;
735 return rc;
736 }
737
FsManagerDmRemoveDevice(const char * devName)738 int FsManagerDmRemoveDevice(const char *devName)
739 {
740 #ifdef SUPPORT_HVB
741 return FsDmRemoveDevice(devName);
742 #endif
743 return 0;
744 }
745
MountOneWithFstabFile(const char * fstabFile,const char * devName,bool required)746 int MountOneWithFstabFile(const char *fstabFile, const char *devName, bool required)
747 {
748 bool isFile = fstabFile == NULL || *fstabFile == '\0';
749 BEGET_CHECK(!isFile, return -1);
750
751 Fstab *fstab = NULL;
752 fstab = ReadFstabFromFile(fstabFile, false);
753 BEGET_ERROR_CHECK(fstab != NULL, return -1, "Read fstab file \" %s \" failed.", fstabFile);
754
755 FstabItem *item = NULL;
756 int rc = -1;
757
758 #ifdef SUPPORT_HVB
759 if (required) {
760 rc = HvbDmVerityinit(fstab);
761 if (rc != 0) {
762 BEGET_LOGE("set dm_verity init, ret = 0x%x", rc);
763 return rc;
764 }
765 }
766 #endif
767
768 for (item = fstab->head; item != NULL; item = item->next) {
769 if (strcmp(item->mountPoint, devName) == 0) {
770 rc = CheckRequiredAndMount(item, required);
771 break;
772 }
773 }
774
775 #ifdef SUPPORT_HVB
776 if (required) {
777 HvbDmVerityFinal();
778 }
779 #endif
780
781 ReleaseFstab(fstab);
782 fstab = NULL;
783 return rc;
784 }
785
786 #ifdef __cplusplus
787 #if __cplusplus
788 }
789 #endif
790 #endif
791