• 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 "fs_mgr/roots.h"
18 
19 #include <sys/mount.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 
23 #include <string>
24 
25 #include "fs_mgr.h"
26 #include "fs_mgr_dm_linear.h"
27 #include "fs_mgr_priv.h"
28 
29 namespace android {
30 namespace fs_mgr {
31 
32 static constexpr const char* kSystemRoot = "/system";
33 
34 static bool gDidMapLogicalPartitions = false;
35 
GetEntryForPath(Fstab * fstab,const std::string & path)36 FstabEntry* GetEntryForPath(Fstab* fstab, const std::string& path) {
37     if (path.empty()) return nullptr;
38     std::string str(path);
39     while (true) {
40         auto entry = GetEntryForMountPoint(fstab, str);
41         if (entry != nullptr) return entry;
42         if (str == "/") break;
43         auto slash = str.find_last_of('/');
44         if (slash == std::string::npos) break;
45         if (slash == 0) {
46             str = "/";
47         } else {
48             str = str.substr(0, slash);
49         }
50     }
51     return nullptr;
52 }
53 
54 enum class MountState {
55     ERROR = -1,
56     NOT_MOUNTED = 0,
57     MOUNTED = 1,
58 };
59 
GetMountState(const std::string & mount_point)60 static MountState GetMountState(const std::string& mount_point) {
61     Fstab mounted_fstab;
62     if (!ReadFstabFromFile("/proc/mounts", &mounted_fstab)) {
63         LERROR << "Failed to scan mounted volumes";
64         return MountState::ERROR;
65     }
66 
67     auto mv = GetEntryForMountPoint(&mounted_fstab, mount_point);
68     if (mv != nullptr) {
69         return MountState::MOUNTED;
70     }
71     return MountState::NOT_MOUNTED;
72 }
73 
EnsurePathMounted(Fstab * fstab,const std::string & path,const std::string & mount_pt)74 bool EnsurePathMounted(Fstab* fstab, const std::string& path, const std::string& mount_pt) {
75     auto rec = GetEntryForPath(fstab, path);
76     if (rec == nullptr) {
77         LERROR << "unknown volume for path [" << path << "]";
78         return false;
79     }
80     if (rec->fs_type == "ramdisk") {
81         // The ramdisk is always mounted.
82         return true;
83     }
84 
85     // If we can't acquire the block device for a logical partition, it likely
86     // was never created. In that case we try to create it.
87     if (rec->fs_mgr_flags.logical && !fs_mgr_update_logical_partition(rec)) {
88         if (gDidMapLogicalPartitions) {
89             LERROR << "Failed to find block device for partition";
90             return false;
91         }
92         std::string super_name = fs_mgr_get_super_partition_name();
93         if (!android::fs_mgr::CreateLogicalPartitions("/dev/block/by-name/" + super_name)) {
94             LERROR << "Failed to create logical partitions";
95             return false;
96         }
97         gDidMapLogicalPartitions = true;
98         if (!fs_mgr_update_logical_partition(rec)) {
99             LERROR << "Failed to find block device for partition";
100             return false;
101         }
102     }
103 
104     const std::string mount_point = mount_pt.empty() ? rec->mount_point : mount_pt;
105 
106     auto mounted = GetMountState(mount_point);
107     if (mounted == MountState::ERROR) {
108         return false;
109     }
110     if (mounted == MountState::MOUNTED) {
111         return true;
112     }
113 
114     static const std::vector<std::string> supported_fs{"ext4", "squashfs", "vfat", "f2fs", "erofs",
115                                                        "none"};
116     if (std::find(supported_fs.begin(), supported_fs.end(), rec->fs_type) == supported_fs.end()) {
117         LERROR << "unknown fs_type \"" << rec->fs_type << "\" for " << mount_point;
118         return false;
119     }
120 
121     int result = fs_mgr_do_mount_one(*rec, mount_point);
122     if (result == -1 && rec->fs_mgr_flags.formattable) {
123         PERROR << "Failed to mount " << mount_point << "; formatting";
124         bool crypt_footer = rec->is_encryptable() && rec->key_loc == "footer";
125         if (fs_mgr_do_format(*rec, crypt_footer) != 0) {
126             PERROR << "Failed to format " << mount_point;
127             return false;
128         }
129         result = fs_mgr_do_mount_one(*rec, mount_point);
130     }
131 
132     if (result == -1) {
133         PERROR << "Failed to mount " << mount_point;
134         return false;
135     }
136     return true;
137 }
138 
EnsurePathUnmounted(Fstab * fstab,const std::string & path)139 bool EnsurePathUnmounted(Fstab* fstab, const std::string& path) {
140     auto rec = GetEntryForPath(fstab, path);
141     if (rec == nullptr) {
142         LERROR << "unknown volume for path [" << path << "]";
143         return false;
144     }
145     if (rec->fs_type == "ramdisk") {
146         // The ramdisk is always mounted; you can't unmount it.
147         return false;
148     }
149 
150     Fstab mounted_fstab;
151     if (!ReadFstabFromFile("/proc/mounts", &mounted_fstab)) {
152         LERROR << "Failed to scan mounted volumes";
153         return false;
154     }
155 
156     auto mounted = GetMountState(rec->mount_point);
157     if (mounted == MountState::ERROR) {
158         return false;
159     }
160     if (mounted == MountState::NOT_MOUNTED) {
161         return true;
162     }
163 
164     int result = umount(rec->mount_point.c_str());
165     if (result == -1) {
166         PWARNING << "Failed to umount " << rec->mount_point;
167         return false;
168     }
169     return true;
170 }
171 
GetSystemRoot()172 std::string GetSystemRoot() {
173     Fstab fstab;
174     if (!ReadDefaultFstab(&fstab)) {
175         LERROR << "Failed to read default fstab";
176         return "";
177     }
178 
179     auto entry = GetEntryForMountPoint(&fstab, kSystemRoot);
180     if (entry == nullptr) {
181         return "/";
182     }
183 
184     return kSystemRoot;
185 }
186 
LogicalPartitionsMapped()187 bool LogicalPartitionsMapped() {
188     return gDidMapLogicalPartitions;
189 }
190 
191 }  // namespace fs_mgr
192 }  // namespace android
193