VolumeManager.cpp revision fff0b47998a722d57eea6a07350bbd7a6032b3cc
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)) {
223a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Mountpoint creation failed (%s)", strerror(errno));
224a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
225a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
226a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
227a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
228a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
229fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    if (Fat::doMount(loopDevice, mountPoint, false, false, ownerUid,
230fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat                     0, 0007, false)) {
231a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC FAT mount failed (%s)", strerror(errno));
232a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
233a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
234a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
235a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
236a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
237a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
238a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
239a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
240a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::finalizeAsec(const char *id) {
241a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
242a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
243a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
244a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
245a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(asecFileName, sizeof(asecFileName),
246a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             "/sdcard/android_secure/%s.asec", id);
247a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
248a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
249a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Unable to finalize %s (%s)", id, strerror(errno));
250a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
251a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
252a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
253a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
254fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    // XXX:
255fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    if (Fat::doMount(loopDevice, mountPoint, true, true, 0, 0, 0227, false)) {
256a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC finalize mount failed (%s)", strerror(errno));
257a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
258a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
259a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
260a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s finalized", id);
261a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
262a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
263a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
264a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::destroyAsec(const char *id) {
265a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
266a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
267a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
268a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(asecFileName, sizeof(asecFileName),
269a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             "/sdcard/android_secure/%s.asec", id);
270a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
271a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
272a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (isMountpointMounted(mountPoint)) {
273a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        int i, rc;
274a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        for (i = 0; i < 10; i++) {
275a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            rc = umount(mountPoint);
276a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            if (!rc) {
277a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                break;
278a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            }
279a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            if (rc && (errno == EINVAL || errno == ENOENT)) {
280a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                rc = 0;
281a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                break;
282a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            }
283a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            LOGW("ASEC %s unmount attempt %d failed (%s)",
284a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                  id, i +1, strerror(errno));
285a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            usleep(1000 * 250);
286a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
287a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (rc) {
288a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            LOGE("Failed to unmount ASEC %s for destroy", id);
289a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return -1;
290a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
291a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
292a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
293a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
294a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
295a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
296a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
297a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
298a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    unlink(asecFileName);
299a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
300a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s destroyed", id);
301a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
302a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
303a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
304a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
305a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
306a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
307a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
308a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(asecFileName, sizeof(asecFileName),
309a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             "/sdcard/android_secure/%s.asec", id);
310a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
311a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
312a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (isMountpointMounted(mountPoint)) {
313a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC %s already mounted", id);
314a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EBUSY;
315a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
316a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
317a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
318a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
319a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
320a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (Loop::getNextAvailable(loopDevice, sizeof(loopDevice))) {
321a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            LOGE("Unable to find loop device for ASEC mount");
322a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return -1;
323a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
324a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
325a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (Loop::create(loopDevice, asecFileName)) {
326a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            LOGE("ASEC loop device creation failed (%s)", strerror(errno));
327a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return -1;
328a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
329a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
330a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
331a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (mkdir(mountPoint, 0777)) {
332a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Mountpoint creation failed (%s)", strerror(errno));
333a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
334a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
335a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
336fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    if (Fat::doMount(loopDevice, mountPoint, true, false, ownerUid, 0,
337fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat                     0227, false)) {
338a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC mount failed (%s)", strerror(errno));
339a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
340a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
341a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
342a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s mounted", id);
343a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
344a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
345a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
34649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint VolumeManager::mountVolume(const char *label) {
34749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
34849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
34949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
35049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
35149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
35249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
35349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
354a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->mountVol();
355a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
356a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
357a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareAvailable(const char *method, bool *avail) {
358a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
359a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
360a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
361a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
362a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
363a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
364a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (mUsbMassStorageConnected)
365a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        *avail = true;
366a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else
367a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        *avail = false;
368a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
369a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
370a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
371a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::simulate(const char *cmd, const char *arg) {
372a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
373a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!strcmp(cmd, "ums")) {
374a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(arg, "connect")) {
375a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(true);
376a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else if (!strcmp(arg, "disconnect")) {
377a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(false);
378a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
379a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            errno = EINVAL;
380a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            return -1;
381a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
382a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
383a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
384a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
385a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
386a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
387a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
388a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
389a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareVolume(const char *label, const char *method) {
390a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
391a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
392a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
393a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
394a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
395a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
396a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
397a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    /*
398a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * Eventually, we'll want to support additional share back-ends,
399a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * some of which may work while the media is mounted. For now,
400a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * we just support UMS
401a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     */
402a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
403a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
404a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
405a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
406a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
407a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
408a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
409a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
410a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
411a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
41249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Idle) {
413a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // You need to unmount manually befoe sharing
41449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
41549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
41649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
41749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
418a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t d = v->getDiskDevice();
419a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
420a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // This volume does not support raw disk access
421a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
422a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
423a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
424a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
425a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
426a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
427a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
428a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
429a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
430a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
4310cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file",
4320cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat                   O_WRONLY)) < 0) {
433a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to open ums lunfile (%s)", strerror(errno));
434a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
435a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
436a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
437a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, nodepath, strlen(nodepath)) < 0) {
438a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
439a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
440a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
441a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
442a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
443a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
444a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeShared();
445a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
446a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
447a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
448a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::unshareVolume(const char *label, const char *method) {
449a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
450a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
451a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
452a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
453a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
454a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
455a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
456a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
457a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
458a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
459a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
460a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
461a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() != Volume::State_Shared) {
462a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
463a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
464a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
465a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
466a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t d = v->getDiskDevice();
467a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
468a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
469a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
470a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
471a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
472a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
473a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
4740cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file", O_WRONLY)) < 0) {
475a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to open ums lunfile (%s)", strerror(errno));
476a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
477a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
478a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
479a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char ch = 0;
480a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, &ch, 1) < 0) {
481a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
482a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
483a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
484a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
485a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
486a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
487a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeUnshared();
488a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
48949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
49049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
49149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint VolumeManager::unmountVolume(const char *label) {
49249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
49349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
49449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
49549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
49649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
49749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
49849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
499a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
500a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
501a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
502a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
503a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
50449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Mounted) {
505a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Attempt to unmount volume which isn't mounted (%d)\n",
506a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             v->getState());
50749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
50849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
50949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
51049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
511a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->unmountVol();
51249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
51349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
514a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat/*
515a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * Looks up a volume by it's label or mount-point
516a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat */
51749e2bce5b74129c26a35e25d4693cbfe98c4688eSan MehatVolume *VolumeManager::lookupVolume(const char *label) {
51849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    VolumeCollection::iterator i;
51949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
52049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
521a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (label[0] == '/') {
522a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getMountpoint()))
523a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
524a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
525a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getLabel()))
526a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
527a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
52849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
52949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    return NULL;
53049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
531a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
532a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatbool VolumeManager::isMountpointMounted(const char *mp)
533a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat{
534a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char device[256];
535a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mount_path[256];
536a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char rest[256];
537a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    FILE *fp;
538a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char line[1024];
539a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
540a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!(fp = fopen("/proc/mounts", "r"))) {
541a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Error opening /proc/mounts (%s)", strerror(errno));
542a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return false;
543a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
544a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
545a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    while(fgets(line, sizeof(line), fp)) {
546a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        line[strlen(line)-1] = '\0';
547a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
548a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (!strcmp(mount_path, mp)) {
549a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            fclose(fp);
550a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return true;
551a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
552a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
553a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
554a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
555a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    fclose(fp);
556a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return false;
557a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
558a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
559