VolumeManager.cpp revision 0cde53ce7b44ce189d0bc6fa81c0036e096deb51
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>
22a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include <linux/kdev_t.h>
23f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
24f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#define LOG_TAG "Vold"
25f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
26f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <cutils/log.h>
27f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
28fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat#include <sysutils/NetlinkEvent.h>
29fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat
30f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "VolumeManager.h"
31ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehat#include "DirectVolume.h"
32a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "ResponseCode.h"
33f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
34f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::sInstance = NULL;
35f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
36f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::Instance() {
37f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!sInstance)
38f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        sInstance = new VolumeManager();
39f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return sInstance;
40f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
41f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
42f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::VolumeManager() {
43f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mBlockDevices = new BlockDeviceCollection();
44f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mVolumes = new VolumeCollection();
45f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mBroadcaster = NULL;
46a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mUsbMassStorageConnected = false;
47f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
48f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
49f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::~VolumeManager() {
50f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    delete mBlockDevices;
51f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
52f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
53f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::start() {
54f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
55f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
56f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
57f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::stop() {
58f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
59f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
60f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
61f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::addVolume(Volume *v) {
62f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mVolumes->push_back(v);
63f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
64f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
65f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
66a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid VolumeManager::notifyUmsConnected(bool connected) {
67a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char msg[255];
68a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
69a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (connected) {
70a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mUsbMassStorageConnected = true;
71a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
72a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mUsbMassStorageConnected = false;
73a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
74a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(msg, sizeof(msg), "Share method ums now %s",
75a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             (connected ? "available" : "unavailable"));
76a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
77a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    getBroadcaster()->sendBroadcast(ResponseCode::ShareAvailabilityChange,
78a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                    msg, false);
79a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
80a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
81a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid VolumeManager::handleSwitchEvent(NetlinkEvent *evt) {
820cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    const char *devpath = evt->findParam("DEVPATH");
83a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    const char *name = evt->findParam("SWITCH_NAME");
84a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    const char *state = evt->findParam("SWITCH_STATE");
85a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
860cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if (!name || !state) {
870cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat        LOGW("Switch %s event missing name/state info", devpath);
880cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat        return;
890cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    }
900cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat
91a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!strcmp(name, "usb_mass_storage")) {
92a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
93a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(state, "online"))  {
94a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(true);
95a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
96a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(false);
97a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
98a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
99a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Ignoring unknown switch '%s'", name);
100a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
101a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
102a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
103fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehatvoid VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
104fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    const char *devpath = evt->findParam("DEVPATH");
105f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
106fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    /* Lookup a volume to handle this device */
107f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator it;
108f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    bool hit = false;
109f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
110fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat        if (!(*it)->handleBlockEvent(evt)) {
111a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
112a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            LOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
113a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
114f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            hit = true;
115f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            break;
116f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        }
117f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
118f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
119f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!hit) {
120a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
121fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat        LOGW("No volumes handled block event for '%s'", devpath);
122a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
123f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
124f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
125f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
126f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::listVolumes(SocketClient *cli) {
127f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator i;
128f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
129f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
130f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        char *buffer;
131f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        asprintf(&buffer, "%s %s %d",
132f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getLabel(), (*i)->getMountpoint(),
133f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getState());
134a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
135f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        free(buffer);
136f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
137a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false);
138f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
139f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
14049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
141a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::formatVolume(const char *label) {
142a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
143a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
144a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
145a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
146a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
147a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
148a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
149a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->formatVol();
150a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
151a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
15249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint VolumeManager::mountVolume(const char *label) {
15349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
15449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
15549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
15649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
15749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
15849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
15949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
160a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->mountVol();
161a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
162a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
163a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareAvailable(const char *method, bool *avail) {
164a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
165a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
166a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
167a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
168a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
169a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
170a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (mUsbMassStorageConnected)
171a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        *avail = true;
172a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else
173a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        *avail = false;
174a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
175a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
176a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
177a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::simulate(const char *cmd, const char *arg) {
178a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
179a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!strcmp(cmd, "ums")) {
180a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(arg, "connect")) {
181a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(true);
182a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else if (!strcmp(arg, "disconnect")) {
183a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(false);
184a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
185a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            errno = EINVAL;
186a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            return -1;
187a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
188a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
189a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
190a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
191a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
192a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
193a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
194a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
195a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareVolume(const char *label, const char *method) {
196a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
197a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
198a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
199a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
200a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
201a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
202a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
203a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    /*
204a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * Eventually, we'll want to support additional share back-ends,
205a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * some of which may work while the media is mounted. For now,
206a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * we just support UMS
207a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     */
208a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
209a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
210a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
211a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
212a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
213a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
214a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
215a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
216a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
217a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
21849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Idle) {
219a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // You need to unmount manually befoe sharing
22049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
22149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
22249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
22349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
224a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t d = v->getDiskDevice();
225a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
226a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // This volume does not support raw disk access
227a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
228a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
229a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
230a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
231a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
232a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
233a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
234a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
235a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
236a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
2370cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file",
2380cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat                   O_WRONLY)) < 0) {
239a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to open ums lunfile (%s)", strerror(errno));
240a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
241a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
242a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
243a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, nodepath, strlen(nodepath)) < 0) {
244a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
245a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
246a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
247a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
248a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
249a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
250a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeShared();
251a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
252a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
253a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
254a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::unshareVolume(const char *label, const char *method) {
255a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
256a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
257a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
258a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
259a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
260a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
261a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
262a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
263a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
264a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
265a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
266a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
267a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() != Volume::State_Shared) {
268a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
269a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
270a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
271a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
272a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t d = v->getDiskDevice();
273a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
274a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
275a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
276a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
277a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
278a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
279a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
2800cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file", O_WRONLY)) < 0) {
281a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to open ums lunfile (%s)", strerror(errno));
282a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
283a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
284a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
285a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char ch = 0;
286a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, &ch, 1) < 0) {
287a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
288a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
289a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
290a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
291a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
292a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
293a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeUnshared();
294a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
29549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
29649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
29749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint VolumeManager::unmountVolume(const char *label) {
29849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
29949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
30049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
30149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
30249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
30349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
30449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
305a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
306a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
307a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
308a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
309a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
31049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Mounted) {
311a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Attempt to unmount volume which isn't mounted (%d)\n",
312a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             v->getState());
31349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
31449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
31549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
31649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
317a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->unmountVol();
31849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
31949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
320a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat/*
321a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * Looks up a volume by it's label or mount-point
322a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat */
32349e2bce5b74129c26a35e25d4693cbfe98c4688eSan MehatVolume *VolumeManager::lookupVolume(const char *label) {
32449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    VolumeCollection::iterator i;
32549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
32649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
327a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (label[0] == '/') {
328a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getMountpoint()))
329a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
330a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
331a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getLabel()))
332a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
333a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
33449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
33549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    return NULL;
33649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
337