blob: 4b3342ed871aa81abba7b12e1de9a1617e6e56db [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
30#include <cutils/log.h>
31
San Mehatfd7f5872009-10-12 11:32:47 -070032#include <sysutils/NetlinkEvent.h>
33
San Mehatf1b736b2009-10-10 17:22:08 -070034#include "VolumeManager.h"
San Mehatae10b912009-10-12 14:57:05 -070035#include "DirectVolume.h"
San Mehata2677e42009-12-13 10:40:18 -080036#include "ResponseCode.h"
San Mehata19b2502010-01-06 10:33:53 -080037#include "Loop.h"
38#include "Fat.h"
San Mehatb78a32c2010-01-10 13:02:12 -080039#include "Devmapper.h"
San Mehatf1b736b2009-10-10 17:22:08 -070040
San Mehat23969932010-01-09 07:08:06 -080041extern "C" void KillProcessesWithOpenFiles(const char *, int, int, int);
42
San Mehatf1b736b2009-10-10 17:22:08 -070043VolumeManager *VolumeManager::sInstance = NULL;
44
45VolumeManager *VolumeManager::Instance() {
46 if (!sInstance)
47 sInstance = new VolumeManager();
48 return sInstance;
49}
50
51VolumeManager::VolumeManager() {
52 mBlockDevices = new BlockDeviceCollection();
53 mVolumes = new VolumeCollection();
San Mehat88705162010-01-15 09:26:28 -080054 mActiveContainers = new AsecIdCollection();
San Mehatf1b736b2009-10-10 17:22:08 -070055 mBroadcaster = NULL;
San Mehata2677e42009-12-13 10:40:18 -080056 mUsbMassStorageConnected = false;
San Mehatf1b736b2009-10-10 17:22:08 -070057}
58
59VolumeManager::~VolumeManager() {
60 delete mBlockDevices;
San Mehat88705162010-01-15 09:26:28 -080061 delete mVolumes;
62 delete mActiveContainers;
San Mehatf1b736b2009-10-10 17:22:08 -070063}
64
65int VolumeManager::start() {
66 return 0;
67}
68
69int VolumeManager::stop() {
70 return 0;
71}
72
73int VolumeManager::addVolume(Volume *v) {
74 mVolumes->push_back(v);
75 return 0;
76}
77
San Mehata2677e42009-12-13 10:40:18 -080078void VolumeManager::notifyUmsConnected(bool connected) {
79 char msg[255];
80
81 if (connected) {
82 mUsbMassStorageConnected = true;
83 } else {
84 mUsbMassStorageConnected = false;
85 }
86 snprintf(msg, sizeof(msg), "Share method ums now %s",
87 (connected ? "available" : "unavailable"));
88
89 getBroadcaster()->sendBroadcast(ResponseCode::ShareAvailabilityChange,
90 msg, false);
91}
92
93void VolumeManager::handleSwitchEvent(NetlinkEvent *evt) {
San Mehat0cde53c2009-12-22 08:32:33 -080094 const char *devpath = evt->findParam("DEVPATH");
San Mehata2677e42009-12-13 10:40:18 -080095 const char *name = evt->findParam("SWITCH_NAME");
96 const char *state = evt->findParam("SWITCH_STATE");
97
San Mehat0cde53c2009-12-22 08:32:33 -080098 if (!name || !state) {
99 LOGW("Switch %s event missing name/state info", devpath);
100 return;
101 }
102
San Mehata2677e42009-12-13 10:40:18 -0800103 if (!strcmp(name, "usb_mass_storage")) {
104
105 if (!strcmp(state, "online")) {
106 notifyUmsConnected(true);
107 } else {
108 notifyUmsConnected(false);
109 }
110 } else {
111 LOGW("Ignoring unknown switch '%s'", name);
112 }
113}
114
San Mehatfd7f5872009-10-12 11:32:47 -0700115void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
116 const char *devpath = evt->findParam("DEVPATH");
San Mehatf1b736b2009-10-10 17:22:08 -0700117
San Mehatfd7f5872009-10-12 11:32:47 -0700118 /* Lookup a volume to handle this device */
San Mehatf1b736b2009-10-10 17:22:08 -0700119 VolumeCollection::iterator it;
120 bool hit = false;
121 for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
San Mehatfd7f5872009-10-12 11:32:47 -0700122 if (!(*it)->handleBlockEvent(evt)) {
San Mehata2677e42009-12-13 10:40:18 -0800123#ifdef NETLINK_DEBUG
124 LOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
125#endif
San Mehatf1b736b2009-10-10 17:22:08 -0700126 hit = true;
San Mehatf1b736b2009-10-10 17:22:08 -0700127 break;
128 }
129 }
130
131 if (!hit) {
San Mehata2677e42009-12-13 10:40:18 -0800132#ifdef NETLINK_DEBUG
San Mehatfd7f5872009-10-12 11:32:47 -0700133 LOGW("No volumes handled block event for '%s'", devpath);
San Mehata2677e42009-12-13 10:40:18 -0800134#endif
San Mehatf1b736b2009-10-10 17:22:08 -0700135 }
136}
137
San Mehatf1b736b2009-10-10 17:22:08 -0700138int VolumeManager::listVolumes(SocketClient *cli) {
139 VolumeCollection::iterator i;
140
141 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
142 char *buffer;
143 asprintf(&buffer, "%s %s %d",
144 (*i)->getLabel(), (*i)->getMountpoint(),
145 (*i)->getState());
San Mehata2677e42009-12-13 10:40:18 -0800146 cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
San Mehatf1b736b2009-10-10 17:22:08 -0700147 free(buffer);
148 }
San Mehata2677e42009-12-13 10:40:18 -0800149 cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false);
San Mehatf1b736b2009-10-10 17:22:08 -0700150 return 0;
151}
San Mehat49e2bce2009-10-12 16:29:01 -0700152
San Mehata2677e42009-12-13 10:40:18 -0800153int VolumeManager::formatVolume(const char *label) {
154 Volume *v = lookupVolume(label);
155
156 if (!v) {
157 errno = ENOENT;
158 return -1;
159 }
160
161 return v->formatVol();
162}
163
San Mehata19b2502010-01-06 10:33:53 -0800164int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
165 char mountPoint[255];
166
167 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
168
169 if (!isMountpointMounted(mountPoint)) {
170 errno = ENOENT;
171 return -1;
172 }
173 snprintf(buffer, maxlen, "/asec/%s", id);
174 return 0;
175}
176
San Mehat8b8f71b2010-01-11 09:17:25 -0800177int VolumeManager::createAsec(const char *id, unsigned int numSectors,
San Mehata19b2502010-01-06 10:33:53 -0800178 const char *fstype, const char *key, int ownerUid) {
179
180 mkdir("/sdcard/android_secure", 0777);
181
182 if (lookupVolume(id)) {
183 LOGE("ASEC volume '%s' currently exists", id);
184 errno = EADDRINUSE;
185 return -1;
186 }
187
188 char asecFileName[255];
189 snprintf(asecFileName, sizeof(asecFileName),
190 "/sdcard/android_secure/%s.asec", id);
191
192 if (!access(asecFileName, F_OK)) {
193 LOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
194 asecFileName, strerror(errno));
195 errno = EADDRINUSE;
196 return -1;
197 }
198
San Mehat8b8f71b2010-01-11 09:17:25 -0800199 if (Loop::createImageFile(asecFileName, numSectors)) {
San Mehata19b2502010-01-06 10:33:53 -0800200 LOGE("ASEC image file creation failed (%s)", strerror(errno));
201 return -1;
202 }
203
204 char loopDevice[255];
San Mehat8da6bcb2010-01-09 12:24:05 -0800205 if (Loop::create(asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehata19b2502010-01-06 10:33:53 -0800206 LOGE("ASEC loop device creation failed (%s)", strerror(errno));
207 unlink(asecFileName);
208 return -1;
209 }
210
San Mehatb78a32c2010-01-10 13:02:12 -0800211 char dmDevice[255];
212 bool cleanupDm = false;
San Mehata19b2502010-01-06 10:33:53 -0800213
San Mehatb78a32c2010-01-10 13:02:12 -0800214 if (strcmp(key, "none")) {
San Mehat8b8f71b2010-01-11 09:17:25 -0800215 if (Devmapper::create(id, loopDevice, key, numSectors, dmDevice,
San Mehatb78a32c2010-01-10 13:02:12 -0800216 sizeof(dmDevice))) {
217 LOGE("ASEC device mapping failed (%s)", strerror(errno));
218 Loop::destroyByDevice(loopDevice);
219 unlink(asecFileName);
220 return -1;
221 }
222 cleanupDm = true;
223 } else {
224 strcpy(dmDevice, loopDevice);
225 }
226
227 if (Fat::format(dmDevice)) {
San Mehata19b2502010-01-06 10:33:53 -0800228 LOGE("ASEC FAT format failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800229 if (cleanupDm) {
230 Devmapper::destroy(id);
231 }
San Mehata19b2502010-01-06 10:33:53 -0800232 Loop::destroyByDevice(loopDevice);
233 unlink(asecFileName);
234 return -1;
235 }
236
237 char mountPoint[255];
238
239 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
240 if (mkdir(mountPoint, 0777)) {
San Mehateb13a902010-01-07 12:12:50 -0800241 if (errno != EEXIST) {
242 LOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800243 if (cleanupDm) {
244 Devmapper::destroy(id);
245 }
San Mehateb13a902010-01-07 12:12:50 -0800246 Loop::destroyByDevice(loopDevice);
247 unlink(asecFileName);
248 return -1;
249 }
San Mehata19b2502010-01-06 10:33:53 -0800250 }
251
San Mehatb78a32c2010-01-10 13:02:12 -0800252 if (Fat::doMount(dmDevice, mountPoint, false, false, ownerUid,
San Mehatcff5ec32010-01-08 12:31:44 -0800253 0, 0000, false)) {
254// 0, 0007, false)) {
San Mehata19b2502010-01-06 10:33:53 -0800255 LOGE("ASEC FAT mount failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800256 if (cleanupDm) {
257 Devmapper::destroy(id);
258 }
San Mehata19b2502010-01-06 10:33:53 -0800259 Loop::destroyByDevice(loopDevice);
260 unlink(asecFileName);
261 return -1;
262 }
San Mehat88705162010-01-15 09:26:28 -0800263
264 mActiveContainers->push_back(strdup(id));
San Mehata19b2502010-01-06 10:33:53 -0800265 return 0;
266}
267
268int VolumeManager::finalizeAsec(const char *id) {
269 char asecFileName[255];
270 char loopDevice[255];
271 char mountPoint[255];
272
273 snprintf(asecFileName, sizeof(asecFileName),
274 "/sdcard/android_secure/%s.asec", id);
275
276 if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
277 LOGE("Unable to finalize %s (%s)", id, strerror(errno));
278 return -1;
279 }
280
281 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
San Mehatfff0b472010-01-06 19:19:46 -0800282 // XXX:
283 if (Fat::doMount(loopDevice, mountPoint, true, true, 0, 0, 0227, false)) {
San Mehata19b2502010-01-06 10:33:53 -0800284 LOGE("ASEC finalize mount failed (%s)", strerror(errno));
285 return -1;
286 }
287
288 LOGD("ASEC %s finalized", id);
289 return 0;
290}
291
San Mehatb78a32c2010-01-10 13:02:12 -0800292int VolumeManager::unmountAsec(const char *id) {
San Mehata19b2502010-01-06 10:33:53 -0800293 char asecFileName[255];
294 char mountPoint[255];
295
296 snprintf(asecFileName, sizeof(asecFileName),
297 "/sdcard/android_secure/%s.asec", id);
298 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
299
San Mehat0586d542010-01-12 15:38:59 -0800300 if (!isMountpointMounted(mountPoint)) {
San Mehatb78a32c2010-01-10 13:02:12 -0800301 LOGE("Unmount request for ASEC %s when not mounted", id);
302 errno = EINVAL;
303 return -1;
304 }
San Mehat23969932010-01-09 07:08:06 -0800305
San Mehatb78a32c2010-01-10 13:02:12 -0800306 int i, rc;
307 for (i = 0; i < 10; i++) {
308 rc = umount(mountPoint);
309 if (!rc) {
310 break;
San Mehata19b2502010-01-06 10:33:53 -0800311 }
San Mehatb78a32c2010-01-10 13:02:12 -0800312 if (rc && (errno == EINVAL || errno == ENOENT)) {
313 rc = 0;
314 break;
San Mehata19b2502010-01-06 10:33:53 -0800315 }
San Mehatb78a32c2010-01-10 13:02:12 -0800316 LOGW("ASEC %s unmount attempt %d failed (%s)",
317 id, i +1, strerror(errno));
318
319 if (i >= 5) {
320 KillProcessesWithOpenFiles(mountPoint, (i < 7 ? 0 : 1),
321 NULL, 0);
322 }
323 usleep(1000 * 250);
324 }
325
326 if (rc) {
327 LOGE("Failed to unmount ASEC %s", id);
328 return -1;
329 }
330
San Mehat88705162010-01-15 09:26:28 -0800331 unlink(mountPoint);
332
San Mehatb78a32c2010-01-10 13:02:12 -0800333 if (Devmapper::destroy(id) && errno != ENXIO) {
334 LOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800335 }
336
337 char loopDevice[255];
338 if (!Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
339 Loop::destroyByDevice(loopDevice);
340 }
San Mehat88705162010-01-15 09:26:28 -0800341
342 AsecIdCollection::iterator it;
343 for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) {
344 if (!strcmp(*it, id)) {
345 free(*it);
346 mActiveContainers->erase(it);
347 break;
348 }
349 }
350 if (it == mActiveContainers->end()) {
351 LOGW("mActiveContainers is inconsistent!");
352 }
San Mehatb78a32c2010-01-10 13:02:12 -0800353 return 0;
354}
355
356int VolumeManager::destroyAsec(const char *id) {
357 char asecFileName[255];
358 char mountPoint[255];
359
360 snprintf(asecFileName, sizeof(asecFileName),
361 "/sdcard/android_secure/%s.asec", id);
362 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
363
San Mehat0586d542010-01-12 15:38:59 -0800364 if (isMountpointMounted(mountPoint)) {
365 if (unmountAsec(id)) {
366 LOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
367 return -1;
368 }
369 }
San Mehata19b2502010-01-06 10:33:53 -0800370
San Mehat0586d542010-01-12 15:38:59 -0800371 if (unlink(asecFileName)) {
372 LOGE("Failed to unlink asec %s (%s)", id, strerror(errno));
373 return -1;
374 }
San Mehata19b2502010-01-06 10:33:53 -0800375
376 LOGD("ASEC %s destroyed", id);
377 return 0;
378}
379
380int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
381 char asecFileName[255];
382 char mountPoint[255];
383
384 snprintf(asecFileName, sizeof(asecFileName),
385 "/sdcard/android_secure/%s.asec", id);
386 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
387
388 if (isMountpointMounted(mountPoint)) {
389 LOGE("ASEC %s already mounted", id);
390 errno = EBUSY;
391 return -1;
392 }
393
394 char loopDevice[255];
395 if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehat8da6bcb2010-01-09 12:24:05 -0800396 if (Loop::create(asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehata19b2502010-01-06 10:33:53 -0800397 LOGE("ASEC loop device creation failed (%s)", strerror(errno));
398 return -1;
399 }
San Mehatb78a32c2010-01-10 13:02:12 -0800400 LOGD("New loop device created at %s", loopDevice);
401 } else {
402 LOGD("Found active loopback for %s at %s", asecFileName, loopDevice);
403 }
404
405 char dmDevice[255];
406 bool cleanupDm = false;
407 if (strcmp(key, "none")) {
408 if (Devmapper::lookupActive(id, dmDevice, sizeof(dmDevice))) {
409 unsigned int nr_sec = 0;
410 int fd;
411
412 if ((fd = open(loopDevice, O_RDWR)) < 0) {
413 LOGE("Failed to open loopdevice (%s)", strerror(errno));
414 Loop::destroyByDevice(loopDevice);
415 return -1;
416 }
417
418 if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
419 LOGE("Failed to get loop size (%s)", strerror(errno));
420 Loop::destroyByDevice(loopDevice);
421 close(fd);
422 return -1;
423 }
424 close(fd);
San Mehat8b8f71b2010-01-11 09:17:25 -0800425 if (Devmapper::create(id, loopDevice, key, nr_sec,
San Mehatb78a32c2010-01-10 13:02:12 -0800426 dmDevice, sizeof(dmDevice))) {
427 LOGE("ASEC device mapping failed (%s)", strerror(errno));
428 Loop::destroyByDevice(loopDevice);
429 return -1;
430 }
431 LOGD("New devmapper instance created at %s", dmDevice);
432 } else {
433 LOGD("Found active devmapper for %s at %s", asecFileName, dmDevice);
434 }
435 cleanupDm = true;
436 } else {
437 strcpy(dmDevice, loopDevice);
San Mehata19b2502010-01-06 10:33:53 -0800438 }
439
440 if (mkdir(mountPoint, 0777)) {
San Mehatb78a32c2010-01-10 13:02:12 -0800441 if (errno != EEXIST) {
442 LOGE("Mountpoint creation failed (%s)", strerror(errno));
443 if (cleanupDm) {
444 Devmapper::destroy(id);
445 }
446 Loop::destroyByDevice(loopDevice);
447 return -1;
448 }
San Mehata19b2502010-01-06 10:33:53 -0800449 }
450
San Mehatb78a32c2010-01-10 13:02:12 -0800451 if (Fat::doMount(dmDevice, mountPoint, true, false, ownerUid, 0,
San Mehatcff5ec32010-01-08 12:31:44 -0800452 0222, false)) {
453// 0227, false)) {
San Mehata19b2502010-01-06 10:33:53 -0800454 LOGE("ASEC mount failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800455 if (cleanupDm) {
456 Devmapper::destroy(id);
457 }
458 Loop::destroyByDevice(loopDevice);
San Mehata19b2502010-01-06 10:33:53 -0800459 return -1;
460 }
461
San Mehat88705162010-01-15 09:26:28 -0800462 mActiveContainers->push_back(strdup(id));
San Mehata19b2502010-01-06 10:33:53 -0800463 LOGD("ASEC %s mounted", id);
464 return 0;
465}
466
San Mehat49e2bce2009-10-12 16:29:01 -0700467int VolumeManager::mountVolume(const char *label) {
468 Volume *v = lookupVolume(label);
469
470 if (!v) {
471 errno = ENOENT;
472 return -1;
473 }
474
San Mehata2677e42009-12-13 10:40:18 -0800475 return v->mountVol();
476}
477
478int VolumeManager::shareAvailable(const char *method, bool *avail) {
479
480 if (strcmp(method, "ums")) {
481 errno = ENOSYS;
482 return -1;
483 }
484
485 if (mUsbMassStorageConnected)
486 *avail = true;
487 else
488 *avail = false;
489 return 0;
490}
491
492int VolumeManager::simulate(const char *cmd, const char *arg) {
493
494 if (!strcmp(cmd, "ums")) {
495 if (!strcmp(arg, "connect")) {
496 notifyUmsConnected(true);
497 } else if (!strcmp(arg, "disconnect")) {
498 notifyUmsConnected(false);
499 } else {
500 errno = EINVAL;
501 return -1;
502 }
503 } else {
504 errno = EINVAL;
505 return -1;
506 }
507 return 0;
508}
509
510int VolumeManager::shareVolume(const char *label, const char *method) {
511 Volume *v = lookupVolume(label);
512
513 if (!v) {
514 errno = ENOENT;
515 return -1;
516 }
517
518 /*
519 * Eventually, we'll want to support additional share back-ends,
520 * some of which may work while the media is mounted. For now,
521 * we just support UMS
522 */
523 if (strcmp(method, "ums")) {
524 errno = ENOSYS;
525 return -1;
526 }
527
528 if (v->getState() == Volume::State_NoMedia) {
529 errno = ENODEV;
530 return -1;
531 }
532
San Mehat49e2bce2009-10-12 16:29:01 -0700533 if (v->getState() != Volume::State_Idle) {
San Mehata2677e42009-12-13 10:40:18 -0800534 // You need to unmount manually befoe sharing
San Mehat49e2bce2009-10-12 16:29:01 -0700535 errno = EBUSY;
536 return -1;
537 }
538
San Mehata2677e42009-12-13 10:40:18 -0800539 dev_t d = v->getDiskDevice();
540 if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
541 // This volume does not support raw disk access
542 errno = EINVAL;
543 return -1;
544 }
545
546 int fd;
547 char nodepath[255];
548 snprintf(nodepath,
549 sizeof(nodepath), "/dev/block/vold/%d:%d",
550 MAJOR(d), MINOR(d));
551
San Mehat0cde53c2009-12-22 08:32:33 -0800552 if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file",
553 O_WRONLY)) < 0) {
San Mehata2677e42009-12-13 10:40:18 -0800554 LOGE("Unable to open ums lunfile (%s)", strerror(errno));
555 return -1;
556 }
557
558 if (write(fd, nodepath, strlen(nodepath)) < 0) {
559 LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
560 close(fd);
561 return -1;
562 }
563
564 close(fd);
565 v->handleVolumeShared();
566 return 0;
567}
568
569int VolumeManager::unshareVolume(const char *label, const char *method) {
570 Volume *v = lookupVolume(label);
571
572 if (!v) {
573 errno = ENOENT;
574 return -1;
575 }
576
577 if (strcmp(method, "ums")) {
578 errno = ENOSYS;
579 return -1;
580 }
581
582 if (v->getState() != Volume::State_Shared) {
583 errno = EINVAL;
584 return -1;
585 }
586
587 dev_t d = v->getDiskDevice();
588
589 int fd;
590 char nodepath[255];
591 snprintf(nodepath,
592 sizeof(nodepath), "/dev/block/vold/%d:%d",
593 MAJOR(d), MINOR(d));
594
San Mehat0cde53c2009-12-22 08:32:33 -0800595 if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file", O_WRONLY)) < 0) {
San Mehata2677e42009-12-13 10:40:18 -0800596 LOGE("Unable to open ums lunfile (%s)", strerror(errno));
597 return -1;
598 }
599
600 char ch = 0;
601 if (write(fd, &ch, 1) < 0) {
602 LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
603 close(fd);
604 return -1;
605 }
606
607 close(fd);
608 v->handleVolumeUnshared();
609 return 0;
San Mehat49e2bce2009-10-12 16:29:01 -0700610}
611
612int VolumeManager::unmountVolume(const char *label) {
613 Volume *v = lookupVolume(label);
614
615 if (!v) {
616 errno = ENOENT;
617 return -1;
618 }
619
San Mehata2677e42009-12-13 10:40:18 -0800620 if (v->getState() == Volume::State_NoMedia) {
621 errno = ENODEV;
622 return -1;
623 }
624
San Mehat49e2bce2009-10-12 16:29:01 -0700625 if (v->getState() != Volume::State_Mounted) {
San Mehata2677e42009-12-13 10:40:18 -0800626 LOGW("Attempt to unmount volume which isn't mounted (%d)\n",
627 v->getState());
San Mehat49e2bce2009-10-12 16:29:01 -0700628 errno = EBUSY;
629 return -1;
630 }
631
San Mehat88705162010-01-15 09:26:28 -0800632 while(mActiveContainers->size()) {
633 AsecIdCollection::iterator it = mActiveContainers->begin();
634 LOGI("Unmounting ASEC %s (dependant on %s)", *it, v->getMountpoint());
635 if (unmountAsec(*it)) {
636 LOGE("Failed to unmount ASEC %s (%s) - unmount of %s may fail!", *it,
637 strerror(errno), v->getMountpoint());
638 }
639 }
640
San Mehata2677e42009-12-13 10:40:18 -0800641 return v->unmountVol();
San Mehat49e2bce2009-10-12 16:29:01 -0700642}
643
San Mehata2677e42009-12-13 10:40:18 -0800644/*
645 * Looks up a volume by it's label or mount-point
646 */
San Mehat49e2bce2009-10-12 16:29:01 -0700647Volume *VolumeManager::lookupVolume(const char *label) {
648 VolumeCollection::iterator i;
649
650 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
San Mehata2677e42009-12-13 10:40:18 -0800651 if (label[0] == '/') {
652 if (!strcmp(label, (*i)->getMountpoint()))
653 return (*i);
654 } else {
655 if (!strcmp(label, (*i)->getLabel()))
656 return (*i);
657 }
San Mehat49e2bce2009-10-12 16:29:01 -0700658 }
659 return NULL;
660}
San Mehata19b2502010-01-06 10:33:53 -0800661
662bool VolumeManager::isMountpointMounted(const char *mp)
663{
664 char device[256];
665 char mount_path[256];
666 char rest[256];
667 FILE *fp;
668 char line[1024];
669
670 if (!(fp = fopen("/proc/mounts", "r"))) {
671 LOGE("Error opening /proc/mounts (%s)", strerror(errno));
672 return false;
673 }
674
675 while(fgets(line, sizeof(line), fp)) {
676 line[strlen(line)-1] = '\0';
677 sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
678 if (!strcmp(mount_path, mp)) {
679 fclose(fp);
680 return true;
681 }
682
683 }
684
685 fclose(fp);
686 return false;
687}
688