1 /*
2 * Copyright (C) 2023 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 #include "mount.h"
16
17 #include <sys/mount.h>
18 #include <securec.h>
19 #include <fcntl.h>
20 #include <unistd.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23
FindMountDeviceByPath(const char * toQuery,char * dev)24 bool FindMountDeviceByPath(const char *toQuery, char *dev)
25 {
26 int fd;
27 int res;
28 char *token = nullptr;
29 const char delims[] = "\n";
30 char buf[BUF_SIZE_DEFAULT2];
31
32 fd = open("/proc/mounts", O_RDONLY | O_CLOEXEC);
33 if (fd < 0) {
34 return false;
35 }
36 read(fd, buf, sizeof(buf) - 1);
37 close(fd);
38 buf[sizeof(buf) - 1] = '\0';
39 token = strtok(buf, delims);
40
41 while (token) {
42 char dir[BUF_SIZE_SMALL] = "";
43 int freq;
44 int passnno;
45 // clang-format off
46 res = sscanf_s(token, "%255s %255s %*s %*s %d %d\n", dev, strlen(dev),
47 dir, sizeof(dir), &freq, &passnno);
48 // clang-format on
49 dev[BUF_SIZE_SMALL - 1] = '\0';
50 dir[BUF_SIZE_SMALL - 1] = '\0';
51 if (res == 4 && (strcmp(toQuery, dir) == 0)) { // 4 : The correct number of parameters
52 return true;
53 }
54 token = strtok(nullptr, delims);
55 }
56 return false;
57 }
58
RemountPartition(const char * dir)59 bool RemountPartition(const char *dir)
60 {
61 int fd;
62 int off = 0;
63 char dev[BUF_SIZE_SMALL] = "";
64
65 if (!FindMountDeviceByPath(dir, dev) || strlen(dev) < 4) { // 4 : file count
66 return false;
67 }
68
69 if ((fd = open(dev, O_RDONLY | O_CLOEXEC)) < 0) {
70 return false;
71 }
72 ioctl(fd, BLKROSET, &off);
73 close(fd);
74
75 if (mount(dev, dir, "none", MS_REMOUNT, nullptr) < 0) {
76 return false;
77 }
78 return true;
79 }
80
RemountDevice()81 bool RemountDevice()
82 {
83 if (getuid() != 0) {
84 return false;
85 }
86 struct stat info;
87 if (!lstat("/vendor", &info) && (info.st_mode & S_IFMT) == S_IFDIR) {
88 // has vendor
89 if (!RemountPartition("/vendor")) {
90 return false;
91 }
92 }
93 if (!lstat("/data", &info) && (info.st_mode & S_IFMT) == S_IFDIR) {
94 if (!RemountPartition("/data")) {
95 return false;
96 }
97 }
98 return true;
99 }