VolumeManager.cpp revision eb13a90bb96b329d8e24a6c3d4720ae88451d301
1f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat/*
2f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Copyright (C) 2008 The Android Open Source Project
3f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
4f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Licensed under the Apache License, Version 2.0 (the "License");
5f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * you may not use this file except in compliance with the License.
6f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * You may obtain a copy of the License at
7f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
8f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *      http://www.apache.org/licenses/LICENSE-2.0
9f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
10f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Unless required by applicable law or agreed to in writing, software
11f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * distributed under the License is distributed on an "AS IS" BASIS,
12f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * See the License for the specific language governing permissions and
14f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * limitations under the License.
15f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat */
16f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
17f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <stdio.h>
18fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat#include <stdlib.h>
19fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat#include <string.h>
20f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <errno.h>
21a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include <fcntl.h>
22a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include <sys/stat.h>
23a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include <sys/types.h>
24a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include <sys/mount.h>
25a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
26a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include <linux/kdev_t.h>
27f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
28f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#define LOG_TAG "Vold"
29f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
30f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <cutils/log.h>
31f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
32fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat#include <sysutils/NetlinkEvent.h>
33fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat
34f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "VolumeManager.h"
35ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehat#include "DirectVolume.h"
36a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "ResponseCode.h"
37a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include "Loop.h"
38a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include "Fat.h"
39f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
40f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::sInstance = NULL;
41f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
42f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::Instance() {
43f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!sInstance)
44f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        sInstance = new VolumeManager();
45f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return sInstance;
46f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
47f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
48f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::VolumeManager() {
49f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mBlockDevices = new BlockDeviceCollection();
50f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mVolumes = new VolumeCollection();
51f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mBroadcaster = NULL;
52a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mUsbMassStorageConnected = false;
53f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
54f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
55f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::~VolumeManager() {
56f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    delete mBlockDevices;
57f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
58f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
59f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::start() {
60f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
61f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
62f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
63f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::stop() {
64f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
65f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
66f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
67f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::addVolume(Volume *v) {
68f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mVolumes->push_back(v);
69f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
70f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
71f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
72a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid VolumeManager::notifyUmsConnected(bool connected) {
73a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char msg[255];
74a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
75a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (connected) {
76a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mUsbMassStorageConnected = true;
77a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
78a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mUsbMassStorageConnected = false;
79a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
80a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(msg, sizeof(msg), "Share method ums now %s",
81a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             (connected ? "available" : "unavailable"));
82a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
83a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    getBroadcaster()->sendBroadcast(ResponseCode::ShareAvailabilityChange,
84a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                    msg, false);
85a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
86a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
87a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid VolumeManager::handleSwitchEvent(NetlinkEvent *evt) {
880cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    const char *devpath = evt->findParam("DEVPATH");
89a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    const char *name = evt->findParam("SWITCH_NAME");
90a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    const char *state = evt->findParam("SWITCH_STATE");
91a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
920cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if (!name || !state) {
930cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat        LOGW("Switch %s event missing name/state info", devpath);
940cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat        return;
950cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    }
960cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat
97a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!strcmp(name, "usb_mass_storage")) {
98a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
99a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(state, "online"))  {
100a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(true);
101a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
102a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(false);
103a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
104a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
105a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Ignoring unknown switch '%s'", name);
106a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
107a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
108a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
109fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehatvoid VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
110fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    const char *devpath = evt->findParam("DEVPATH");
111f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
112fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    /* Lookup a volume to handle this device */
113f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator it;
114f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    bool hit = false;
115f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
116fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat        if (!(*it)->handleBlockEvent(evt)) {
117a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
118a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            LOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
119a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
120f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            hit = true;
121f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            break;
122f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        }
123f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
124f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
125f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!hit) {
126a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
127fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat        LOGW("No volumes handled block event for '%s'", devpath);
128a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
129f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
130f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
131f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
132f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::listVolumes(SocketClient *cli) {
133f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator i;
134f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
135f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
136f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        char *buffer;
137f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        asprintf(&buffer, "%s %s %d",
138f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getLabel(), (*i)->getMountpoint(),
139f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getState());
140a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
141f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        free(buffer);
142f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
143a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false);
144f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
145f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
14649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
147a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::formatVolume(const char *label) {
148a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
149a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
150a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
151a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
152a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
153a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
154a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
155a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->formatVol();
156a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
157a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
158a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
159a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
160a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
161a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
162a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
163a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!isMountpointMounted(mountPoint)) {
164a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = ENOENT;
165a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
166a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
167a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(buffer, maxlen, "/asec/%s", id);
168a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
169a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
170a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
171a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::createAsec(const char *id, int sizeMb,
172a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                              const char *fstype, const char *key, int ownerUid) {
173a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
174a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    mkdir("/sdcard/android_secure", 0777);
175a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
176a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (lookupVolume(id)) {
177a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC volume '%s' currently exists", id);
178a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EADDRINUSE;
179a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
180a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
181a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
182a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
183a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(asecFileName, sizeof(asecFileName),
184a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             "/sdcard/android_secure/%s.asec", id);
185a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
186a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!access(asecFileName, F_OK)) {
187a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
188a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             asecFileName, strerror(errno));
189a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EADDRINUSE;
190a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
191a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
192a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
193a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::createImageFile(asecFileName, sizeMb)) {
194a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC image file creation failed (%s)", strerror(errno));
195a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
196a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
197a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
198a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
199a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::getNextAvailable(loopDevice, sizeof(loopDevice))) {
200a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
201a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
202a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
203a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
204a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::create(loopDevice, asecFileName)) {
205a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC loop device creation failed (%s)", strerror(errno));
206a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
207a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
208a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
209a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
210a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    /* XXX: Start devmapper */
211a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
212a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Fat::format(loopDevice)) {
213a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC FAT format failed (%s)", strerror(errno));
214a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
215a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
216a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
217a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
218a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
219a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
220a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
221a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
222a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (mkdir(mountPoint, 0777)) {
223eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat        if (errno != EEXIST) {
224eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            LOGE("Mountpoint creation failed (%s)", strerror(errno));
225eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            Loop::destroyByDevice(loopDevice);
226eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            unlink(asecFileName);
227eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            return -1;
228eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat        }
229a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
230a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
231fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    if (Fat::doMount(loopDevice, mountPoint, false, false, ownerUid,
232fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat                     0, 0007, false)) {
233a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC FAT mount failed (%s)", strerror(errno));
234a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
235a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
236a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
237a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
238a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
239a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
240a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
241a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
242a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::finalizeAsec(const char *id) {
243a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
244a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
245a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
246a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
247a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(asecFileName, sizeof(asecFileName),
248a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             "/sdcard/android_secure/%s.asec", id);
249a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
250a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
251a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Unable to finalize %s (%s)", id, strerror(errno));
252a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
253a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
254a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
255a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
256fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    // XXX:
257fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    if (Fat::doMount(loopDevice, mountPoint, true, true, 0, 0, 0227, false)) {
258a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC finalize mount failed (%s)", strerror(errno));
259a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
260a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
261a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
262a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s finalized", id);
263a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
264a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
265a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
266a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::destroyAsec(const char *id) {
267a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
268a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
269a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
270a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(asecFileName, sizeof(asecFileName),
271a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             "/sdcard/android_secure/%s.asec", id);
272a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
273a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
274a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (isMountpointMounted(mountPoint)) {
275a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        int i, rc;
276a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        for (i = 0; i < 10; i++) {
277a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            rc = umount(mountPoint);
278a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            if (!rc) {
279a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                break;
280a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            }
281a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            if (rc && (errno == EINVAL || errno == ENOENT)) {
282a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                rc = 0;
283a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                break;
284a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            }
285a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            LOGW("ASEC %s unmount attempt %d failed (%s)",
286a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                  id, i +1, strerror(errno));
287a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            usleep(1000 * 250);
288a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
289a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (rc) {
290a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            LOGE("Failed to unmount ASEC %s for destroy", id);
291a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return -1;
292a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
293a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
294a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
295a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
296a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
297a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
298a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
299a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
300a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    unlink(asecFileName);
301a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
302a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s destroyed", id);
303a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
304a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
305a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
306a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
307a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
308a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
309a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
310a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(asecFileName, sizeof(asecFileName),
311a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             "/sdcard/android_secure/%s.asec", id);
312a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
313a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
314a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (isMountpointMounted(mountPoint)) {
315a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC %s already mounted", id);
316a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EBUSY;
317a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
318a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
319a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
320a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
321a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
322a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (Loop::getNextAvailable(loopDevice, sizeof(loopDevice))) {
323a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            LOGE("Unable to find loop device for ASEC mount");
324a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return -1;
325a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
326a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
327a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (Loop::create(loopDevice, asecFileName)) {
328a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            LOGE("ASEC loop device creation failed (%s)", strerror(errno));
329a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return -1;
330a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
331a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
332a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
333a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (mkdir(mountPoint, 0777)) {
334a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Mountpoint creation failed (%s)", strerror(errno));
335a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
336a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
337a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
338fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    if (Fat::doMount(loopDevice, mountPoint, true, false, ownerUid, 0,
339fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat                     0227, false)) {
340a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC mount failed (%s)", strerror(errno));
341a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
342a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
343a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
344a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s mounted", id);
345a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
346a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
347a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
34849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint VolumeManager::mountVolume(const char *label) {
34949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
35049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
35149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
35249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
35349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
35449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
35549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
356a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->mountVol();
357a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
358a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
359a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareAvailable(const char *method, bool *avail) {
360a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
361a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
362a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
363a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
364a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
365a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
366a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (mUsbMassStorageConnected)
367a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        *avail = true;
368a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else
369a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        *avail = false;
370a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
371a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
372a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
373a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::simulate(const char *cmd, const char *arg) {
374a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
375a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!strcmp(cmd, "ums")) {
376a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(arg, "connect")) {
377a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(true);
378a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else if (!strcmp(arg, "disconnect")) {
379a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(false);
380a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
381a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            errno = EINVAL;
382a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            return -1;
383a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
384a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
385a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
386a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
387a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
388a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
389a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
390a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
391a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareVolume(const char *label, const char *method) {
392a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
393a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
394a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
395a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
396a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
397a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
398a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
399a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    /*
400a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * Eventually, we'll want to support additional share back-ends,
401a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * some of which may work while the media is mounted. For now,
402a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * we just support UMS
403a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     */
404a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
405a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
406a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
407a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
408a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
409a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
410a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
411a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
412a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
413a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
41449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Idle) {
415a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // You need to unmount manually befoe sharing
41649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
41749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
41849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
41949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
420a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t d = v->getDiskDevice();
421a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
422a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // This volume does not support raw disk access
423a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
424a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
425a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
426a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
427a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
428a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
429a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
430a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
431a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
432a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
4330cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file",
4340cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat                   O_WRONLY)) < 0) {
435a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to open ums lunfile (%s)", strerror(errno));
436a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
437a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
438a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
439a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, nodepath, strlen(nodepath)) < 0) {
440a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
441a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
442a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
443a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
444a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
445a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
446a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeShared();
447a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
448a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
449a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
450a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::unshareVolume(const char *label, const char *method) {
451a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
452a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
453a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
454a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
455a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
456a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
457a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
458a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
459a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
460a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
461a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
462a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
463a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() != Volume::State_Shared) {
464a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
465a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
466a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
467a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
468a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t d = v->getDiskDevice();
469a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
470a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
471a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
472a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
473a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
474a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
475a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
4760cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file", O_WRONLY)) < 0) {
477a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to open ums lunfile (%s)", strerror(errno));
478a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
479a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
480a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
481a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char ch = 0;
482a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, &ch, 1) < 0) {
483a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
484a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
485a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
486a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
487a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
488a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
489a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeUnshared();
490a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
49149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
49249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
49349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint VolumeManager::unmountVolume(const char *label) {
49449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
49549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
49649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
49749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
49849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
49949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
50049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
501a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
502a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
503a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
504a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
505a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
50649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Mounted) {
507a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Attempt to unmount volume which isn't mounted (%d)\n",
508a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             v->getState());
50949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
51049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
51149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
51249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
513a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->unmountVol();
51449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
51549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
516a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat/*
517a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * Looks up a volume by it's label or mount-point
518a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat */
51949e2bce5b74129c26a35e25d4693cbfe98c4688eSan MehatVolume *VolumeManager::lookupVolume(const char *label) {
52049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    VolumeCollection::iterator i;
52149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
52249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
523a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (label[0] == '/') {
524a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getMountpoint()))
525a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
526a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
527a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getLabel()))
528a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
529a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
53049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
53149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    return NULL;
53249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
533a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
534a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatbool VolumeManager::isMountpointMounted(const char *mp)
535a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat{
536a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char device[256];
537a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mount_path[256];
538a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char rest[256];
539a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    FILE *fp;
540a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char line[1024];
541a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
542a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!(fp = fopen("/proc/mounts", "r"))) {
543a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Error opening /proc/mounts (%s)", strerror(errno));
544a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return false;
545a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
546a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
547a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    while(fgets(line, sizeof(line), fp)) {
548a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        line[strlen(line)-1] = '\0';
549a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
550a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (!strcmp(mount_path, mp)) {
551a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            fclose(fp);
552a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return true;
553a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
554a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
555a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
556a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
557a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    fclose(fp);
558a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return false;
559a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
560a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
561