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 "fs_manager/mount.h"
17 #include <cerrno>
18 #include <map>
19 #include <string>
20 #include <sys/mount.h>
21 #include <sys/stat.h>
22 #include <sys/wait.h>
23 #include <unistd.h>
24 #include <vector>
25 #include "log/log.h"
26 #include "utils.h"
27
28 namespace updater {
29 using updater::utils::SplitString;
30 static std::string g_defaultUpdaterFstab = "";
31 static Fstab *g_fstab;
GetFstabFile()32 static std::string GetFstabFile()
33 {
34 /* check vendor fstab files from specific directory */
35 std::vector<const std::string> specificFstabFiles = {"/vendor/etc/fstab.updater"};
36 for (auto& fstabFile : specificFstabFiles) {
37 if (access(fstabFile.c_str(), F_OK) == 0) {
38 return fstabFile;
39 }
40 }
41 return "";
42 }
43
GetMountStatusForPath(const std::string & path)44 MountStatus GetMountStatusForPath(const std::string &path)
45 {
46 FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str());
47 if (item == nullptr) {
48 return MountStatus::MOUNT_ERROR;
49 }
50 return GetMountStatusForMountPoint(item->mountPoint);
51 }
52
LoadFstab()53 void LoadFstab()
54 {
55 std::string fstabFile = g_defaultUpdaterFstab;
56 if (fstabFile.empty()) {
57 fstabFile = GetFstabFile();
58 if (fstabFile.empty()) {
59 fstabFile = "/etc/fstab.updater";
60 }
61 }
62 // Clear fstab before read fstab file.
63 if ((g_fstab = ReadFstabFromFile(fstabFile.c_str(), false)) == nullptr) {
64 LOG(WARNING) << "Read " << fstabFile << " failed";
65 return;
66 }
67
68 LOG(DEBUG) << "Updater filesystem config info:";
69 for (FstabItem *item = g_fstab->head; item != nullptr; item = item->next) {
70 LOG(DEBUG) << "\tDevice: " << item->deviceName;
71 LOG(DEBUG) << "\tMount point : " << item->mountPoint;
72 LOG(DEBUG) << "\tFs type : " << item->fsType;
73 LOG(DEBUG) << "\tMount options: " << item->mountOptions;
74 }
75 }
76
LoadSpecificFstab(const std::string & fstabName)77 void LoadSpecificFstab(const std::string &fstabName)
78 {
79 g_defaultUpdaterFstab = fstabName;
80 LoadFstab();
81 g_defaultUpdaterFstab = "";
82 }
83
UmountForPath(const std::string & path)84 int UmountForPath(const std::string& path)
85 {
86 FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str());
87 if (item == nullptr) {
88 LOG(ERROR) << "Cannot find fstab item for " << path << " to umount.";
89 return -1;
90 }
91
92 LOG(DEBUG) << "Umount for path " << path;
93 MountStatus rc = GetMountStatusForMountPoint(item->mountPoint);
94 if (rc == MOUNT_ERROR) {
95 return -1;
96 } else if (rc == MOUNT_UMOUNTED) {
97 return 0;
98 } else {
99 int ret = umount(item->mountPoint);
100 if (ret == -1) {
101 LOG(ERROR) << "Umount " << item->mountPoint << "failed: " << errno;
102 return -1;
103 }
104 }
105 return 0;
106 }
107
MountForPath(const std::string & path)108 int MountForPath(const std::string &path)
109 {
110 FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str());
111 int ret = -1;
112 if (item == nullptr) {
113 LOG(ERROR) << "Cannot find fstab item for " << path << " to mount.";
114 return -1;
115 }
116
117 LOG(DEBUG) << "Mount for path " << path;
118 MountStatus rc = GetMountStatusForMountPoint(item->mountPoint);
119 if (rc == MountStatus::MOUNT_ERROR) {
120 ret = -1;
121 } else if (rc == MountStatus::MOUNT_MOUNTED) {
122 LOG(INFO) << path << " already mounted";
123 ret = 0;
124 } else {
125 ret = MountOneItem(item);
126 }
127 return ret;
128 }
129
FormatPartition(const std::string & path)130 int FormatPartition(const std::string &path)
131 {
132 FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str());
133 if (item == nullptr) {
134 LOG(ERROR) << "Cannot find fstab item for " << path << " to format.";
135 return -1;
136 }
137
138 if (strcmp(item->mountPoint, "/") == 0) {
139 /* Can not format root */
140 return 0;
141 }
142
143 if (!IsSupportedFilesystem(item->fsType)) {
144 LOG(ERROR) << "Try to format " << item->mountPoint << " with unsupported file system type: " << item->fsType;
145 return -1;
146 }
147
148 // Umount first
149 if (UmountForPath(path) != 0) {
150 return -1;
151 }
152 int ret = DoFormat(item->deviceName, item->fsType);
153 if (ret != 0) {
154 LOG(ERROR) << "Format " << path << " failed";
155 }
156 return ((ret != 0) ? -1 : 0);
157 }
158
SetupPartitions()159 int SetupPartitions()
160 {
161 if (g_fstab == NULL || g_fstab->head == NULL) {
162 LOG(ERROR) << "Fstab is invalid";
163 return -1;
164 }
165 for (const FstabItem *item = g_fstab->head; item != nullptr; item = item->next) {
166 std::string mountPoint(item->mountPoint);
167 std::string fsType(item->fsType);
168 if (mountPoint == "/" || mountPoint == "/tmp" || fsType == "none" ||
169 mountPoint == "/sdcard") {
170 continue;
171 }
172
173 if (mountPoint == "/data") {
174 if (MountForPath(mountPoint) != 0) {
175 LOG(ERROR) << "Expected partition " << mountPoint << " is not mounted.";
176 return -1;
177 }
178 continue;
179 }
180 if (UmountForPath(mountPoint) != 0) {
181 LOG(ERROR) << "Umount " << mountPoint << " failed";
182 return -1;
183 }
184 }
185 return 0;
186 }
187
GetBlockDeviceByMountPoint(const std::string & mountPoint)188 const std::string GetBlockDeviceByMountPoint(const std::string &mountPoint)
189 {
190 std::string blockDevice = "";
191 if (!mountPoint.empty()) {
192 FstabItem *item = FindFstabItemForMountPoint(*g_fstab, mountPoint.c_str());
193 if (item != NULL) {
194 blockDevice = item->deviceName;
195 }
196 }
197 return blockDevice;
198 }
199 } // updater
200