blob: 596590dbf579103cff5f57e3857f6a634dda7ab4 [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();
54 mBroadcaster = NULL;
San Mehata2677e42009-12-13 10:40:18 -080055 mUsbMassStorageConnected = false;
San Mehatf1b736b2009-10-10 17:22:08 -070056}
57
58VolumeManager::~VolumeManager() {
59 delete mBlockDevices;
60}
61
62int VolumeManager::start() {
63 return 0;
64}
65
66int VolumeManager::stop() {
67 return 0;
68}
69
70int VolumeManager::addVolume(Volume *v) {
71 mVolumes->push_back(v);
72 return 0;
73}
74
San Mehata2677e42009-12-13 10:40:18 -080075void VolumeManager::notifyUmsConnected(bool connected) {
76 char msg[255];
77
78 if (connected) {
79 mUsbMassStorageConnected = true;
80 } else {
81 mUsbMassStorageConnected = false;
82 }
83 snprintf(msg, sizeof(msg), "Share method ums now %s",
84 (connected ? "available" : "unavailable"));
85
86 getBroadcaster()->sendBroadcast(ResponseCode::ShareAvailabilityChange,
87 msg, false);
88}
89
90void VolumeManager::handleSwitchEvent(NetlinkEvent *evt) {
San Mehat0cde53c2009-12-22 08:32:33 -080091 const char *devpath = evt->findParam("DEVPATH");
San Mehata2677e42009-12-13 10:40:18 -080092 const char *name = evt->findParam("SWITCH_NAME");
93 const char *state = evt->findParam("SWITCH_STATE");
94
San Mehat0cde53c2009-12-22 08:32:33 -080095 if (!name || !state) {
96 LOGW("Switch %s event missing name/state info", devpath);
97 return;
98 }
99
San Mehata2677e42009-12-13 10:40:18 -0800100 if (!strcmp(name, "usb_mass_storage")) {
101
102 if (!strcmp(state, "online")) {
103 notifyUmsConnected(true);
104 } else {
105 notifyUmsConnected(false);
106 }
107 } else {
108 LOGW("Ignoring unknown switch '%s'", name);
109 }
110}
111
San Mehatfd7f5872009-10-12 11:32:47 -0700112void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
113 const char *devpath = evt->findParam("DEVPATH");
San Mehatf1b736b2009-10-10 17:22:08 -0700114
San Mehatfd7f5872009-10-12 11:32:47 -0700115 /* Lookup a volume to handle this device */
San Mehatf1b736b2009-10-10 17:22:08 -0700116 VolumeCollection::iterator it;
117 bool hit = false;
118 for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
San Mehatfd7f5872009-10-12 11:32:47 -0700119 if (!(*it)->handleBlockEvent(evt)) {
San Mehata2677e42009-12-13 10:40:18 -0800120#ifdef NETLINK_DEBUG
121 LOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
122#endif
San Mehatf1b736b2009-10-10 17:22:08 -0700123 hit = true;
San Mehatf1b736b2009-10-10 17:22:08 -0700124 break;
125 }
126 }
127
128 if (!hit) {
San Mehata2677e42009-12-13 10:40:18 -0800129#ifdef NETLINK_DEBUG
San Mehatfd7f5872009-10-12 11:32:47 -0700130 LOGW("No volumes handled block event for '%s'", devpath);
San Mehata2677e42009-12-13 10:40:18 -0800131#endif
San Mehatf1b736b2009-10-10 17:22:08 -0700132 }
133}
134
San Mehatf1b736b2009-10-10 17:22:08 -0700135int VolumeManager::listVolumes(SocketClient *cli) {
136 VolumeCollection::iterator i;
137
138 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
139 char *buffer;
140 asprintf(&buffer, "%s %s %d",
141 (*i)->getLabel(), (*i)->getMountpoint(),
142 (*i)->getState());
San Mehata2677e42009-12-13 10:40:18 -0800143 cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
San Mehatf1b736b2009-10-10 17:22:08 -0700144 free(buffer);
145 }
San Mehata2677e42009-12-13 10:40:18 -0800146 cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false);
San Mehatf1b736b2009-10-10 17:22:08 -0700147 return 0;
148}
San Mehat49e2bce2009-10-12 16:29:01 -0700149
San Mehata2677e42009-12-13 10:40:18 -0800150int VolumeManager::formatVolume(const char *label) {
151 Volume *v = lookupVolume(label);
152
153 if (!v) {
154 errno = ENOENT;
155 return -1;
156 }
157
158 return v->formatVol();
159}
160
San Mehata19b2502010-01-06 10:33:53 -0800161int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
162 char mountPoint[255];
163
164 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
165
166 if (!isMountpointMounted(mountPoint)) {
167 errno = ENOENT;
168 return -1;
169 }
170 snprintf(buffer, maxlen, "/asec/%s", id);
171 return 0;
172}
173
San Mehat8b8f71b2010-01-11 09:17:25 -0800174int VolumeManager::createAsec(const char *id, unsigned int numSectors,
San Mehata19b2502010-01-06 10:33:53 -0800175 const char *fstype, const char *key, int ownerUid) {
176
177 mkdir("/sdcard/android_secure", 0777);
178
179 if (lookupVolume(id)) {
180 LOGE("ASEC volume '%s' currently exists", id);
181 errno = EADDRINUSE;
182 return -1;
183 }
184
185 char asecFileName[255];
186 snprintf(asecFileName, sizeof(asecFileName),
187 "/sdcard/android_secure/%s.asec", id);
188
189 if (!access(asecFileName, F_OK)) {
190 LOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
191 asecFileName, strerror(errno));
192 errno = EADDRINUSE;
193 return -1;
194 }
195
San Mehat8b8f71b2010-01-11 09:17:25 -0800196 if (Loop::createImageFile(asecFileName, numSectors)) {
San Mehata19b2502010-01-06 10:33:53 -0800197 LOGE("ASEC image file creation failed (%s)", strerror(errno));
198 return -1;
199 }
200
201 char loopDevice[255];
San Mehat8da6bcb2010-01-09 12:24:05 -0800202 if (Loop::create(asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehata19b2502010-01-06 10:33:53 -0800203 LOGE("ASEC loop device creation failed (%s)", strerror(errno));
204 unlink(asecFileName);
205 return -1;
206 }
207
San Mehatb78a32c2010-01-10 13:02:12 -0800208 char dmDevice[255];
209 bool cleanupDm = false;
San Mehata19b2502010-01-06 10:33:53 -0800210
San Mehatb78a32c2010-01-10 13:02:12 -0800211 if (strcmp(key, "none")) {
San Mehat8b8f71b2010-01-11 09:17:25 -0800212 if (Devmapper::create(id, loopDevice, key, numSectors, dmDevice,
San Mehatb78a32c2010-01-10 13:02:12 -0800213 sizeof(dmDevice))) {
214 LOGE("ASEC device mapping failed (%s)", strerror(errno));
215 Loop::destroyByDevice(loopDevice);
216 unlink(asecFileName);
217 return -1;
218 }
219 cleanupDm = true;
220 } else {
221 strcpy(dmDevice, loopDevice);
222 }
223
224 if (Fat::format(dmDevice)) {
San Mehata19b2502010-01-06 10:33:53 -0800225 LOGE("ASEC FAT format failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800226 if (cleanupDm) {
227 Devmapper::destroy(id);
228 }
San Mehata19b2502010-01-06 10:33:53 -0800229 Loop::destroyByDevice(loopDevice);
230 unlink(asecFileName);
231 return -1;
232 }
233
234 char mountPoint[255];
235
236 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
237 if (mkdir(mountPoint, 0777)) {
San Mehateb13a902010-01-07 12:12:50 -0800238 if (errno != EEXIST) {
239 LOGE("Mountpoint creation failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800240 if (cleanupDm) {
241 Devmapper::destroy(id);
242 }
San Mehateb13a902010-01-07 12:12:50 -0800243 Loop::destroyByDevice(loopDevice);
244 unlink(asecFileName);
245 return -1;
246 }
San Mehata19b2502010-01-06 10:33:53 -0800247 }
248
San Mehatb78a32c2010-01-10 13:02:12 -0800249 if (Fat::doMount(dmDevice, mountPoint, false, false, ownerUid,
San Mehatcff5ec32010-01-08 12:31:44 -0800250 0, 0000, false)) {
251// 0, 0007, false)) {
San Mehata19b2502010-01-06 10:33:53 -0800252 LOGE("ASEC FAT mount failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800253 if (cleanupDm) {
254 Devmapper::destroy(id);
255 }
San Mehata19b2502010-01-06 10:33:53 -0800256 Loop::destroyByDevice(loopDevice);
257 unlink(asecFileName);
258 return -1;
259 }
260
261 return 0;
262}
263
264int VolumeManager::finalizeAsec(const char *id) {
265 char asecFileName[255];
266 char loopDevice[255];
267 char mountPoint[255];
268
269 snprintf(asecFileName, sizeof(asecFileName),
270 "/sdcard/android_secure/%s.asec", id);
271
272 if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
273 LOGE("Unable to finalize %s (%s)", id, strerror(errno));
274 return -1;
275 }
276
277 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
San Mehatfff0b472010-01-06 19:19:46 -0800278 // XXX:
279 if (Fat::doMount(loopDevice, mountPoint, true, true, 0, 0, 0227, false)) {
San Mehata19b2502010-01-06 10:33:53 -0800280 LOGE("ASEC finalize mount failed (%s)", strerror(errno));
281 return -1;
282 }
283
284 LOGD("ASEC %s finalized", id);
285 return 0;
286}
287
San Mehatb78a32c2010-01-10 13:02:12 -0800288int VolumeManager::unmountAsec(const char *id) {
San Mehata19b2502010-01-06 10:33:53 -0800289 char asecFileName[255];
290 char mountPoint[255];
291
292 snprintf(asecFileName, sizeof(asecFileName),
293 "/sdcard/android_secure/%s.asec", id);
294 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
295
San Mehat0586d542010-01-12 15:38:59 -0800296 if (!isMountpointMounted(mountPoint)) {
San Mehatb78a32c2010-01-10 13:02:12 -0800297 LOGE("Unmount request for ASEC %s when not mounted", id);
298 errno = EINVAL;
299 return -1;
300 }
San Mehat23969932010-01-09 07:08:06 -0800301
San Mehatb78a32c2010-01-10 13:02:12 -0800302 int i, rc;
303 for (i = 0; i < 10; i++) {
304 rc = umount(mountPoint);
305 if (!rc) {
306 break;
San Mehata19b2502010-01-06 10:33:53 -0800307 }
San Mehatb78a32c2010-01-10 13:02:12 -0800308 if (rc && (errno == EINVAL || errno == ENOENT)) {
309 rc = 0;
310 break;
San Mehata19b2502010-01-06 10:33:53 -0800311 }
San Mehatb78a32c2010-01-10 13:02:12 -0800312 LOGW("ASEC %s unmount attempt %d failed (%s)",
313 id, i +1, strerror(errno));
314
315 if (i >= 5) {
316 KillProcessesWithOpenFiles(mountPoint, (i < 7 ? 0 : 1),
317 NULL, 0);
318 }
319 usleep(1000 * 250);
320 }
321
322 if (rc) {
323 LOGE("Failed to unmount ASEC %s", id);
324 return -1;
325 }
326
327 if (Devmapper::destroy(id) && errno != ENXIO) {
328 LOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
San Mehata19b2502010-01-06 10:33:53 -0800329 }
330
331 char loopDevice[255];
332 if (!Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
333 Loop::destroyByDevice(loopDevice);
334 }
San Mehatb78a32c2010-01-10 13:02:12 -0800335 return 0;
336}
337
338int VolumeManager::destroyAsec(const char *id) {
339 char asecFileName[255];
340 char mountPoint[255];
341
342 snprintf(asecFileName, sizeof(asecFileName),
343 "/sdcard/android_secure/%s.asec", id);
344 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
345
San Mehat0586d542010-01-12 15:38:59 -0800346 if (isMountpointMounted(mountPoint)) {
347 if (unmountAsec(id)) {
348 LOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
349 return -1;
350 }
351 }
San Mehata19b2502010-01-06 10:33:53 -0800352
San Mehat0586d542010-01-12 15:38:59 -0800353 if (unlink(asecFileName)) {
354 LOGE("Failed to unlink asec %s (%s)", id, strerror(errno));
355 return -1;
356 }
San Mehata19b2502010-01-06 10:33:53 -0800357
358 LOGD("ASEC %s destroyed", id);
359 return 0;
360}
361
362int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
363 char asecFileName[255];
364 char mountPoint[255];
365
366 snprintf(asecFileName, sizeof(asecFileName),
367 "/sdcard/android_secure/%s.asec", id);
368 snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
369
370 if (isMountpointMounted(mountPoint)) {
371 LOGE("ASEC %s already mounted", id);
372 errno = EBUSY;
373 return -1;
374 }
375
376 char loopDevice[255];
377 if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehat8da6bcb2010-01-09 12:24:05 -0800378 if (Loop::create(asecFileName, loopDevice, sizeof(loopDevice))) {
San Mehata19b2502010-01-06 10:33:53 -0800379 LOGE("ASEC loop device creation failed (%s)", strerror(errno));
380 return -1;
381 }
San Mehatb78a32c2010-01-10 13:02:12 -0800382 LOGD("New loop device created at %s", loopDevice);
383 } else {
384 LOGD("Found active loopback for %s at %s", asecFileName, loopDevice);
385 }
386
387 char dmDevice[255];
388 bool cleanupDm = false;
389 if (strcmp(key, "none")) {
390 if (Devmapper::lookupActive(id, dmDevice, sizeof(dmDevice))) {
391 unsigned int nr_sec = 0;
392 int fd;
393
394 if ((fd = open(loopDevice, O_RDWR)) < 0) {
395 LOGE("Failed to open loopdevice (%s)", strerror(errno));
396 Loop::destroyByDevice(loopDevice);
397 return -1;
398 }
399
400 if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
401 LOGE("Failed to get loop size (%s)", strerror(errno));
402 Loop::destroyByDevice(loopDevice);
403 close(fd);
404 return -1;
405 }
406 close(fd);
San Mehat8b8f71b2010-01-11 09:17:25 -0800407 if (Devmapper::create(id, loopDevice, key, nr_sec,
San Mehatb78a32c2010-01-10 13:02:12 -0800408 dmDevice, sizeof(dmDevice))) {
409 LOGE("ASEC device mapping failed (%s)", strerror(errno));
410 Loop::destroyByDevice(loopDevice);
411 return -1;
412 }
413 LOGD("New devmapper instance created at %s", dmDevice);
414 } else {
415 LOGD("Found active devmapper for %s at %s", asecFileName, dmDevice);
416 }
417 cleanupDm = true;
418 } else {
419 strcpy(dmDevice, loopDevice);
San Mehata19b2502010-01-06 10:33:53 -0800420 }
421
422 if (mkdir(mountPoint, 0777)) {
San Mehatb78a32c2010-01-10 13:02:12 -0800423 if (errno != EEXIST) {
424 LOGE("Mountpoint creation failed (%s)", strerror(errno));
425 if (cleanupDm) {
426 Devmapper::destroy(id);
427 }
428 Loop::destroyByDevice(loopDevice);
429 return -1;
430 }
San Mehata19b2502010-01-06 10:33:53 -0800431 }
432
San Mehatb78a32c2010-01-10 13:02:12 -0800433 if (Fat::doMount(dmDevice, mountPoint, true, false, ownerUid, 0,
San Mehatcff5ec32010-01-08 12:31:44 -0800434 0222, false)) {
435// 0227, false)) {
San Mehata19b2502010-01-06 10:33:53 -0800436 LOGE("ASEC mount failed (%s)", strerror(errno));
San Mehatb78a32c2010-01-10 13:02:12 -0800437 if (cleanupDm) {
438 Devmapper::destroy(id);
439 }
440 Loop::destroyByDevice(loopDevice);
San Mehata19b2502010-01-06 10:33:53 -0800441 return -1;
442 }
443
444 LOGD("ASEC %s mounted", id);
445 return 0;
446}
447
San Mehat49e2bce2009-10-12 16:29:01 -0700448int VolumeManager::mountVolume(const char *label) {
449 Volume *v = lookupVolume(label);
450
451 if (!v) {
452 errno = ENOENT;
453 return -1;
454 }
455
San Mehata2677e42009-12-13 10:40:18 -0800456 return v->mountVol();
457}
458
459int VolumeManager::shareAvailable(const char *method, bool *avail) {
460
461 if (strcmp(method, "ums")) {
462 errno = ENOSYS;
463 return -1;
464 }
465
466 if (mUsbMassStorageConnected)
467 *avail = true;
468 else
469 *avail = false;
470 return 0;
471}
472
473int VolumeManager::simulate(const char *cmd, const char *arg) {
474
475 if (!strcmp(cmd, "ums")) {
476 if (!strcmp(arg, "connect")) {
477 notifyUmsConnected(true);
478 } else if (!strcmp(arg, "disconnect")) {
479 notifyUmsConnected(false);
480 } else {
481 errno = EINVAL;
482 return -1;
483 }
484 } else {
485 errno = EINVAL;
486 return -1;
487 }
488 return 0;
489}
490
491int VolumeManager::shareVolume(const char *label, const char *method) {
492 Volume *v = lookupVolume(label);
493
494 if (!v) {
495 errno = ENOENT;
496 return -1;
497 }
498
499 /*
500 * Eventually, we'll want to support additional share back-ends,
501 * some of which may work while the media is mounted. For now,
502 * we just support UMS
503 */
504 if (strcmp(method, "ums")) {
505 errno = ENOSYS;
506 return -1;
507 }
508
509 if (v->getState() == Volume::State_NoMedia) {
510 errno = ENODEV;
511 return -1;
512 }
513
San Mehat49e2bce2009-10-12 16:29:01 -0700514 if (v->getState() != Volume::State_Idle) {
San Mehata2677e42009-12-13 10:40:18 -0800515 // You need to unmount manually befoe sharing
San Mehat49e2bce2009-10-12 16:29:01 -0700516 errno = EBUSY;
517 return -1;
518 }
519
San Mehata2677e42009-12-13 10:40:18 -0800520 dev_t d = v->getDiskDevice();
521 if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
522 // This volume does not support raw disk access
523 errno = EINVAL;
524 return -1;
525 }
526
527 int fd;
528 char nodepath[255];
529 snprintf(nodepath,
530 sizeof(nodepath), "/dev/block/vold/%d:%d",
531 MAJOR(d), MINOR(d));
532
San Mehat0cde53c2009-12-22 08:32:33 -0800533 if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file",
534 O_WRONLY)) < 0) {
San Mehata2677e42009-12-13 10:40:18 -0800535 LOGE("Unable to open ums lunfile (%s)", strerror(errno));
536 return -1;
537 }
538
539 if (write(fd, nodepath, strlen(nodepath)) < 0) {
540 LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
541 close(fd);
542 return -1;
543 }
544
545 close(fd);
546 v->handleVolumeShared();
547 return 0;
548}
549
550int VolumeManager::unshareVolume(const char *label, const char *method) {
551 Volume *v = lookupVolume(label);
552
553 if (!v) {
554 errno = ENOENT;
555 return -1;
556 }
557
558 if (strcmp(method, "ums")) {
559 errno = ENOSYS;
560 return -1;
561 }
562
563 if (v->getState() != Volume::State_Shared) {
564 errno = EINVAL;
565 return -1;
566 }
567
568 dev_t d = v->getDiskDevice();
569
570 int fd;
571 char nodepath[255];
572 snprintf(nodepath,
573 sizeof(nodepath), "/dev/block/vold/%d:%d",
574 MAJOR(d), MINOR(d));
575
San Mehat0cde53c2009-12-22 08:32:33 -0800576 if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file", O_WRONLY)) < 0) {
San Mehata2677e42009-12-13 10:40:18 -0800577 LOGE("Unable to open ums lunfile (%s)", strerror(errno));
578 return -1;
579 }
580
581 char ch = 0;
582 if (write(fd, &ch, 1) < 0) {
583 LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
584 close(fd);
585 return -1;
586 }
587
588 close(fd);
589 v->handleVolumeUnshared();
590 return 0;
San Mehat49e2bce2009-10-12 16:29:01 -0700591}
592
593int VolumeManager::unmountVolume(const char *label) {
594 Volume *v = lookupVolume(label);
595
596 if (!v) {
597 errno = ENOENT;
598 return -1;
599 }
600
San Mehata2677e42009-12-13 10:40:18 -0800601 if (v->getState() == Volume::State_NoMedia) {
602 errno = ENODEV;
603 return -1;
604 }
605
San Mehat49e2bce2009-10-12 16:29:01 -0700606 if (v->getState() != Volume::State_Mounted) {
San Mehata2677e42009-12-13 10:40:18 -0800607 LOGW("Attempt to unmount volume which isn't mounted (%d)\n",
608 v->getState());
San Mehat49e2bce2009-10-12 16:29:01 -0700609 errno = EBUSY;
610 return -1;
611 }
612
San Mehata2677e42009-12-13 10:40:18 -0800613 return v->unmountVol();
San Mehat49e2bce2009-10-12 16:29:01 -0700614}
615
San Mehata2677e42009-12-13 10:40:18 -0800616/*
617 * Looks up a volume by it's label or mount-point
618 */
San Mehat49e2bce2009-10-12 16:29:01 -0700619Volume *VolumeManager::lookupVolume(const char *label) {
620 VolumeCollection::iterator i;
621
622 for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
San Mehata2677e42009-12-13 10:40:18 -0800623 if (label[0] == '/') {
624 if (!strcmp(label, (*i)->getMountpoint()))
625 return (*i);
626 } else {
627 if (!strcmp(label, (*i)->getLabel()))
628 return (*i);
629 }
San Mehat49e2bce2009-10-12 16:29:01 -0700630 }
631 return NULL;
632}
San Mehata19b2502010-01-06 10:33:53 -0800633
634bool VolumeManager::isMountpointMounted(const char *mp)
635{
636 char device[256];
637 char mount_path[256];
638 char rest[256];
639 FILE *fp;
640 char line[1024];
641
642 if (!(fp = fopen("/proc/mounts", "r"))) {
643 LOGE("Error opening /proc/mounts (%s)", strerror(errno));
644 return false;
645 }
646
647 while(fgets(line, sizeof(line), fp)) {
648 line[strlen(line)-1] = '\0';
649 sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
650 if (!strcmp(mount_path, mp)) {
651 fclose(fp);
652 return true;
653 }
654
655 }
656
657 fclose(fp);
658 return false;
659}
660