• 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 "fs_manager/mount.h"
17 #include <cerrno>
18 #include <fcntl.h>
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 <linux/fs.h>
26 #include "log/log.h"
27 #include "utils.h"
28 
29 namespace Updater {
30 using Updater::Utils::SplitString;
31 static std::string g_defaultUpdaterFstab = "";
32 static Fstab *g_fstab = nullptr;
33 static const std::string PARTITION_PATH = "/dev/block/by-name";
34 
GetFstabFile()35 static std::string GetFstabFile()
36 {
37     /* check vendor fstab files from specific directory */
38     std::vector<const std::string> specificFstabFiles = {"/vendor/etc/fstab.updater"};
39     for (auto& fstabFile : specificFstabFiles) {
40         if (access(fstabFile.c_str(), F_OK) == 0) {
41             return fstabFile;
42         }
43     }
44     return "";
45 }
46 
GetMountStatusForPath(const std::string & path)47 MountStatus GetMountStatusForPath(const std::string &path)
48 {
49     FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str());
50     if (item == nullptr) {
51         return MountStatus::MOUNT_ERROR;
52     }
53     return GetMountStatusForMountPoint(item->mountPoint);
54 }
55 
LoadFstab()56 void LoadFstab()
57 {
58     std::string fstabFile = g_defaultUpdaterFstab;
59     if (fstabFile.empty()) {
60         fstabFile = GetFstabFile();
61         if (fstabFile.empty()) {
62             fstabFile = "/etc/fstab.updater";
63         }
64     }
65     // Clear fstab before read fstab file.
66     if ((g_fstab = ReadFstabFromFile(fstabFile.c_str(), false)) == nullptr) {
67         LOG(WARNING) << "Read " << fstabFile << " failed";
68         return;
69     }
70 
71     LOG(DEBUG) << "Updater filesystem config info:";
72     for (FstabItem *item = g_fstab->head; item != nullptr; item = item->next) {
73         LOG(DEBUG) << "\tDevice: " << item->deviceName;
74         LOG(DEBUG) << "\tMount point : " << item->mountPoint;
75         LOG(DEBUG) << "\tFs type : " << item->fsType;
76         LOG(DEBUG) << "\tMount options: " << item->mountOptions;
77     }
78 }
79 
LoadSpecificFstab(const std::string & fstabName)80 void LoadSpecificFstab(const std::string &fstabName)
81 {
82     g_defaultUpdaterFstab = fstabName;
83     LoadFstab();
84     g_defaultUpdaterFstab = "";
85 }
86 
UmountForPath(const std::string & path)87 int UmountForPath(const std::string& path)
88 {
89     FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str());
90     if (item == nullptr) {
91         LOG(ERROR) << "Cannot find fstab item for " << path << " to umount.";
92         return -1;
93     }
94 
95     LOG(DEBUG) << "Umount for path " << path;
96     MountStatus rc = GetMountStatusForMountPoint(item->mountPoint);
97     if (rc == MOUNT_ERROR) {
98         return -1;
99     } else if (rc == MOUNT_UMOUNTED) {
100         return 0;
101     } else {
102         int ret = umount(item->mountPoint);
103         if (ret == -1) {
104             LOG(ERROR) << "Umount " << item->mountPoint << "failed: " << errno;
105             return -1;
106         }
107     }
108     return 0;
109 }
110 
MountForPath(const std::string & path)111 int MountForPath(const std::string &path)
112 {
113     FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str());
114     int ret = -1;
115     if (item == nullptr) {
116         LOG(ERROR) << "Cannot find fstab item for " << path << " to mount.";
117         return -1;
118     }
119 
120     LOG(DEBUG) << "Mount for path " << path;
121     MountStatus rc = GetMountStatusForMountPoint(item->mountPoint);
122     if (rc == MountStatus::MOUNT_ERROR) {
123         ret = -1;
124     } else if (rc == MountStatus::MOUNT_MOUNTED) {
125         LOG(INFO) << path << " already mounted";
126         ret = 0;
127     } else {
128         ret = MountOneItem(item);
129     }
130     return ret;
131 }
132 
ErasePartition(const std::string & devPath)133 void ErasePartition(const std::string &devPath)
134 {
135     std::string realPath {};
136     if (!Utils::PathToRealPath(devPath, realPath)) {
137         LOG(ERROR) << "realpath failed:" << devPath;
138         return;
139     }
140     int fd = open(realPath.c_str(), O_RDWR | O_LARGEFILE);
141     if (fd == -1) {
142         LOG(ERROR) << "open failed:" << realPath;
143         return;
144     }
145 
146     uint64_t size = 0;
147     int ret = ioctl(fd, BLKGETSIZE64, &size);
148     if (ret < 0) {
149         LOG(ERROR) << "get partition size failed:" << size;
150         close(fd);
151         return;
152     }
153 
154     LOG(INFO) << "erase partition size:" << size;
155 
156     uint64_t range[] { 0, size };
157     ret = ioctl(fd, BLKDISCARD, &range);
158     if (ret < 0) {
159         LOG(ERROR) << "erase partition failed";
160     }
161     close(fd);
162 
163     return;
164 }
165 
FormatPartition(const std::string & path,bool isZeroErase)166 int FormatPartition(const std::string &path, bool isZeroErase)
167 {
168     FstabItem *item = FindFstabItemForPath(*g_fstab, path.c_str());
169     if (item == nullptr) {
170         LOG(ERROR) << "Cannot find fstab item for " << path << " to format.";
171         return -1;
172     }
173 
174     if (strcmp(item->mountPoint, "/") == 0) {
175         /* Can not format root */
176         return 0;
177     }
178 
179     if (!IsSupportedFilesystem(item->fsType)) {
180         LOG(ERROR) << "Try to format " << item->mountPoint << " with unsupported file system type: " << item->fsType;
181         return -1;
182     }
183 
184     // Umount first
185     if (UmountForPath(path) != 0) {
186         return -1;
187     }
188 
189     if (isZeroErase) {
190         ErasePartition(item->deviceName);
191     }
192 
193     int ret = DoFormat(item->deviceName, item->fsType);
194     if (ret != 0) {
195         LOG(ERROR) << "Format " << path << " failed";
196     }
197     return ((ret != 0) ? -1 : 0);
198 }
199 
SetupPartitions(PackageUpdateMode mode)200 int SetupPartitions(PackageUpdateMode mode)
201 {
202     if (!Utils::IsUpdaterMode()) {
203         LOG(ERROR) << "live update mode";
204         return 0;
205     }
206 
207     if (g_fstab == NULL || g_fstab->head == NULL) {
208         LOG(ERROR) << "Fstab is invalid";
209         return -1;
210     }
211     for (const FstabItem *item = g_fstab->head; item != nullptr; item = item->next) {
212         std::string mountPoint(item->mountPoint);
213         std::string fsType(item->fsType);
214         if (mountPoint == "/" || mountPoint == "/tmp" || fsType == "none" ||
215             mountPoint == "/sdcard") {
216             continue;
217         }
218 
219         if (mountPoint == "/data" && mode != SDCARD_UPDATE) {
220             if (MountForPath(mountPoint) != 0) {
221                 LOG(ERROR) << "Expected partition " << mountPoint << " is not mounted.";
222                 return -1;
223             }
224             continue;
225         }
226         if (UmountForPath(mountPoint) != 0) {
227             LOG(ERROR) << "Umount " << mountPoint << " failed";
228             return -1;
229         }
230     }
231     return 0;
232 }
233 
GetBlockDeviceByMountPoint(const std::string & mountPoint)234 const std::string GetBlockDeviceByMountPoint(const std::string &mountPoint)
235 {
236     if (mountPoint.empty()) {
237         LOG(ERROR) << "mountPoint empty error.";
238         return "";
239     }
240     std::string blockDevice = PARTITION_PATH + mountPoint;
241     if (mountPoint[0] != '/') {
242         blockDevice = PARTITION_PATH + "/" + mountPoint;
243     }
244     if (g_fstab != nullptr) {
245         FstabItem *item = FindFstabItemForMountPoint(*g_fstab, mountPoint.c_str());
246         if (item != NULL) {
247             blockDevice = item->deviceName;
248         }
249     }
250     return blockDevice;
251 }
252 } // updater
253