1 /*
2  * Copyright (C) 2007 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 "mounts.h"
18 
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <mntent.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/mount.h>
26 
27 #include <string>
28 #include <vector>
29 
30 #include <android-base/logging.h>
31 
32 struct MountedVolume {
33   std::string device;
34   std::string mount_point;
35   std::string filesystem;
36   std::string flags;
37 };
38 
39 static std::vector<MountedVolume*> g_mounts_state;
40 
scan_mounted_volumes()41 bool scan_mounted_volumes() {
42   for (size_t i = 0; i < g_mounts_state.size(); ++i) {
43     delete g_mounts_state[i];
44   }
45   g_mounts_state.clear();
46 
47   // Open and read mount table entries.
48   FILE* fp = setmntent("/proc/mounts", "re");
49   if (fp == NULL) {
50     return false;
51   }
52   mntent* e;
53   while ((e = getmntent(fp)) != NULL) {
54     MountedVolume* v = new MountedVolume;
55     v->device = e->mnt_fsname;
56     v->mount_point = e->mnt_dir;
57     v->filesystem = e->mnt_type;
58     v->flags = e->mnt_opts;
59     g_mounts_state.push_back(v);
60   }
61   endmntent(fp);
62   return true;
63 }
64 
find_mounted_volume_by_mount_point(const char * mount_point)65 MountedVolume* find_mounted_volume_by_mount_point(const char* mount_point) {
66   for (size_t i = 0; i < g_mounts_state.size(); ++i) {
67     if (g_mounts_state[i]->mount_point == mount_point) return g_mounts_state[i];
68   }
69   return nullptr;
70 }
71 
unmount_mounted_volume(MountedVolume * volume)72 int unmount_mounted_volume(MountedVolume* volume) {
73   // Intentionally pass the empty string to umount if the caller tries to unmount a volume they
74   // already unmounted using this function.
75   std::string mount_point = volume->mount_point;
76   volume->mount_point.clear();
77   int result = umount(mount_point.c_str());
78   if (result == -1) {
79     PLOG(WARNING) << "Failed to umount " << mount_point;
80   }
81   return result;
82 }
83