VolumeManager.cpp revision 23969931fad6e993832208f099f6eea0f6f76eb5
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
4023969931fad6e993832208f099f6eea0f6f76eb5San Mehatextern "C" void KillProcessesWithOpenFiles(const char *, int, int, int);
4123969931fad6e993832208f099f6eea0f6f76eb5San Mehat
42f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::sInstance = NULL;
43f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
44f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::Instance() {
45f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!sInstance)
46f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        sInstance = new VolumeManager();
47f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return sInstance;
48f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
49f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
50f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::VolumeManager() {
51f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mBlockDevices = new BlockDeviceCollection();
52f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mVolumes = new VolumeCollection();
53f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mBroadcaster = NULL;
54a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mUsbMassStorageConnected = false;
55f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
56f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
57f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::~VolumeManager() {
58f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    delete mBlockDevices;
59f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
60f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
61f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::start() {
62f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
63f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
64f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
65f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::stop() {
66f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
67f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
68f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
69f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::addVolume(Volume *v) {
70f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mVolumes->push_back(v);
71f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
72f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
73f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
74a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid VolumeManager::notifyUmsConnected(bool connected) {
75a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char msg[255];
76a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
77a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (connected) {
78a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mUsbMassStorageConnected = true;
79a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
80a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mUsbMassStorageConnected = false;
81a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
82a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(msg, sizeof(msg), "Share method ums now %s",
83a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             (connected ? "available" : "unavailable"));
84a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
85a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    getBroadcaster()->sendBroadcast(ResponseCode::ShareAvailabilityChange,
86a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                    msg, false);
87a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
88a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
89a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid VolumeManager::handleSwitchEvent(NetlinkEvent *evt) {
900cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    const char *devpath = evt->findParam("DEVPATH");
91a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    const char *name = evt->findParam("SWITCH_NAME");
92a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    const char *state = evt->findParam("SWITCH_STATE");
93a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
940cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if (!name || !state) {
950cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat        LOGW("Switch %s event missing name/state info", devpath);
960cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat        return;
970cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    }
980cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat
99a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!strcmp(name, "usb_mass_storage")) {
100a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
101a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(state, "online"))  {
102a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(true);
103a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
104a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(false);
105a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
106a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
107a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Ignoring unknown switch '%s'", name);
108a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
109a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
110a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
111fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehatvoid VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
112fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    const char *devpath = evt->findParam("DEVPATH");
113f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
114fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    /* Lookup a volume to handle this device */
115f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator it;
116f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    bool hit = false;
117f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
118fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat        if (!(*it)->handleBlockEvent(evt)) {
119a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
120a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            LOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
121a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
122f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            hit = true;
123f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            break;
124f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        }
125f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
126f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
127f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!hit) {
128a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
129fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat        LOGW("No volumes handled block event for '%s'", devpath);
130a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
131f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
132f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
133f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
134f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::listVolumes(SocketClient *cli) {
135f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator i;
136f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
137f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
138f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        char *buffer;
139f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        asprintf(&buffer, "%s %s %d",
140f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getLabel(), (*i)->getMountpoint(),
141f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getState());
142a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
143f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        free(buffer);
144f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
145a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false);
146f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
147f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
14849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
149a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::formatVolume(const char *label) {
150a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
151a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
152a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
153a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
154a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
155a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
156a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
157a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->formatVol();
158a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
159a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
160a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
161a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
162a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
163a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
164a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
165a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!isMountpointMounted(mountPoint)) {
166a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = ENOENT;
167a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
168a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
169a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(buffer, maxlen, "/asec/%s", id);
170a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
171a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
172a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
173a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::createAsec(const char *id, int sizeMb,
174a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                              const char *fstype, const char *key, int ownerUid) {
175a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
176a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    mkdir("/sdcard/android_secure", 0777);
177a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
178a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (lookupVolume(id)) {
179a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC volume '%s' currently exists", id);
180a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EADDRINUSE;
181a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
182a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
183a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
184a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
185a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(asecFileName, sizeof(asecFileName),
186a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             "/sdcard/android_secure/%s.asec", id);
187a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
188a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!access(asecFileName, F_OK)) {
189a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
190a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             asecFileName, strerror(errno));
191a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EADDRINUSE;
192a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
193a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
194a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
195a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::createImageFile(asecFileName, sizeMb)) {
196a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC image file creation failed (%s)", strerror(errno));
197a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
198a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
199a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
200a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
201a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::getNextAvailable(loopDevice, sizeof(loopDevice))) {
202a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
203a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
204a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
205a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
206a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::create(loopDevice, asecFileName)) {
207a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC loop device creation failed (%s)", strerror(errno));
208a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
209a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
210a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
211a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
212a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    /* XXX: Start devmapper */
213a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
214a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Fat::format(loopDevice)) {
215a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC FAT format failed (%s)", strerror(errno));
216a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
217a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
218a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
219a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
220a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
221a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
222a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
223a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
224a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (mkdir(mountPoint, 0777)) {
225eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat        if (errno != EEXIST) {
226eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            LOGE("Mountpoint creation failed (%s)", strerror(errno));
227eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            Loop::destroyByDevice(loopDevice);
228eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            unlink(asecFileName);
229eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            return -1;
230eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat        }
231a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
232a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
233fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    if (Fat::doMount(loopDevice, mountPoint, false, false, ownerUid,
234cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat                     0, 0000, false)) {
235cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat//                     0, 0007, false)) {
236a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC FAT mount failed (%s)", strerror(errno));
237a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
238a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
239a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
240a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
241a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
242a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
243a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
244a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
245a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::finalizeAsec(const char *id) {
246a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
247a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
248a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
249a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
250a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(asecFileName, sizeof(asecFileName),
251a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             "/sdcard/android_secure/%s.asec", id);
252a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
253a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
254a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Unable to finalize %s (%s)", id, strerror(errno));
255a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
256a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
257a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
258a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
259fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    // XXX:
260fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    if (Fat::doMount(loopDevice, mountPoint, true, true, 0, 0, 0227, false)) {
261a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC finalize mount failed (%s)", strerror(errno));
262a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
263a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
264a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
265a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s finalized", id);
266a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
267a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
268a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
269a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::destroyAsec(const char *id) {
270a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
271a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
272a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
273a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(asecFileName, sizeof(asecFileName),
274a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             "/sdcard/android_secure/%s.asec", id);
275a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
276a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
277a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (isMountpointMounted(mountPoint)) {
278a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        int i, rc;
279a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        for (i = 0; i < 10; i++) {
280a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            rc = umount(mountPoint);
281a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            if (!rc) {
282a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                break;
283a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            }
284a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            if (rc && (errno == EINVAL || errno == ENOENT)) {
285a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                rc = 0;
286a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                break;
287a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            }
288a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            LOGW("ASEC %s unmount attempt %d failed (%s)",
289a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                  id, i +1, strerror(errno));
29023969931fad6e993832208f099f6eea0f6f76eb5San Mehat
29123969931fad6e993832208f099f6eea0f6f76eb5San Mehat            if (i >= 5) {
29223969931fad6e993832208f099f6eea0f6f76eb5San Mehat                KillProcessesWithOpenFiles(mountPoint, (i < 7 ? 0 : 1),
29323969931fad6e993832208f099f6eea0f6f76eb5San Mehat                                           NULL, 0);
29423969931fad6e993832208f099f6eea0f6f76eb5San Mehat            }
295a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            usleep(1000 * 250);
296a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
297a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (rc) {
298a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            LOGE("Failed to unmount ASEC %s for destroy", id);
299a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return -1;
300a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
301a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
302a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
303a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
304a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
305a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
306a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
307a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
308a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    unlink(asecFileName);
309a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
310a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s destroyed", id);
311a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
312a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
313a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
314a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
315a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
316a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
317a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
318a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(asecFileName, sizeof(asecFileName),
319a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             "/sdcard/android_secure/%s.asec", id);
320a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
321a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
322a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (isMountpointMounted(mountPoint)) {
323a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC %s already mounted", id);
324a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EBUSY;
325a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
326a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
327a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
328a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
329a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
330a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (Loop::getNextAvailable(loopDevice, sizeof(loopDevice))) {
331a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            LOGE("Unable to find loop device for ASEC mount");
332a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return -1;
333a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
334a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
335a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (Loop::create(loopDevice, asecFileName)) {
336a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            LOGE("ASEC loop device creation failed (%s)", strerror(errno));
337a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return -1;
338a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
339a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
340a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
341a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (mkdir(mountPoint, 0777)) {
342a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Mountpoint creation failed (%s)", strerror(errno));
343a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
344a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
345a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
346fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    if (Fat::doMount(loopDevice, mountPoint, true, false, ownerUid, 0,
347cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat                     0222, false)) {
348cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat//                     0227, false)) {
349a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC mount failed (%s)", strerror(errno));
350a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
351a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
352a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
353a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s mounted", id);
354a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
355a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
356a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
35749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint VolumeManager::mountVolume(const char *label) {
35849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
35949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
36049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
36149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
36249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
36349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
36449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
365a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->mountVol();
366a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
367a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
368a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareAvailable(const char *method, bool *avail) {
369a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
370a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
371a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
372a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
373a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
374a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
375a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (mUsbMassStorageConnected)
376a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        *avail = true;
377a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else
378a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        *avail = false;
379a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
380a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
381a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
382a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::simulate(const char *cmd, const char *arg) {
383a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
384a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!strcmp(cmd, "ums")) {
385a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(arg, "connect")) {
386a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(true);
387a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else if (!strcmp(arg, "disconnect")) {
388a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(false);
389a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
390a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            errno = EINVAL;
391a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            return -1;
392a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
393a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
394a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
395a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
396a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
397a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
398a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
399a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
400a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareVolume(const char *label, const char *method) {
401a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
402a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
403a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
404a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
405a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
406a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
407a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
408a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    /*
409a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * Eventually, we'll want to support additional share back-ends,
410a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * some of which may work while the media is mounted. For now,
411a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * we just support UMS
412a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     */
413a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
414a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
415a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
416a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
417a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
418a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
419a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
420a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
421a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
422a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
42349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Idle) {
424a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // You need to unmount manually befoe sharing
42549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
42649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
42749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
42849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
429a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t d = v->getDiskDevice();
430a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
431a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // This volume does not support raw disk access
432a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
433a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
434a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
435a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
436a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
437a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
438a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
439a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
440a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
441a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
4420cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file",
4430cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat                   O_WRONLY)) < 0) {
444a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to open ums lunfile (%s)", strerror(errno));
445a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
446a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
447a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
448a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, nodepath, strlen(nodepath)) < 0) {
449a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
450a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
451a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
452a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
453a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
454a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
455a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeShared();
456a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
457a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
458a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
459a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::unshareVolume(const char *label, const char *method) {
460a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
461a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
462a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
463a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
464a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
465a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
466a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
467a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
468a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
469a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
470a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
471a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
472a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() != Volume::State_Shared) {
473a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
474a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
475a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
476a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
477a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t d = v->getDiskDevice();
478a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
479a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
480a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
481a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
482a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
483a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
484a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
4850cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file", O_WRONLY)) < 0) {
486a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to open ums lunfile (%s)", strerror(errno));
487a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
488a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
489a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
490a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char ch = 0;
491a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, &ch, 1) < 0) {
492a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
493a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
494a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
495a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
496a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
497a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
498a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeUnshared();
499a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
50049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
50149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
50249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint VolumeManager::unmountVolume(const char *label) {
50349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
50449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
50549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
50649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
50749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
50849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
50949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
510a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
511a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
512a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
513a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
514a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
51549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Mounted) {
516a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Attempt to unmount volume which isn't mounted (%d)\n",
517a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             v->getState());
51849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
51949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
52049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
52149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
522a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->unmountVol();
52349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
52449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
525a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat/*
526a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * Looks up a volume by it's label or mount-point
527a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat */
52849e2bce5b74129c26a35e25d4693cbfe98c4688eSan MehatVolume *VolumeManager::lookupVolume(const char *label) {
52949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    VolumeCollection::iterator i;
53049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
53149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
532a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (label[0] == '/') {
533a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getMountpoint()))
534a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
535a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
536a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getLabel()))
537a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
538a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
53949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
54049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    return NULL;
54149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
542a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
543a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatbool VolumeManager::isMountpointMounted(const char *mp)
544a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat{
545a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char device[256];
546a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mount_path[256];
547a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char rest[256];
548a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    FILE *fp;
549a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char line[1024];
550a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
551a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!(fp = fopen("/proc/mounts", "r"))) {
552a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Error opening /proc/mounts (%s)", strerror(errno));
553a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return false;
554a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
555a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
556a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    while(fgets(line, sizeof(line), fp)) {
557a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        line[strlen(line)-1] = '\0';
558a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
559a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (!strcmp(mount_path, mp)) {
560a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            fclose(fp);
561a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return true;
562a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
563a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
564a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
565a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
566a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    fclose(fp);
567a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return false;
568a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
569a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
570