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