• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "android-base/file.h"
18 #include "fs_mgr/roots.h"
19 
20 #include <sys/mount.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 
24 #include <string>
25 
26 #include "fs_mgr.h"
27 #include "fs_mgr_dm_linear.h"
28 #include "fs_mgr_priv.h"
29 
30 namespace android {
31 namespace fs_mgr {
32 
33 static constexpr const char* kSystemRoot = "/system";
34 
35 static bool gDidMapLogicalPartitions = false;
36 
GetEntryForPath(Fstab * fstab,const std::string & path)37 FstabEntry* GetEntryForPath(Fstab* fstab, const std::string& path) {
38     if (path.empty()) return nullptr;
39     std::string str(path);
40     while (true) {
41         auto entry = GetEntryForMountPoint(fstab, str);
42         if (entry != nullptr) return entry;
43         str = android::base::Dirname(str);
44         if (!str.compare(".") || !str.compare("/")) break;
45     }
46     return nullptr;
47 }
48 
GetEntriesForPath(Fstab * fstab,const std::string & path)49 std::vector<FstabEntry*> GetEntriesForPath(Fstab* fstab, const std::string& path) {
50     std::vector<FstabEntry*> entries;
51     if (path.empty()) return entries;
52 
53     std::string str(path);
54     while (true) {
55         entries = GetEntriesForMountPoint(fstab, str);
56         if (!entries.empty()) return entries;
57         str = android::base::Dirname(str);
58         if (!str.compare(".") || !str.compare("/")) break;
59     }
60     return entries;
61 }
62 
63 enum class MountState {
64     ERROR = -1,
65     NOT_MOUNTED = 0,
66     MOUNTED = 1,
67 };
68 
GetMountState(const std::string & mount_point)69 static MountState GetMountState(const std::string& mount_point) {
70     Fstab mounted_fstab;
71     if (!ReadFstabFromFile("/proc/mounts", &mounted_fstab)) {
72         LERROR << "Failed to scan mounted volumes";
73         return MountState::ERROR;
74     }
75 
76     auto mv = GetEntryForMountPoint(&mounted_fstab, mount_point);
77     if (mv != nullptr) {
78         return MountState::MOUNTED;
79     }
80     return MountState::NOT_MOUNTED;
81 }
82 
TryPathMount(FstabEntry * rec,const std::string & mount_pt)83 bool TryPathMount(FstabEntry* rec, const std::string& mount_pt) {
84     if (rec->fs_type == "ramdisk") {
85         // The ramdisk is always mounted.
86         return true;
87     }
88 
89     // If we can't acquire the block device for a logical partition, it likely
90     // was never created. In that case we try to create it.
91     if (rec->fs_mgr_flags.logical && !fs_mgr_update_logical_partition(rec)) {
92         if (gDidMapLogicalPartitions) {
93             LERROR << "Failed to find block device for partition";
94             return false;
95         }
96         std::string super_name = fs_mgr_get_super_partition_name();
97         if (!android::fs_mgr::CreateLogicalPartitions("/dev/block/by-name/" + super_name)) {
98             LERROR << "Failed to create logical partitions";
99             return false;
100         }
101         gDidMapLogicalPartitions = true;
102         if (!fs_mgr_update_logical_partition(rec)) {
103             LERROR << "Failed to find block device for partition";
104             return false;
105         }
106     }
107 
108     const std::string mount_point = mount_pt.empty() ? rec->mount_point : mount_pt;
109 
110     auto mounted = GetMountState(mount_point);
111     if (mounted == MountState::ERROR) {
112         return false;
113     }
114     if (mounted == MountState::MOUNTED) {
115         return true;
116     }
117 
118     static const std::vector<std::string> supported_fs{"ext4", "squashfs", "vfat", "exfat", "f2fs",
119                                                        "erofs", "none"};
120     if (std::find(supported_fs.begin(), supported_fs.end(), rec->fs_type) == supported_fs.end()) {
121         LERROR << "unknown fs_type \"" << rec->fs_type << "\" for " << mount_point;
122         return false;
123     }
124 
125     int result = fs_mgr_do_mount_one(*rec, mount_point);
126     if (result == -1 && rec->fs_mgr_flags.formattable) {
127         PERROR << "Failed to mount " << mount_point << "; formatting";
128         if (fs_mgr_do_format(*rec) != 0) {
129             PERROR << "Failed to format " << mount_point;
130             return false;
131         }
132         result = fs_mgr_do_mount_one(*rec, mount_point);
133     }
134 
135     if (result == -1) {
136         PERROR << "Failed to mount " << mount_point;
137         return false;
138     }
139     return true;
140 }
141 
EnsurePathMounted(Fstab * fstab,const std::string & path,const std::string & mount_point)142 bool EnsurePathMounted(Fstab* fstab, const std::string& path, const std::string& mount_point) {
143     auto entries = GetEntriesForPath(fstab, path);
144     if (entries.empty()) {
145         LERROR << "unknown volume for path [" << path << "]";
146         return false;
147     }
148 
149     for (auto entry : entries) {
150         if (TryPathMount(entry, mount_point)) return true;
151     }
152 
153     LERROR << "Failed to mount for path [" << path << "]";
154     return false;
155 }
156 
EnsurePathUnmounted(Fstab * fstab,const std::string & path)157 bool EnsurePathUnmounted(Fstab* fstab, const std::string& path) {
158     auto rec = GetEntryForPath(fstab, path);
159     if (rec == nullptr) {
160         LERROR << "unknown volume for path [" << path << "]";
161         return false;
162     }
163     if (rec->fs_type == "ramdisk") {
164         // The ramdisk is always mounted; you can't unmount it.
165         return false;
166     }
167 
168     Fstab mounted_fstab;
169     if (!ReadFstabFromFile("/proc/mounts", &mounted_fstab)) {
170         LERROR << "Failed to scan mounted volumes";
171         return false;
172     }
173 
174     auto mounted = GetMountState(rec->mount_point);
175     if (mounted == MountState::ERROR) {
176         return false;
177     }
178     if (mounted == MountState::NOT_MOUNTED) {
179         return true;
180     }
181 
182     int result = umount(rec->mount_point.c_str());
183     if (result == -1) {
184         PWARNING << "Failed to umount " << rec->mount_point;
185         return false;
186     }
187     return true;
188 }
189 
GetSystemRoot()190 std::string GetSystemRoot() {
191     Fstab fstab;
192     if (!ReadDefaultFstab(&fstab)) {
193         LERROR << "Failed to read default fstab";
194         return "";
195     }
196 
197     auto entry = GetEntryForMountPoint(&fstab, kSystemRoot);
198     if (entry == nullptr) {
199         return "/";
200     }
201 
202     return kSystemRoot;
203 }
204 
LogicalPartitionsMapped()205 bool LogicalPartitionsMapped() {
206     return gDidMapLogicalPartitions;
207 }
208 
209 }  // namespace fs_mgr
210 }  // namespace android
211