VolumeManager.cpp revision 0586d54053ee00e6d6523d4f125282ccb9a24aab
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"
39b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include "Devmapper.h"
40f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
4123969931fad6e993832208f099f6eea0f6f76eb5San Mehatextern "C" void KillProcessesWithOpenFiles(const char *, int, int, int);
4223969931fad6e993832208f099f6eea0f6f76eb5San Mehat
43f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::sInstance = NULL;
44f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
45f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::Instance() {
46f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!sInstance)
47f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        sInstance = new VolumeManager();
48f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return sInstance;
49f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
50f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
51f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::VolumeManager() {
52f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mBlockDevices = new BlockDeviceCollection();
53f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mVolumes = new VolumeCollection();
54f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mBroadcaster = NULL;
55a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mUsbMassStorageConnected = false;
56f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
57f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
58f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::~VolumeManager() {
59f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    delete mBlockDevices;
60f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
61f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
62f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::start() {
63f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
64f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
65f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
66f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::stop() {
67f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
68f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
69f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
70f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::addVolume(Volume *v) {
71f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mVolumes->push_back(v);
72f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
73f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
74f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
75a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid VolumeManager::notifyUmsConnected(bool connected) {
76a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char msg[255];
77a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
78a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (connected) {
79a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mUsbMassStorageConnected = true;
80a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
81a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mUsbMassStorageConnected = false;
82a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
83a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(msg, sizeof(msg), "Share method ums now %s",
84a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             (connected ? "available" : "unavailable"));
85a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
86a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    getBroadcaster()->sendBroadcast(ResponseCode::ShareAvailabilityChange,
87a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                    msg, false);
88a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
89a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
90a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid VolumeManager::handleSwitchEvent(NetlinkEvent *evt) {
910cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    const char *devpath = evt->findParam("DEVPATH");
92a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    const char *name = evt->findParam("SWITCH_NAME");
93a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    const char *state = evt->findParam("SWITCH_STATE");
94a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
950cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if (!name || !state) {
960cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat        LOGW("Switch %s event missing name/state info", devpath);
970cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat        return;
980cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    }
990cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat
100a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!strcmp(name, "usb_mass_storage")) {
101a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
102a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(state, "online"))  {
103a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(true);
104a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
105a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(false);
106a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
107a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
108a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Ignoring unknown switch '%s'", name);
109a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
110a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
111a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
112fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehatvoid VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
113fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    const char *devpath = evt->findParam("DEVPATH");
114f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
115fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    /* Lookup a volume to handle this device */
116f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator it;
117f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    bool hit = false;
118f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
119fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat        if (!(*it)->handleBlockEvent(evt)) {
120a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
121a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            LOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
122a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
123f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            hit = true;
124f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            break;
125f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        }
126f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
127f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
128f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!hit) {
129a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
130fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat        LOGW("No volumes handled block event for '%s'", devpath);
131a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
132f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
133f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
134f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
135f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::listVolumes(SocketClient *cli) {
136f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator i;
137f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
138f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
139f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        char *buffer;
140f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        asprintf(&buffer, "%s %s %d",
141f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getLabel(), (*i)->getMountpoint(),
142f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getState());
143a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
144f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        free(buffer);
145f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
146a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false);
147f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
148f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
14949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
150a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::formatVolume(const char *label) {
151a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
152a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
153a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
154a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
155a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
156a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
157a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
158a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->formatVol();
159a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
160a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
161a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
162a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
163a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
164a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
165a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
166a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!isMountpointMounted(mountPoint)) {
167a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = ENOENT;
168a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
169a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
170a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(buffer, maxlen, "/asec/%s", id);
171a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
172a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
173a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1748b8f71b1d760411279f3b07a5c97709f052c689eSan Mehatint VolumeManager::createAsec(const char *id, unsigned int numSectors,
175a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                              const char *fstype, const char *key, int ownerUid) {
176a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
177a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    mkdir("/sdcard/android_secure", 0777);
178a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
179a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (lookupVolume(id)) {
180a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC volume '%s' currently exists", id);
181a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EADDRINUSE;
182a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
183a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
184a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
185a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
186a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(asecFileName, sizeof(asecFileName),
187a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             "/sdcard/android_secure/%s.asec", id);
188a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
189a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!access(asecFileName, F_OK)) {
190a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
191a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             asecFileName, strerror(errno));
192a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EADDRINUSE;
193a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
194a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
195a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1968b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat    if (Loop::createImageFile(asecFileName, numSectors)) {
197a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC image file creation failed (%s)", strerror(errno));
198a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
199a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
200a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
201a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
2028da6bcb006f4e4257cdd685e35e910a6334f6ceaSan Mehat    if (Loop::create(asecFileName, loopDevice, sizeof(loopDevice))) {
203a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC loop device creation failed (%s)", strerror(errno));
204a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
205a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
206a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
207a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
208b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char dmDevice[255];
209b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    bool cleanupDm = false;
210a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
211b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (strcmp(key, "none")) {
2128b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat        if (Devmapper::create(id, loopDevice, key, numSectors, dmDevice,
213b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                             sizeof(dmDevice))) {
214b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            LOGE("ASEC device mapping failed (%s)", strerror(errno));
215b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Loop::destroyByDevice(loopDevice);
216b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            unlink(asecFileName);
217b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            return -1;
218b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
219b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        cleanupDm = true;
220b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
221b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        strcpy(dmDevice, loopDevice);
222b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
223b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
224b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (Fat::format(dmDevice)) {
225a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC FAT format failed (%s)", strerror(errno));
226b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (cleanupDm) {
227b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Devmapper::destroy(id);
228b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
229a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
230a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
231a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
232a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
233a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
234a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
235a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
236a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
237a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (mkdir(mountPoint, 0777)) {
238eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat        if (errno != EEXIST) {
239eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            LOGE("Mountpoint creation failed (%s)", strerror(errno));
240b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if (cleanupDm) {
241b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                Devmapper::destroy(id);
242b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
243eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            Loop::destroyByDevice(loopDevice);
244eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            unlink(asecFileName);
245eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            return -1;
246eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat        }
247a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
248a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
249b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (Fat::doMount(dmDevice, mountPoint, false, false, ownerUid,
250cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat                     0, 0000, false)) {
251cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat//                     0, 0007, false)) {
252a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC FAT mount failed (%s)", strerror(errno));
253b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (cleanupDm) {
254b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Devmapper::destroy(id);
255b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
256a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
257a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
258a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
259a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
260a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
261a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
262a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
263a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
264a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::finalizeAsec(const char *id) {
265a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
266a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
267a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
268a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
269a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(asecFileName, sizeof(asecFileName),
270a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             "/sdcard/android_secure/%s.asec", id);
271a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
272a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
273a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Unable to finalize %s (%s)", id, strerror(errno));
274a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
275a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
276a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
277a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
278fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    // XXX:
279fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    if (Fat::doMount(loopDevice, mountPoint, true, true, 0, 0, 0227, false)) {
280a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC finalize mount failed (%s)", strerror(errno));
281a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
282a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
283a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
284a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s finalized", id);
285a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
286a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
287a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
288b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatint VolumeManager::unmountAsec(const char *id) {
289a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
290a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
291a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
292a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(asecFileName, sizeof(asecFileName),
293a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             "/sdcard/android_secure/%s.asec", id);
294a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
295a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
2960586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (!isMountpointMounted(mountPoint)) {
297b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGE("Unmount request for ASEC %s when not mounted", id);
298b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        errno = EINVAL;
299b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
300b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
30123969931fad6e993832208f099f6eea0f6f76eb5San Mehat
302b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    int i, rc;
303b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    for (i = 0; i < 10; i++) {
304b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        rc = umount(mountPoint);
305b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (!rc) {
306b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            break;
307a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
308b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (rc && (errno == EINVAL || errno == ENOENT)) {
309b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            rc = 0;
310b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            break;
311a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
312b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGW("ASEC %s unmount attempt %d failed (%s)",
313b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat              id, i +1, strerror(errno));
314b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
315b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (i >= 5) {
316b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            KillProcessesWithOpenFiles(mountPoint, (i < 7 ? 0 : 1),
317b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                                       NULL, 0);
318b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
319b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        usleep(1000 * 250);
320b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
321b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
322b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (rc) {
323b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGE("Failed to unmount ASEC %s", id);
324b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
325b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
326b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
327b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (Devmapper::destroy(id) && errno != ENXIO) {
328b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
329a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
330a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
331a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
332a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
333a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
334a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
335b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    return 0;
336b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat}
337b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
338b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehatint VolumeManager::destroyAsec(const char *id) {
339b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char asecFileName[255];
340b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char mountPoint[255];
341b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
342b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    snprintf(asecFileName, sizeof(asecFileName),
343b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat             "/sdcard/android_secure/%s.asec", id);
344b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
345b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
3460586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (isMountpointMounted(mountPoint)) {
3470586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        if (unmountAsec(id)) {
3480586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat            LOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
3490586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat            return -1;
3500586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        }
3510586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    }
352a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
3530586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (unlink(asecFileName)) {
3540586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        LOGE("Failed to unlink asec %s (%s)", id, strerror(errno));
3550586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        return -1;
3560586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    }
357a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
358a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s destroyed", id);
359a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
360a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
361a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
362a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
363a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
364a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
365a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
366a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(asecFileName, sizeof(asecFileName),
367a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             "/sdcard/android_secure/%s.asec", id);
368a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    snprintf(mountPoint, sizeof(mountPoint), "/asec/%s", id);
369a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
370a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (isMountpointMounted(mountPoint)) {
371a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC %s already mounted", id);
372a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EBUSY;
373a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
374a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
375a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
376a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
377a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
3788da6bcb006f4e4257cdd685e35e910a6334f6ceaSan Mehat        if (Loop::create(asecFileName, loopDevice, sizeof(loopDevice))) {
379a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            LOGE("ASEC loop device creation failed (%s)", strerror(errno));
380a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return -1;
381a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
382b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGD("New loop device created at %s", loopDevice);
383b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
384b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGD("Found active loopback for %s at %s", asecFileName, loopDevice);
385b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
386b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
387b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char dmDevice[255];
388b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    bool cleanupDm = false;
389b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (strcmp(key, "none")) {
390b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (Devmapper::lookupActive(id, dmDevice, sizeof(dmDevice))) {
391b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            unsigned int nr_sec = 0;
392b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            int fd;
393b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
394b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if ((fd = open(loopDevice, O_RDWR)) < 0) {
395b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                LOGE("Failed to open loopdevice (%s)", strerror(errno));
396b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                Loop::destroyByDevice(loopDevice);
397b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                return -1;
398b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
399b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
400b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
401b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                LOGE("Failed to get loop size (%s)", strerror(errno));
402b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                Loop::destroyByDevice(loopDevice);
403b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                close(fd);
404b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                return -1;
405b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
406b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            close(fd);
4078b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat            if (Devmapper::create(id, loopDevice, key, nr_sec,
408b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                                  dmDevice, sizeof(dmDevice))) {
409b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                LOGE("ASEC device mapping failed (%s)", strerror(errno));
410b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                Loop::destroyByDevice(loopDevice);
411b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                return -1;
412b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
413b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            LOGD("New devmapper instance created at %s", dmDevice);
414b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        } else {
415b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            LOGD("Found active devmapper for %s at %s", asecFileName, dmDevice);
416b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
417b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        cleanupDm = true;
418b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
419b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        strcpy(dmDevice, loopDevice);
420a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
421a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
422a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (mkdir(mountPoint, 0777)) {
423b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (errno != EEXIST) {
424b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            LOGE("Mountpoint creation failed (%s)", strerror(errno));
425b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if (cleanupDm) {
426b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                Devmapper::destroy(id);
427b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
428b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Loop::destroyByDevice(loopDevice);
429b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            return -1;
430b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
431a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
432a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
433b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (Fat::doMount(dmDevice, mountPoint, true, false, ownerUid, 0,
434cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat                     0222, false)) {
435cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat//                     0227, false)) {
436a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC mount failed (%s)", strerror(errno));
437b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (cleanupDm) {
438b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Devmapper::destroy(id);
439b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
440b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        Loop::destroyByDevice(loopDevice);
441a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
442a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
443a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
444a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s mounted", id);
445a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
446a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
447a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
44849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint VolumeManager::mountVolume(const char *label) {
44949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
45049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
45149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
45249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
45349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
45449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
45549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
456a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->mountVol();
457a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
458a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
459a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareAvailable(const char *method, bool *avail) {
460a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
461a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
462a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
463a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
464a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
465a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
466a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (mUsbMassStorageConnected)
467a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        *avail = true;
468a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else
469a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        *avail = false;
470a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
471a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
472a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
473a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::simulate(const char *cmd, const char *arg) {
474a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
475a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!strcmp(cmd, "ums")) {
476a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(arg, "connect")) {
477a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(true);
478a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else if (!strcmp(arg, "disconnect")) {
479a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(false);
480a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
481a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            errno = EINVAL;
482a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            return -1;
483a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
484a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
485a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
486a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
487a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
488a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
489a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
490a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
491a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareVolume(const char *label, const char *method) {
492a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
493a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
494a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
495a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
496a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
497a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
498a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
499a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    /*
500a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * Eventually, we'll want to support additional share back-ends,
501a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * some of which may work while the media is mounted. For now,
502a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * we just support UMS
503a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     */
504a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
505a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
506a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
507a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
508a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
509a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
510a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
511a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
512a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
513a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
51449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Idle) {
515a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // You need to unmount manually befoe sharing
51649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
51749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
51849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
51949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
520a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t d = v->getDiskDevice();
521a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
522a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // This volume does not support raw disk access
523a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
524a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
525a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
526a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
527a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
528a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
529a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
530a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
531a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
532a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
5330cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file",
5340cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat                   O_WRONLY)) < 0) {
535a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to open ums lunfile (%s)", strerror(errno));
536a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
537a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
538a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
539a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, nodepath, strlen(nodepath)) < 0) {
540a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
541a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
542a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
543a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
544a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
545a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
546a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeShared();
547a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
548a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
549a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
550a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::unshareVolume(const char *label, const char *method) {
551a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
552a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
553a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
554a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
555a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
556a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
557a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
558a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
559a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
560a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
561a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
562a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
563a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() != Volume::State_Shared) {
564a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
565a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
566a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
567a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
568a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t d = v->getDiskDevice();
569a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
570a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
571a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
572a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
573a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
574a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
575a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
5760cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file", O_WRONLY)) < 0) {
577a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to open ums lunfile (%s)", strerror(errno));
578a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
579a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
580a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
581a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char ch = 0;
582a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, &ch, 1) < 0) {
583a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
584a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
585a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
586a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
587a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
588a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
589a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeUnshared();
590a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
59149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
59249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
59349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint VolumeManager::unmountVolume(const char *label) {
59449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
59549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
59649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
59749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
59849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
59949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
60049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
601a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
602a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
603a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
604a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
605a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
60649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Mounted) {
607a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Attempt to unmount volume which isn't mounted (%d)\n",
608a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             v->getState());
60949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
61049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
61149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
61249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
613a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->unmountVol();
61449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
61549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
616a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat/*
617a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * Looks up a volume by it's label or mount-point
618a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat */
61949e2bce5b74129c26a35e25d4693cbfe98c4688eSan MehatVolume *VolumeManager::lookupVolume(const char *label) {
62049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    VolumeCollection::iterator i;
62149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
62249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
623a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (label[0] == '/') {
624a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getMountpoint()))
625a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
626a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
627a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getLabel()))
628a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
629a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
63049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
63149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    return NULL;
63249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
633a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
634a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatbool VolumeManager::isMountpointMounted(const char *mp)
635a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat{
636a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char device[256];
637a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mount_path[256];
638a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char rest[256];
639a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    FILE *fp;
640a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char line[1024];
641a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
642a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!(fp = fopen("/proc/mounts", "r"))) {
643a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Error opening /proc/mounts (%s)", strerror(errno));
644a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return false;
645a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
646a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
647a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    while(fgets(line, sizeof(line), fp)) {
648a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        line[strlen(line)-1] = '\0';
649a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
650a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (!strcmp(mount_path, mp)) {
651a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            fclose(fp);
652a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return true;
653a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
654a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
655a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
656a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
657a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    fclose(fp);
658a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return false;
659a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
660a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
661