blob: 4f803fca6c55a24e7e3d9c968fb0a203fbdee58f [file] [log] [blame]
San Mehatf1b736b2009-10-10 17:22:08 -07001/*
2 * Copyright (C) 2008 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 <stdio.h>
San Mehatfd7f5872009-10-12 11:32:47 -070018#include <stdlib.h>
19#include <string.h>
San Mehatf1b736b2009-10-10 17:22:08 -070020#include <errno.h>
San Mehata2677e42009-12-13 10:40:18 -080021#include <fcntl.h>
San Mehata19b2502010-01-06 10:33:53 -080022#include <sys/stat.h>
23#include <sys/types.h>
24#include <sys/mount.h>
25
San Mehata2677e42009-12-13 10:40:18 -080026#include <linux/kdev_t.h>
San Mehatf1b736b2009-10-10 17:22:08 -070027
28#define LOG_TAG "Vold"
29
Kenny Root7b18a7b2010-03-15 13:13:41 -070030#include <openssl/md5.h>
31
San Mehatf1b736b2009-10-10 17:22:08 -070032#include <cutils/log.h>
33
San Mehatfd7f5872009-10-12 11:32:47 -070034#include <sysutils/NetlinkEvent.h>
35
San Mehatf1b736b2009-10-10 17:22:08 -070036#include "VolumeManager.h"
San Mehatae10b912009-10-12 14:57:05 -070037#include "DirectVolume.h"
San Mehata2677e42009-12-13 10:40:18 -080038#include "ResponseCode.h"
San Mehata19b2502010-01-06 10:33:53 -080039#include "Loop.h"
40#include "Fat.h"
San Mehatb78a32c2010-01-10 13:02:12 -080041#include "Devmapper.h"
San Mehat586536c2010-02-16 17:12:00 -080042#include "Process.h"
San Mehatfcf24fe2010-03-03 12:37:32 -080043#include "Asec.h"
San Mehat23969932010-01-09 07:08:06 -080044
San Mehatf1b736b2009-10-10 17:22:08 -070045VolumeManager *VolumeManager::sInstance = NULL;
46
47VolumeManager *VolumeManager::Instance() {
48 if (!sInstance)
49 sInstance = new VolumeManager();
50 return sInstance;
51}
52
53VolumeManager::VolumeManager() {
San Mehatd9a4e352010-03-12 13:32:47 -080054 mDebug = false;
San Mehatf1b736b2009-10-10 17:22:08 -070055 mVolumes = new VolumeCollection();
San Mehat88705162010-01-15 09:26:28 -080056 mActiveContainers = new AsecIdCollection();
San Mehatf1b736b2009-10-10 17:22:08 -070057 mBroadcaster = NULL;
San Mehata2677e42009-12-13 10:40:18 -080058 mUsbMassStorageConnected = false;
San Mehatf1b736b2009-10-10 17:22:08 -070059}
60
61VolumeManager::~VolumeManager() {
San Mehat88705162010-01-15 09:26:28 -080062 delete mVolumes;
63 delete mActiveContainers;
San Mehatf1b736b2009-10-10 17:22:08 -070064}
65
Kenny Root7b18a7b2010-03-15 13:13:41 -070066char *VolumeManager::asecHash(const char *id, char *buffer, size_t len) {
Kenny Rootacc9e7d2010-06-18 19:06:50 -070067 static const char* digits = "0123456789abcdef";
68
Kenny Root7b18a7b2010-03-15 13:13:41 -070069 unsigned char sig[MD5_DIGEST_LENGTH];
70
Kenny Rootacc9e7d2010-06-18 19:06:50 -070071 if (buffer == NULL) {
72 SLOGE("Destination buffer is NULL");
73 errno = ESPIPE;
74 return NULL;
75 } else if (id == NULL) {
76 SLOGE("Source buffer is NULL");
77 errno = ESPIPE;
78 return NULL;
79 } else if (len < MD5_ASCII_LENGTH_PLUS_NULL) {
80 SLOGE("Target hash buffer size < %d bytes (%d)",
81 MD5_ASCII_LENGTH_PLUS_NULL, len);
San Mehatd9a4e352010-03-12 13:32:47 -080082 errno = ESPIPE;
83 return NULL;
84 }
Kenny Root7b18a7b2010-03-15 13:13:41 -070085
86 MD5(reinterpret_cast<const unsigned char*>(id), strlen(id), sig);
San Mehatd9a4e352010-03-12 13:32:47 -080087
Kenny Rootacc9e7d2010-06-18 19:06:50 -070088 char *p = buffer;
Kenny Root7b18a7b2010-03-15 13:13:41 -070089 for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
Kenny Rootacc9e7d2010-06-18 19:06:50 -070090 *p++ = digits[sig[i] >> 4];
91 *p++ = digits[sig[i] & 0x0F];
San Mehatd9a4e352010-03-12 13:32:47 -080092 }
Kenny Rootacc9e7d2010-06-18 19:06:50 -070093 *p = '\0';
San Mehatd9a4e352010-03-12 13:32:47 -080094
95 return buffer;
96}
97
98void VolumeManager::setDebug(bool enable) {
99 mDebug = enable;
100 VolumeCollection::iterator it;
101 for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
102 (*it)->setDebug(enable);
103 }
104}
105
San Mehatf1b736b2009-10-10 17:22:08 -0700106int VolumeManager::start() {
107 return 0;
108}
109
110int VolumeManager::stop() {
111 return 0;
112}
113
114int VolumeManager::addVolume(Volume *v) {
115 mVolumes->push_back(v);
116 return 0;
117}
118
San Mehata2677e42009-12-13 10:40:18 -0800119void VolumeManager::notifyUmsConnected(bool connected) {
120 char msg[255];
121
122 if (connected) {
123 mUsbMassStorageConnected = true;
124 } else {
125 mUsbMassStorageConnected = false;
126 }
127 snprintf(msg, sizeof(msg), "Share method ums now %s",
128 (connected ? "available" : "unavailable"));
129
130 getBroadcaster()->sendBroadcast(ResponseCode::ShareAvailabilityChange,
131 msg, false);
132}
133
134void VolumeManager::handleSwitchEvent(NetlinkEvent *evt) {
San Mehat0cde53c2009-12-22 08:32:33 -0800135 const char *devpath = evt->findParam("DEVPATH");
San Mehata2677e42009-12-13 10:40:18 -0800136 const char *name = evt->findParam("SWITCH_NAME");
137 const char *state = evt->findParam("SWITCH_STATE");
138
San Mehat0cde53c2009-12-22 08:32:33 -0800139 if (!name || !state) {
San Mehat97ac40e2010-03-24 10:24:19 -0700140 SLOGW("Switch %s event missing name/state info", devpath);
San Mehat0cde53c2009-12-22 08:32:33 -0800141 return;
142 }
143
San Mehata2677e42009-12-13 10:40:18 -0800144 if (!strcmp(name, "usb_mass_storage")) {
145
146 if (!strcmp(state, "online")) {
147 notifyUmsConnected(true);
148 } else {
149 notifyUmsConnected(false);
150 }
151 } else {
San Mehat97ac40e2010-03-24 10:24:19 -0700152 SLOGW("Ignoring unknown switch '%s'", name);
San Mehata2677e42009-12-13 10:40:18 -0800153 }
154}
155
San Mehatfd7f5872009-10-12 11:32:47 -0700156void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
157 const char *devpath = evt->findParam("DEVPATH");
San Mehatf1b736b2009-10-10 17:22:08 -0700158
San Mehatfd7f5872009-10-12 11:32:47 -0700159 /* Lookup a volume to handle this device */
San Mehatf1b736b2009-10-10 17:22:08 -0700160 VolumeCollection::iterator it;
161 bool hit = false;
162 for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
San Mehatfd7f5872009-10-12 11:32:47 -0700163 if (!(*it)->handleBlockEvent(evt)) {
San Mehata2677e42009-12-13 10:40:18 -0800164#ifdef NETLINK_DEBUG
San Mehat97ac40e2010-03-24 10:24:19 -0700165 SLOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
San Mehata2677e42009-12-13 10:40:18 -0800166#endif
San Mehatf1b736b2009-10-10 17:22:08 -0700167 hit = true;
San Mehatf1b736b2009-10-10 17:22:08 -0700168 break;
169 }
170 }
171
172 if (!hit) {
San Mehata2677e42009-12-13 10:40:18 -0800173#ifdef NETLINK_DEBUG
San Mehat97ac40e2010-03-24 10:24:19 -0700174 SLOGW("No volumes handled block event for '%s'", devpath);
San Mehata2677e42009-12-13 10:40:18 -0800175#endif
San Mehatf1b736b2009-10-10 17:22:08 -0700176 }
177}
178
San Mehatf1b736b2009-10-10 17:22:08 -0700179int VolumeManager::listVolumes(SocketClient *cli) {
180 VolumeCollection::iterator i;
181
182 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
183 char *buffer;
184 asprintf(&buffer, "%s %s %d",
185 (*i)->getLabel(), (*i)->getMountpoint(),
186 (*i)->getState());
San Mehata2677e42009-12-13 10:40:18 -0800187 cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
San Mehatf1b736b2009-10-10 17:22:08 -0700188 free(buffer);
189 }
San Mehata2677e42009-12-13 10:40:18 -0800190 cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false);
San Mehatf1b736b2009-10-10 17:22:08 -0700191 return 0;
192}
San Mehat49e2bce2009-10-12 16:29:01 -0700193
San Mehata2677e42009-12-13 10:40:18 -0800194int VolumeManager::formatVolume(const char *label) {
195 Volume *v = lookupVolume(label);
196
197 if (!v) {
198 errno = ENOENT;
199 return -1;
200 }
201
202 return v->formatVol();
203}
204
San Mehata19b2502010-01-06 10:33:53 -0800205int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
San Mehat88ac2c02010-03-23 11:15:58 -0700206 char asecFileName[255];
207 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
208
209 memset(buffer, 0, maxlen);
210 if (access(asecFileName, F_OK)) {
211 errno = ENOENT;
212 return -1;
213 }
San Mehata19b2502010-01-06 10:33:53 -0800214
San Mehat3bb60202010-02-19 18:14:36 -0800215 snprintf(buffer, maxlen, "%s/%s", Volume::ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800216 return 0;
217}
218
San Mehat8b8f71b2010-01-11 09:17:25 -0800219int VolumeManager::createAsec(const char *id, unsigned int numSectors,
San Mehata19b2502010-01-06 10:33:53 -0800220 const char *fstype, const char *key, int ownerUid) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800221 struct asec_superblock sb;
222 memset(&sb, 0, sizeof(sb));
223
224 sb.magic = ASEC_SB_MAGIC;
225 sb.ver = ASEC_SB_VER;
San Mehata19b2502010-01-06 10:33:53 -0800226
San Mehatd31e3802010-02-18 08:37:45 -0800227 if (numSectors < ((1024*1024)/512)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700228 SLOGE("Invalid container size specified (%d sectors)", numSectors);
San Mehatd31e3802010-02-18 08:37:45 -0800229 errno = EINVAL;
230 return -1;
231 }
232
San Mehata19b2502010-01-06 10:33:53 -0800233 if (lookupVolume(id)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700234 SLOGE("ASEC id '%s' currently exists", id);
San Mehata19b2502010-01-06 10:33:53 -0800235 errno = EADDRINUSE;
236 return -1;
237 }
238
239 char asecFileName[255];
San Mehat3bb60202010-02-19 18:14:36 -0800240 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800241
242 if (!access(asecFileName, F_OK)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700243 SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
San Mehata19b2502010-01-06 10:33:53 -0800244 asecFileName, strerror(errno));
245 errno = EADDRINUSE;
246 return -1;
247 }
248
San Mehatfcf24fe2010-03-03 12:37:32 -0800249 /*
250 * Add some headroom
251 */
252 unsigned fatSize = (((numSectors * 4) / 512) + 1) * 2;
253 unsigned numImgSectors = numSectors + fatSize + 2;
254
255 if (numImgSectors % 63) {
256 numImgSectors += (63 - (numImgSectors % 63));
257 }
258
259 // Add +1 for our superblock which is at the end
260 if (Loop::createImageFile(asecFileName, numImgSectors + 1)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700261 SLOGE("ASEC image file creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800262 return -1;
263 }
264
San Mehatd9a4e352010-03-12 13:32:47 -0800265 char idHash[33];
266 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700267 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800268 unlink(asecFileName);
269 return -1;
270 }
271
San Mehata19b2502010-01-06 10:33:53 -0800272 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -0800273 if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700274 SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800275 unlink(asecFileName);
276 return -1;
277 }
278
San Mehatb78a32c2010-01-10 13:02:12 -0800279 char dmDevice[255];
280 bool cleanupDm = false;
San Mehata19b2502010-01-06 10:33:53 -0800281
San Mehatb78a32c2010-01-10 13:02:12 -0800282 if (strcmp(key, "none")) {
San Mehatfcf24fe2010-03-03 12:37:32 -0800283 // XXX: This is all we support for now
284 sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH;
San Mehatd9a4e352010-03-12 13:32:47 -0800285 if (Devmapper::create(idHash, loopDevice, key, numImgSectors, dmDevice,
San Mehatb78a32c2010-01-10 13:02:12 -0800286 sizeof(dmDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700287 SLOGE("ASEC device mapping failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800288 Loop::destroyByDevice(loopDevice);
289 unlink(asecFileName);
290 return -1;
291 }
292 cleanupDm = true;
293 } else {
San Mehatfcf24fe2010-03-03 12:37:32 -0800294 sb.c_cipher = ASEC_SB_C_CIPHER_NONE;
San Mehatb78a32c2010-01-10 13:02:12 -0800295 strcpy(dmDevice, loopDevice);
296 }
297
San Mehatfcf24fe2010-03-03 12:37:32 -0800298 /*
299 * Drop down the superblock at the end of the file
300 */
301
302 int sbfd = open(loopDevice, O_RDWR);
303 if (sbfd < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700304 SLOGE("Failed to open new DM device for superblock write (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800305 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800306 Devmapper::destroy(idHash);
San Mehatfcf24fe2010-03-03 12:37:32 -0800307 }
308 Loop::destroyByDevice(loopDevice);
309 unlink(asecFileName);
310 return -1;
311 }
312
313 if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) {
314 close(sbfd);
San Mehat97ac40e2010-03-24 10:24:19 -0700315 SLOGE("Failed to lseek for superblock (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800316 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800317 Devmapper::destroy(idHash);
San Mehatfcf24fe2010-03-03 12:37:32 -0800318 }
319 Loop::destroyByDevice(loopDevice);
320 unlink(asecFileName);
321 return -1;
322 }
323
324 if (write(sbfd, &sb, sizeof(sb)) != sizeof(sb)) {
325 close(sbfd);
San Mehat97ac40e2010-03-24 10:24:19 -0700326 SLOGE("Failed to write superblock (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800327 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800328 Devmapper::destroy(idHash);
San Mehatfcf24fe2010-03-03 12:37:32 -0800329 }
330 Loop::destroyByDevice(loopDevice);
331 unlink(asecFileName);
332 return -1;
333 }
334 close(sbfd);
335
San Mehata1091cb2010-02-28 20:17:20 -0800336 if (strcmp(fstype, "none")) {
337 if (strcmp(fstype, "fat")) {
San Mehat97ac40e2010-03-24 10:24:19 -0700338 SLOGW("Unknown fstype '%s' specified for container", fstype);
San Mehatb78a32c2010-01-10 13:02:12 -0800339 }
San Mehata19b2502010-01-06 10:33:53 -0800340
San Mehatfcf24fe2010-03-03 12:37:32 -0800341 if (Fat::format(dmDevice, numImgSectors)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700342 SLOGE("ASEC FAT format failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800343 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800344 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -0800345 }
San Mehateb13a902010-01-07 12:12:50 -0800346 Loop::destroyByDevice(loopDevice);
347 unlink(asecFileName);
348 return -1;
349 }
San Mehata1091cb2010-02-28 20:17:20 -0800350 char mountPoint[255];
San Mehata19b2502010-01-06 10:33:53 -0800351
San Mehata1091cb2010-02-28 20:17:20 -0800352 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
353 if (mkdir(mountPoint, 0777)) {
354 if (errno != EEXIST) {
San Mehat97ac40e2010-03-24 10:24:19 -0700355 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehata1091cb2010-02-28 20:17:20 -0800356 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800357 Devmapper::destroy(idHash);
San Mehata1091cb2010-02-28 20:17:20 -0800358 }
359 Loop::destroyByDevice(loopDevice);
360 unlink(asecFileName);
361 return -1;
362 }
San Mehatb78a32c2010-01-10 13:02:12 -0800363 }
San Mehata1091cb2010-02-28 20:17:20 -0800364
365 if (Fat::doMount(dmDevice, mountPoint, false, false, ownerUid,
366 0, 0000, false)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700367 SLOGE("ASEC FAT mount failed (%s)", strerror(errno));
San Mehata1091cb2010-02-28 20:17:20 -0800368 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800369 Devmapper::destroy(idHash);
San Mehata1091cb2010-02-28 20:17:20 -0800370 }
371 Loop::destroyByDevice(loopDevice);
372 unlink(asecFileName);
373 return -1;
374 }
375 } else {
San Mehat97ac40e2010-03-24 10:24:19 -0700376 SLOGI("Created raw secure container %s (no filesystem)", id);
San Mehata19b2502010-01-06 10:33:53 -0800377 }
San Mehat88705162010-01-15 09:26:28 -0800378
379 mActiveContainers->push_back(strdup(id));
San Mehata19b2502010-01-06 10:33:53 -0800380 return 0;
381}
382
383int VolumeManager::finalizeAsec(const char *id) {
384 char asecFileName[255];
385 char loopDevice[255];
386 char mountPoint[255];
387
San Mehat3bb60202010-02-19 18:14:36 -0800388 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800389
San Mehatd9a4e352010-03-12 13:32:47 -0800390 char idHash[33];
391 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700392 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800393 return -1;
394 }
395
396 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700397 SLOGE("Unable to finalize %s (%s)", id, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800398 return -1;
399 }
400
San Mehat3bb60202010-02-19 18:14:36 -0800401 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehatfff0b472010-01-06 19:19:46 -0800402 // XXX:
403 if (Fat::doMount(loopDevice, mountPoint, true, true, 0, 0, 0227, false)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700404 SLOGE("ASEC finalize mount failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800405 return -1;
406 }
407
San Mehatd9a4e352010-03-12 13:32:47 -0800408 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700409 SLOGD("ASEC %s finalized", id);
San Mehatd9a4e352010-03-12 13:32:47 -0800410 }
San Mehata19b2502010-01-06 10:33:53 -0800411 return 0;
412}
413
San Mehat048b0802010-01-23 08:17:06 -0800414int VolumeManager::renameAsec(const char *id1, const char *id2) {
415 char *asecFilename1;
416 char *asecFilename2;
417 char mountPoint[255];
418
San Mehat3bb60202010-02-19 18:14:36 -0800419 asprintf(&asecFilename1, "%s/%s.asec", Volume::SEC_ASECDIR, id1);
420 asprintf(&asecFilename2, "%s/%s.asec", Volume::SEC_ASECDIR, id2);
San Mehat048b0802010-01-23 08:17:06 -0800421
San Mehat3bb60202010-02-19 18:14:36 -0800422 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id1);
San Mehat048b0802010-01-23 08:17:06 -0800423 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700424 SLOGW("Rename attempt when src mounted");
San Mehat048b0802010-01-23 08:17:06 -0800425 errno = EBUSY;
426 goto out_err;
427 }
428
San Mehat96956ed2010-02-24 08:42:51 -0800429 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id2);
430 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700431 SLOGW("Rename attempt when dst mounted");
San Mehat96956ed2010-02-24 08:42:51 -0800432 errno = EBUSY;
433 goto out_err;
434 }
435
San Mehat048b0802010-01-23 08:17:06 -0800436 if (!access(asecFilename2, F_OK)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700437 SLOGE("Rename attempt when dst exists");
San Mehat048b0802010-01-23 08:17:06 -0800438 errno = EADDRINUSE;
439 goto out_err;
440 }
441
442 if (rename(asecFilename1, asecFilename2)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700443 SLOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno));
San Mehat048b0802010-01-23 08:17:06 -0800444 goto out_err;
445 }
446
447 free(asecFilename1);
448 free(asecFilename2);
449 return 0;
450
451out_err:
452 free(asecFilename1);
453 free(asecFilename2);
454 return -1;
455}
456
San Mehat4ba89482010-02-18 09:00:18 -0800457#define ASEC_UNMOUNT_RETRIES 5
458int VolumeManager::unmountAsec(const char *id, bool force) {
San Mehata19b2502010-01-06 10:33:53 -0800459 char asecFileName[255];
460 char mountPoint[255];
461
San Mehat3bb60202010-02-19 18:14:36 -0800462 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
463 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800464
San Mehatd9a4e352010-03-12 13:32:47 -0800465 char idHash[33];
466 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700467 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800468 return -1;
469 }
470
San Mehat0586d542010-01-12 15:38:59 -0800471 if (!isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700472 SLOGE("Unmount request for ASEC %s when not mounted", id);
San Mehatb78a32c2010-01-10 13:02:12 -0800473 errno = EINVAL;
474 return -1;
475 }
San Mehat23969932010-01-09 07:08:06 -0800476
San Mehatb78a32c2010-01-10 13:02:12 -0800477 int i, rc;
San Mehat8c940ef2010-02-13 14:19:53 -0800478 for (i = 1; i <= ASEC_UNMOUNT_RETRIES; i++) {
San Mehatb78a32c2010-01-10 13:02:12 -0800479 rc = umount(mountPoint);
480 if (!rc) {
481 break;
San Mehata19b2502010-01-06 10:33:53 -0800482 }
San Mehatb78a32c2010-01-10 13:02:12 -0800483 if (rc && (errno == EINVAL || errno == ENOENT)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700484 SLOGI("Secure container %s unmounted OK", id);
San Mehatb78a32c2010-01-10 13:02:12 -0800485 rc = 0;
486 break;
San Mehata19b2502010-01-06 10:33:53 -0800487 }
San Mehat97ac40e2010-03-24 10:24:19 -0700488 SLOGW("ASEC %s unmount attempt %d failed (%s)",
San Mehat8c940ef2010-02-13 14:19:53 -0800489 id, i, strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800490
San Mehat4ba89482010-02-18 09:00:18 -0800491 int action = 0; // default is to just complain
492
493 if (force) {
494 if (i > (ASEC_UNMOUNT_RETRIES - 2))
495 action = 2; // SIGKILL
496 else if (i > (ASEC_UNMOUNT_RETRIES - 3))
497 action = 1; // SIGHUP
498 }
San Mehat8c940ef2010-02-13 14:19:53 -0800499
San Mehat586536c2010-02-16 17:12:00 -0800500 Process::killProcessesWithOpenFiles(mountPoint, action);
San Mehat8c940ef2010-02-13 14:19:53 -0800501 usleep(1000 * 1000);
San Mehatb78a32c2010-01-10 13:02:12 -0800502 }
503
504 if (rc) {
San Mehat4ba89482010-02-18 09:00:18 -0800505 errno = EBUSY;
San Mehat97ac40e2010-03-24 10:24:19 -0700506 SLOGE("Failed to unmount container %s (%s)", id, strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800507 return -1;
508 }
509
San Mehat12f4b892010-02-24 11:43:22 -0800510 int retries = 10;
511
512 while(retries--) {
513 if (!rmdir(mountPoint)) {
514 break;
515 }
516
San Mehat97ac40e2010-03-24 10:24:19 -0700517 SLOGW("Failed to rmdir %s (%s)", mountPoint, strerror(errno));
San Mehat12f4b892010-02-24 11:43:22 -0800518 usleep(1000 * 1000);
519 }
520
521 if (!retries) {
San Mehat97ac40e2010-03-24 10:24:19 -0700522 SLOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno));
San Mehatf5c61982010-02-03 11:04:46 -0800523 }
San Mehat88705162010-01-15 09:26:28 -0800524
San Mehatd9a4e352010-03-12 13:32:47 -0800525 if (Devmapper::destroy(idHash) && errno != ENXIO) {
San Mehat97ac40e2010-03-24 10:24:19 -0700526 SLOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800527 }
528
529 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -0800530 if (!Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
San Mehata19b2502010-01-06 10:33:53 -0800531 Loop::destroyByDevice(loopDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800532 } else {
San Mehat97ac40e2010-03-24 10:24:19 -0700533 SLOGW("Failed to find loop device for {%s} (%s)", asecFileName, strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800534 }
San Mehat88705162010-01-15 09:26:28 -0800535
536 AsecIdCollection::iterator it;
537 for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) {
538 if (!strcmp(*it, id)) {
539 free(*it);
540 mActiveContainers->erase(it);
541 break;
542 }
543 }
544 if (it == mActiveContainers->end()) {
San Mehat97ac40e2010-03-24 10:24:19 -0700545 SLOGW("mActiveContainers is inconsistent!");
San Mehat88705162010-01-15 09:26:28 -0800546 }
San Mehatb78a32c2010-01-10 13:02:12 -0800547 return 0;
548}
549
San Mehat4ba89482010-02-18 09:00:18 -0800550int VolumeManager::destroyAsec(const char *id, bool force) {
San Mehatb78a32c2010-01-10 13:02:12 -0800551 char asecFileName[255];
552 char mountPoint[255];
553
San Mehat3bb60202010-02-19 18:14:36 -0800554 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
San Mehat55013f72010-02-24 12:12:34 -0800555 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehatb78a32c2010-01-10 13:02:12 -0800556
San Mehat0586d542010-01-12 15:38:59 -0800557 if (isMountpointMounted(mountPoint)) {
San Mehatd9a4e352010-03-12 13:32:47 -0800558 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700559 SLOGD("Unmounting container before destroy");
San Mehatd9a4e352010-03-12 13:32:47 -0800560 }
San Mehat4ba89482010-02-18 09:00:18 -0800561 if (unmountAsec(id, force)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700562 SLOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -0800563 return -1;
564 }
565 }
San Mehata19b2502010-01-06 10:33:53 -0800566
San Mehat0586d542010-01-12 15:38:59 -0800567 if (unlink(asecFileName)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700568 SLOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno));
San Mehat0586d542010-01-12 15:38:59 -0800569 return -1;
570 }
San Mehata19b2502010-01-06 10:33:53 -0800571
San Mehatd9a4e352010-03-12 13:32:47 -0800572 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700573 SLOGD("ASEC %s destroyed", id);
San Mehatd9a4e352010-03-12 13:32:47 -0800574 }
San Mehata19b2502010-01-06 10:33:53 -0800575 return 0;
576}
577
578int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
579 char asecFileName[255];
580 char mountPoint[255];
581
San Mehat3bb60202010-02-19 18:14:36 -0800582 snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
583 snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
San Mehata19b2502010-01-06 10:33:53 -0800584
585 if (isMountpointMounted(mountPoint)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700586 SLOGE("ASEC %s already mounted", id);
San Mehata19b2502010-01-06 10:33:53 -0800587 errno = EBUSY;
588 return -1;
589 }
590
San Mehatd9a4e352010-03-12 13:32:47 -0800591 char idHash[33];
592 if (!asecHash(id, idHash, sizeof(idHash))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700593 SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
San Mehatd9a4e352010-03-12 13:32:47 -0800594 return -1;
595 }
Kenny Root7b18a7b2010-03-15 13:13:41 -0700596
San Mehata19b2502010-01-06 10:33:53 -0800597 char loopDevice[255];
San Mehatd9a4e352010-03-12 13:32:47 -0800598 if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
599 if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700600 SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800601 return -1;
602 }
San Mehatd9a4e352010-03-12 13:32:47 -0800603 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700604 SLOGD("New loop device created at %s", loopDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800605 }
San Mehatb78a32c2010-01-10 13:02:12 -0800606 } else {
San Mehatd9a4e352010-03-12 13:32:47 -0800607 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700608 SLOGD("Found active loopback for %s at %s", asecFileName, loopDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800609 }
San Mehatb78a32c2010-01-10 13:02:12 -0800610 }
611
612 char dmDevice[255];
613 bool cleanupDm = false;
San Mehatfcf24fe2010-03-03 12:37:32 -0800614 int fd;
615 unsigned int nr_sec = 0;
616
617 if ((fd = open(loopDevice, O_RDWR)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700618 SLOGE("Failed to open loopdevice (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800619 Loop::destroyByDevice(loopDevice);
620 return -1;
621 }
622
623 if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700624 SLOGE("Failed to get loop size (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800625 Loop::destroyByDevice(loopDevice);
626 close(fd);
627 return -1;
628 }
629
630 /*
631 * Validate superblock
632 */
633 struct asec_superblock sb;
634 memset(&sb, 0, sizeof(sb));
635 if (lseek(fd, ((nr_sec-1) * 512), SEEK_SET) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700636 SLOGE("lseek failed (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800637 close(fd);
638 Loop::destroyByDevice(loopDevice);
639 return -1;
640 }
641 if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700642 SLOGE("superblock read failed (%s)", strerror(errno));
San Mehatfcf24fe2010-03-03 12:37:32 -0800643 close(fd);
644 Loop::destroyByDevice(loopDevice);
645 return -1;
646 }
647
648 close(fd);
649
San Mehatd9a4e352010-03-12 13:32:47 -0800650 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700651 SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
San Mehatd9a4e352010-03-12 13:32:47 -0800652 }
San Mehatfcf24fe2010-03-03 12:37:32 -0800653 if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
San Mehat97ac40e2010-03-24 10:24:19 -0700654 SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
San Mehatfcf24fe2010-03-03 12:37:32 -0800655 Loop::destroyByDevice(loopDevice);
656 errno = EMEDIUMTYPE;
657 return -1;
658 }
659 nr_sec--; // We don't want the devmapping to extend onto our superblock
660
San Mehatb78a32c2010-01-10 13:02:12 -0800661 if (strcmp(key, "none")) {
San Mehatd9a4e352010-03-12 13:32:47 -0800662 if (Devmapper::lookupActive(idHash, dmDevice, sizeof(dmDevice))) {
663 if (Devmapper::create(idHash, loopDevice, key, nr_sec,
San Mehatb78a32c2010-01-10 13:02:12 -0800664 dmDevice, sizeof(dmDevice))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700665 SLOGE("ASEC device mapping failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800666 Loop::destroyByDevice(loopDevice);
667 return -1;
668 }
San Mehatd9a4e352010-03-12 13:32:47 -0800669 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700670 SLOGD("New devmapper instance created at %s", dmDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800671 }
San Mehatb78a32c2010-01-10 13:02:12 -0800672 } else {
San Mehatd9a4e352010-03-12 13:32:47 -0800673 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700674 SLOGD("Found active devmapper for %s at %s", asecFileName, dmDevice);
San Mehatd9a4e352010-03-12 13:32:47 -0800675 }
San Mehatb78a32c2010-01-10 13:02:12 -0800676 }
677 cleanupDm = true;
678 } else {
679 strcpy(dmDevice, loopDevice);
San Mehata19b2502010-01-06 10:33:53 -0800680 }
681
682 if (mkdir(mountPoint, 0777)) {
San Mehatb78a32c2010-01-10 13:02:12 -0800683 if (errno != EEXIST) {
San Mehat97ac40e2010-03-24 10:24:19 -0700684 SLOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800685 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800686 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -0800687 }
688 Loop::destroyByDevice(loopDevice);
689 return -1;
690 }
San Mehata19b2502010-01-06 10:33:53 -0800691 }
692
San Mehatb78a32c2010-01-10 13:02:12 -0800693 if (Fat::doMount(dmDevice, mountPoint, true, false, ownerUid, 0,
San Mehatcff5ec32010-01-08 12:31:44 -0800694 0222, false)) {
695// 0227, false)) {
San Mehat97ac40e2010-03-24 10:24:19 -0700696 SLOGE("ASEC mount failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800697 if (cleanupDm) {
San Mehatd9a4e352010-03-12 13:32:47 -0800698 Devmapper::destroy(idHash);
San Mehatb78a32c2010-01-10 13:02:12 -0800699 }
700 Loop::destroyByDevice(loopDevice);
San Mehata19b2502010-01-06 10:33:53 -0800701 return -1;
702 }
703
San Mehat88705162010-01-15 09:26:28 -0800704 mActiveContainers->push_back(strdup(id));
San Mehatd9a4e352010-03-12 13:32:47 -0800705 if (mDebug) {
San Mehat97ac40e2010-03-24 10:24:19 -0700706 SLOGD("ASEC %s mounted", id);
San Mehatd9a4e352010-03-12 13:32:47 -0800707 }
San Mehata19b2502010-01-06 10:33:53 -0800708 return 0;
709}
710
San Mehat49e2bce2009-10-12 16:29:01 -0700711int VolumeManager::mountVolume(const char *label) {
712 Volume *v = lookupVolume(label);
713
714 if (!v) {
715 errno = ENOENT;
716 return -1;
717 }
718
San Mehata2677e42009-12-13 10:40:18 -0800719 return v->mountVol();
720}
721
722int VolumeManager::shareAvailable(const char *method, bool *avail) {
723
724 if (strcmp(method, "ums")) {
725 errno = ENOSYS;
726 return -1;
727 }
728
729 if (mUsbMassStorageConnected)
730 *avail = true;
731 else
732 *avail = false;
733 return 0;
734}
735
San Mehateba65e92010-01-29 05:15:16 -0800736int VolumeManager::shareEnabled(const char *label, const char *method, bool *enabled) {
737 Volume *v = lookupVolume(label);
738
739 if (!v) {
740 errno = ENOENT;
741 return -1;
742 }
743
744 if (strcmp(method, "ums")) {
745 errno = ENOSYS;
746 return -1;
747 }
748
749 if (v->getState() != Volume::State_Shared) {
San Mehateba65e92010-01-29 05:15:16 -0800750 *enabled = false;
San Mehatb9aed742010-02-04 15:07:01 -0800751 } else {
752 *enabled = true;
San Mehateba65e92010-01-29 05:15:16 -0800753 }
754 return 0;
755}
756
San Mehata2677e42009-12-13 10:40:18 -0800757int VolumeManager::simulate(const char *cmd, const char *arg) {
758
759 if (!strcmp(cmd, "ums")) {
760 if (!strcmp(arg, "connect")) {
761 notifyUmsConnected(true);
762 } else if (!strcmp(arg, "disconnect")) {
763 notifyUmsConnected(false);
764 } else {
765 errno = EINVAL;
766 return -1;
767 }
768 } else {
769 errno = EINVAL;
770 return -1;
771 }
772 return 0;
773}
774
775int VolumeManager::shareVolume(const char *label, const char *method) {
776 Volume *v = lookupVolume(label);
777
778 if (!v) {
779 errno = ENOENT;
780 return -1;
781 }
782
783 /*
784 * Eventually, we'll want to support additional share back-ends,
785 * some of which may work while the media is mounted. For now,
786 * we just support UMS
787 */
788 if (strcmp(method, "ums")) {
789 errno = ENOSYS;
790 return -1;
791 }
792
793 if (v->getState() == Volume::State_NoMedia) {
794 errno = ENODEV;
795 return -1;
796 }
797
San Mehat49e2bce2009-10-12 16:29:01 -0700798 if (v->getState() != Volume::State_Idle) {
San Mehata2677e42009-12-13 10:40:18 -0800799 // You need to unmount manually befoe sharing
San Mehat49e2bce2009-10-12 16:29:01 -0700800 errno = EBUSY;
801 return -1;
802 }
803
San Mehata2677e42009-12-13 10:40:18 -0800804 dev_t d = v->getDiskDevice();
805 if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
806 // This volume does not support raw disk access
807 errno = EINVAL;
808 return -1;
809 }
810
811 int fd;
812 char nodepath[255];
813 snprintf(nodepath,
814 sizeof(nodepath), "/dev/block/vold/%d:%d",
815 MAJOR(d), MINOR(d));
816
San Mehat0cde53c2009-12-22 08:32:33 -0800817 if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file",
818 O_WRONLY)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700819 SLOGE("Unable to open ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -0800820 return -1;
821 }
822
823 if (write(fd, nodepath, strlen(nodepath)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700824 SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -0800825 close(fd);
826 return -1;
827 }
828
829 close(fd);
830 v->handleVolumeShared();
831 return 0;
832}
833
834int VolumeManager::unshareVolume(const char *label, const char *method) {
835 Volume *v = lookupVolume(label);
836
837 if (!v) {
838 errno = ENOENT;
839 return -1;
840 }
841
842 if (strcmp(method, "ums")) {
843 errno = ENOSYS;
844 return -1;
845 }
846
847 if (v->getState() != Volume::State_Shared) {
848 errno = EINVAL;
849 return -1;
850 }
851
852 dev_t d = v->getDiskDevice();
853
854 int fd;
855 char nodepath[255];
856 snprintf(nodepath,
857 sizeof(nodepath), "/dev/block/vold/%d:%d",
858 MAJOR(d), MINOR(d));
859
San Mehat0cde53c2009-12-22 08:32:33 -0800860 if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file", O_WRONLY)) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700861 SLOGE("Unable to open ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -0800862 return -1;
863 }
864
865 char ch = 0;
866 if (write(fd, &ch, 1) < 0) {
San Mehat97ac40e2010-03-24 10:24:19 -0700867 SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));
San Mehata2677e42009-12-13 10:40:18 -0800868 close(fd);
869 return -1;
870 }
871
872 close(fd);
873 v->handleVolumeUnshared();
874 return 0;
San Mehat49e2bce2009-10-12 16:29:01 -0700875}
876
San Mehat4ba89482010-02-18 09:00:18 -0800877int VolumeManager::unmountVolume(const char *label, bool force) {
San Mehat49e2bce2009-10-12 16:29:01 -0700878 Volume *v = lookupVolume(label);
879
880 if (!v) {
881 errno = ENOENT;
882 return -1;
883 }
884
San Mehata2677e42009-12-13 10:40:18 -0800885 if (v->getState() == Volume::State_NoMedia) {
886 errno = ENODEV;
887 return -1;
888 }
889
San Mehat49e2bce2009-10-12 16:29:01 -0700890 if (v->getState() != Volume::State_Mounted) {
San Mehat97ac40e2010-03-24 10:24:19 -0700891 SLOGW("Attempt to unmount volume which isn't mounted (%d)\n",
San Mehata2677e42009-12-13 10:40:18 -0800892 v->getState());
San Mehat49e2bce2009-10-12 16:29:01 -0700893 errno = EBUSY;
894 return -1;
895 }
896
San Mehat1a06eda2010-04-15 12:58:50 -0700897 cleanupAsec(v, force);
San Mehat88705162010-01-15 09:26:28 -0800898
San Mehat4ba89482010-02-18 09:00:18 -0800899 return v->unmountVol(force);
San Mehat49e2bce2009-10-12 16:29:01 -0700900}
901
San Mehata2677e42009-12-13 10:40:18 -0800902/*
903 * Looks up a volume by it's label or mount-point
904 */
San Mehat49e2bce2009-10-12 16:29:01 -0700905Volume *VolumeManager::lookupVolume(const char *label) {
906 VolumeCollection::iterator i;
907
908 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
San Mehata2677e42009-12-13 10:40:18 -0800909 if (label[0] == '/') {
910 if (!strcmp(label, (*i)->getMountpoint()))
911 return (*i);
912 } else {
913 if (!strcmp(label, (*i)->getLabel()))
914 return (*i);
915 }
San Mehat49e2bce2009-10-12 16:29:01 -0700916 }
917 return NULL;
918}
San Mehata19b2502010-01-06 10:33:53 -0800919
920bool VolumeManager::isMountpointMounted(const char *mp)
921{
922 char device[256];
923 char mount_path[256];
924 char rest[256];
925 FILE *fp;
926 char line[1024];
927
928 if (!(fp = fopen("/proc/mounts", "r"))) {
San Mehat97ac40e2010-03-24 10:24:19 -0700929 SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800930 return false;
931 }
932
933 while(fgets(line, sizeof(line), fp)) {
934 line[strlen(line)-1] = '\0';
935 sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
936 if (!strcmp(mount_path, mp)) {
937 fclose(fp);
938 return true;
939 }
San Mehata19b2502010-01-06 10:33:53 -0800940 }
941
942 fclose(fp);
943 return false;
944}
945
San Mehat1a06eda2010-04-15 12:58:50 -0700946int VolumeManager::cleanupAsec(Volume *v, bool force) {
947 while(mActiveContainers->size()) {
948 AsecIdCollection::iterator it = mActiveContainers->begin();
949 SLOGI("Unmounting ASEC %s (dependant on %s)", *it, v->getMountpoint());
950 if (unmountAsec(*it, force)) {
951 SLOGE("Failed to unmount ASEC %s (%s)", *it, strerror(errno));
952 return -1;
953 }
954 }
955 return 0;
956}
957