blob: 7d32590fc323d659316de15a483e902312e9ffab [file] [log] [blame]
Jeff Sharkeydeb24052015-03-02 21:01:40 -08001/*
2 * Copyright (C) 2015 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
Jeff Sharkeydeb24052015-03-02 21:01:40 -080017#include "sehandle.h"
18#include "Utils.h"
19#include "Process.h"
20
Jeff Sharkey36801cc2015-03-13 16:09:20 -070021#include <base/logging.h>
Jeff Sharkey9c484982015-03-31 10:35:33 -070022#include <base/stringprintf.h>
Jeff Sharkeydeb24052015-03-02 21:01:40 -080023#include <cutils/fs.h>
Jeff Sharkeydeb24052015-03-02 21:01:40 -080024#include <private/android_filesystem_config.h>
Jeff Sharkey9c484982015-03-31 10:35:33 -070025#include <logwrap/logwrap.h>
Jeff Sharkeydeb24052015-03-02 21:01:40 -080026
27#include <fcntl.h>
28#include <linux/fs.h>
29#include <stdlib.h>
30#include <sys/mount.h>
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <sys/wait.h>
34
35#ifndef UMOUNT_NOFOLLOW
36#define UMOUNT_NOFOLLOW 0x00000008 /* Don't follow symlink on umount */
37#endif
38
Jeff Sharkey9c484982015-03-31 10:35:33 -070039using android::base::StringPrintf;
40
Jeff Sharkeydeb24052015-03-02 21:01:40 -080041namespace android {
42namespace vold {
43
Jeff Sharkey9c484982015-03-31 10:35:33 -070044static const char* kBlkidPath = "/system/bin/blkid";
45
Jeff Sharkeydeb24052015-03-02 21:01:40 -080046status_t CreateDeviceNode(const std::string& path, dev_t dev) {
47 const char* cpath = path.c_str();
48 status_t res = 0;
49
50 char* secontext = nullptr;
51 if (sehandle) {
52 if (!selabel_lookup(sehandle, &secontext, cpath, S_IFBLK)) {
53 setfscreatecon(secontext);
54 }
55 }
56
57 mode_t mode = 0660 | S_IFBLK;
58 if (mknod(cpath, mode, dev) < 0) {
59 if (errno != EEXIST) {
Jeff Sharkey36801cc2015-03-13 16:09:20 -070060 PLOG(ERROR) << "Failed to create device node for " << major(dev)
61 << ":" << minor(dev) << " at " << path;
Jeff Sharkeydeb24052015-03-02 21:01:40 -080062 res = -errno;
63 }
64 }
65
66 if (secontext) {
67 setfscreatecon(nullptr);
68 freecon(secontext);
69 }
70
71 return res;
72}
73
74status_t DestroyDeviceNode(const std::string& path) {
75 const char* cpath = path.c_str();
76 if (TEMP_FAILURE_RETRY(unlink(cpath))) {
77 return -errno;
78 } else {
79 return OK;
80 }
81}
82
83status_t ForceUnmount(const std::string& path) {
84 const char* cpath = path.c_str();
85 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
86 return OK;
87 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -070088 PLOG(WARNING) << "Failed to unmount " << path << "; sending SIGTERM";
Jeff Sharkeydeb24052015-03-02 21:01:40 -080089 Process::killProcessesWithOpenFiles(cpath, SIGTERM);
Jeff Sharkey9c484982015-03-31 10:35:33 -070090 sleep(5);
Jeff Sharkeydeb24052015-03-02 21:01:40 -080091
92 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
93 return OK;
94 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -070095 PLOG(WARNING) << "Failed to unmount " << path << "; sending SIGKILL";
Jeff Sharkeydeb24052015-03-02 21:01:40 -080096 Process::killProcessesWithOpenFiles(cpath, SIGKILL);
Jeff Sharkey9c484982015-03-31 10:35:33 -070097 sleep(5);
Jeff Sharkeydeb24052015-03-02 21:01:40 -080098
99 if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
100 return OK;
101 }
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700102 PLOG(ERROR) << "Failed to unmount " << path << "; giving up";
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800103 return -errno;
104}
105
Jeff Sharkey36801cc2015-03-13 16:09:20 -0700106status_t BindMount(const std::string& source, const std::string& target) {
107 if (::mount(source.c_str(), target.c_str(), "", MS_BIND, NULL)) {
108 PLOG(ERROR) << "Failed to bind mount " << source << " to " << target;
109 return -errno;
110 }
111 return OK;
112}
113
Jeff Sharkey9c484982015-03-31 10:35:33 -0700114status_t ReadMetadata(const std::string& path, std::string& fsType,
115 std::string& fsUuid, std::string& fsLabel) {
116 fsType.clear();
117 fsUuid.clear();
118 fsLabel.clear();
119
120 std::string cmd(StringPrintf("%s -c /dev/null %s", kBlkidPath, path.c_str()));
121 FILE* fp = popen(cmd.c_str(), "r");
122 if (!fp) {
123 PLOG(ERROR) << "Failed to run " << cmd;
124 return -errno;
125 }
126
127 status_t res = OK;
128 char line[1024];
129 char value[128];
130 if (fgets(line, sizeof(line), fp) != nullptr) {
131 LOG(DEBUG) << "blkid identified " << path << " as " << line;
132
133 // Extract values from blkid output, if defined
134 char* start = strstr(line, "TYPE=");
135 if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
136 fsType = value;
137 }
138
139 start = strstr(line, "UUID=");
140 if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
141 fsUuid = value;
142 }
143
144 start = strstr(line, "LABEL=");
145 if (start != nullptr && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) {
146 fsLabel = value;
147 }
148 } else {
149 LOG(WARNING) << "blkid failed to identify " << path;
150 res = -ENODATA;
151 }
152
153 pclose(fp);
154 return res;
155}
156
157status_t ForkExecvp(const std::vector<std::string>& args, int* status,
158 bool ignore_int_quit, bool logwrap) {
159 int argc = args.size();
160 char** argv = (char**) calloc(argc, sizeof(char*));
161 for (int i = 0; i < argc; i++) {
162 argv[i] = (char*) args[i].c_str();
163 if (i == 0) {
164 LOG(VERBOSE) << args[i];
165 } else {
166 LOG(VERBOSE) << " " << args[i];
167 }
168 }
169 int res = android_fork_execvp(argc, argv, status, ignore_int_quit, logwrap);
170 free(argv);
171 return res;
172}
173
174status_t ReadRandomBytes(size_t bytes, std::string& out) {
175 out.clear();
176
177 int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
178 if (fd == -1) {
179 return -errno;
180 }
181
182 char buf[BUFSIZ];
183 size_t n;
184 while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], std::min(sizeof(buf), bytes)))) > 0) {
185 out.append(buf, n);
186 bytes -= n;
187 }
188 TEMP_FAILURE_RETRY(close(fd));
189
190 if (bytes == 0) {
191 return OK;
192 } else {
193 return -EIO;
194 }
195}
196
197status_t HexToStr(const std::string& hex, std::string& str) {
198 str.clear();
199 bool even = true;
200 char cur = 0;
201 for (size_t i = 0; i < hex.size(); i++) {
202 int val = 0;
203 switch (hex[i]) {
204 case ' ': case '-': case ':': continue;
205 case 'f': case 'F': val = 15; break;
206 case 'e': case 'E': val = 14; break;
207 case 'd': case 'D': val = 13; break;
208 case 'c': case 'C': val = 12; break;
209 case 'b': case 'B': val = 11; break;
210 case 'a': case 'A': val = 10; break;
211 case '9': val = 9; break;
212 case '8': val = 8; break;
213 case '7': val = 7; break;
214 case '6': val = 6; break;
215 case '5': val = 5; break;
216 case '4': val = 4; break;
217 case '3': val = 3; break;
218 case '2': val = 2; break;
219 case '1': val = 1; break;
220 case '0': val = 0; break;
221 default: return -EINVAL;
222 }
223
224 if (even) {
225 cur = val << 4;
226 } else {
227 cur += val;
228 str.push_back(cur);
229 cur = 0;
230 }
231 even = !even;
232 }
233 return even ? OK : -EINVAL;
234}
235
236static const char* kLookup = "0123456789abcdef";
237
238status_t StrToHex(const std::string& str, std::string& hex) {
239 hex.clear();
240 for (size_t i = 0; i < str.size(); i++) {
241 hex.push_back(kLookup[str[i] >> 4]);
242 hex.push_back(kLookup[str[i] & 0x0F]);
243 }
244 return OK;
245}
246
Jeff Sharkeydeb24052015-03-02 21:01:40 -0800247} // namespace vold
248} // namespace android