VolumeManager.cpp revision 96956ed0e220cb62a4a96136976ded0d8c2d9075
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"
40586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include "Process.h"
4123969931fad6e993832208f099f6eea0f6f76eb5San Mehat
42f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::sInstance = NULL;
43f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
44f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::Instance() {
45f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!sInstance)
46f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        sInstance = new VolumeManager();
47f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return sInstance;
48f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
49f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
50f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::VolumeManager() {
51f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mBlockDevices = new BlockDeviceCollection();
52f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mVolumes = new VolumeCollection();
5388705166ab82057090a070c6d4200c3d9db76f11San Mehat    mActiveContainers = new AsecIdCollection();
54f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mBroadcaster = NULL;
55a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mUsbMassStorageConnected = false;
56f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
57f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
58f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::~VolumeManager() {
59f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    delete mBlockDevices;
6088705166ab82057090a070c6d4200c3d9db76f11San Mehat    delete mVolumes;
6188705166ab82057090a070c6d4200c3d9db76f11San Mehat    delete mActiveContainers;
62f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
63f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
64f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::start() {
65f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
66f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
67f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
68f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::stop() {
69f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
70f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
71f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
72f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::addVolume(Volume *v) {
73f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mVolumes->push_back(v);
74f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
75f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
76f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
77a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid VolumeManager::notifyUmsConnected(bool connected) {
78a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char msg[255];
79a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
80a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (connected) {
81a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mUsbMassStorageConnected = true;
82a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
83a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mUsbMassStorageConnected = false;
84a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
85a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(msg, sizeof(msg), "Share method ums now %s",
86a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             (connected ? "available" : "unavailable"));
87a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
88a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    getBroadcaster()->sendBroadcast(ResponseCode::ShareAvailabilityChange,
89a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                    msg, false);
90a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
91a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
92a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid VolumeManager::handleSwitchEvent(NetlinkEvent *evt) {
930cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    const char *devpath = evt->findParam("DEVPATH");
94a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    const char *name = evt->findParam("SWITCH_NAME");
95a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    const char *state = evt->findParam("SWITCH_STATE");
96a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
970cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if (!name || !state) {
980cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat        LOGW("Switch %s event missing name/state info", devpath);
990cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat        return;
1000cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    }
1010cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat
102a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!strcmp(name, "usb_mass_storage")) {
103a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
104a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(state, "online"))  {
105a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(true);
106a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
107a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(false);
108a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
109a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
110a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Ignoring unknown switch '%s'", name);
111a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
112a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
113a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
114fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehatvoid VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
115fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    const char *devpath = evt->findParam("DEVPATH");
116f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
117fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    /* Lookup a volume to handle this device */
118f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator it;
119f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    bool hit = false;
120f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
121fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat        if (!(*it)->handleBlockEvent(evt)) {
122a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
123a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            LOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
124a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
125f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            hit = true;
126f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            break;
127f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        }
128f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
129f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
130f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!hit) {
131a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
132fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat        LOGW("No volumes handled block event for '%s'", devpath);
133a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
134f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
135f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
136f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
137f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::listVolumes(SocketClient *cli) {
138f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator i;
139f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
140f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
141f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        char *buffer;
142f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        asprintf(&buffer, "%s %s %d",
143f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getLabel(), (*i)->getMountpoint(),
144f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getState());
145a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
146f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        free(buffer);
147f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
148a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false);
149f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
150f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
15149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
152a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::formatVolume(const char *label) {
153a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
154a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
155a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
156a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
157a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
158a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
159a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
160a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->formatVol();
161a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
162a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
163a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
164a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1653bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(buffer, maxlen, "%s/%s", Volume::ASECDIR, id);
166a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
167a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
168a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1698b8f71b1d760411279f3b07a5c97709f052c689eSan Mehatint VolumeManager::createAsec(const char *id, unsigned int numSectors,
170a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                              const char *fstype, const char *key, int ownerUid) {
171a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
172d31e380bd9689dd9629b510ffe324707e261b439San Mehat    if (numSectors < ((1024*1024)/512)) {
173d31e380bd9689dd9629b510ffe324707e261b439San Mehat        LOGE("Invalid container size specified (%d sectors)", numSectors);
174d31e380bd9689dd9629b510ffe324707e261b439San Mehat        errno = EINVAL;
175d31e380bd9689dd9629b510ffe324707e261b439San Mehat        return -1;
176d31e380bd9689dd9629b510ffe324707e261b439San Mehat    }
177d31e380bd9689dd9629b510ffe324707e261b439San Mehat
178a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (lookupVolume(id)) {
1793bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        LOGE("ASEC id '%s' currently exists", id);
180a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EADDRINUSE;
181a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
182a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
183a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
184a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
1853bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
186a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
187a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!access(asecFileName, F_OK)) {
188a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
189a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             asecFileName, strerror(errno));
190a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EADDRINUSE;
191a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
192a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
193a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1948b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat    if (Loop::createImageFile(asecFileName, numSectors)) {
195a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC image file creation failed (%s)", strerror(errno));
196a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
197a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
198a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
199a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
2008da6bcb006f4e4257cdd685e35e910a6334f6ceaSan Mehat    if (Loop::create(asecFileName, loopDevice, sizeof(loopDevice))) {
201a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC loop device creation failed (%s)", strerror(errno));
202a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
203a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
204a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
205a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
206b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char dmDevice[255];
207b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    bool cleanupDm = false;
208a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
209b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (strcmp(key, "none")) {
2108b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat        if (Devmapper::create(id, loopDevice, key, numSectors, dmDevice,
211b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                             sizeof(dmDevice))) {
212b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            LOGE("ASEC device mapping failed (%s)", strerror(errno));
213b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Loop::destroyByDevice(loopDevice);
214b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            unlink(asecFileName);
215b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            return -1;
216b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
217b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        cleanupDm = true;
218b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
219b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        strcpy(dmDevice, loopDevice);
220b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
221b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
222b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (Fat::format(dmDevice)) {
223a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC FAT format failed (%s)", strerror(errno));
224b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (cleanupDm) {
225b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Devmapper::destroy(id);
226b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
227a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
228a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
229a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
230a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
231a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
232a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
233a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
2343bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
235a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (mkdir(mountPoint, 0777)) {
236eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat        if (errno != EEXIST) {
237eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            LOGE("Mountpoint creation failed (%s)", strerror(errno));
238b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if (cleanupDm) {
239b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                Devmapper::destroy(id);
240b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
241eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            Loop::destroyByDevice(loopDevice);
242eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            unlink(asecFileName);
243eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            return -1;
244eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat        }
245a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
246a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
247b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (Fat::doMount(dmDevice, mountPoint, false, false, ownerUid,
248cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat                     0, 0000, false)) {
249cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat//                     0, 0007, false)) {
250a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC FAT mount failed (%s)", strerror(errno));
251b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (cleanupDm) {
252b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Devmapper::destroy(id);
253b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
254a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
255a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
256a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
257a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
25888705166ab82057090a070c6d4200c3d9db76f11San Mehat
25988705166ab82057090a070c6d4200c3d9db76f11San Mehat    mActiveContainers->push_back(strdup(id));
260a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
261a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
262a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
263a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::finalizeAsec(const char *id) {
264a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
265a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
266a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
267a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
2683bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
269a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
270a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
271a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Unable to finalize %s (%s)", id, strerror(errno));
272a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
273a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
274a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
2753bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
276fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    // XXX:
277fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    if (Fat::doMount(loopDevice, mountPoint, true, true, 0, 0, 0227, false)) {
278a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC finalize mount failed (%s)", strerror(errno));
279a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
280a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
281a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
282a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s finalized", id);
283a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
284a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
285a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
286048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehatint VolumeManager::renameAsec(const char *id1, const char *id2) {
287048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    char *asecFilename1;
288048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    char *asecFilename2;
289048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    char mountPoint[255];
290048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
2913bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    asprintf(&asecFilename1, "%s/%s.asec", Volume::SEC_ASECDIR, id1);
2923bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    asprintf(&asecFilename2, "%s/%s.asec", Volume::SEC_ASECDIR, id2);
293048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
2943bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id1);
295048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    if (isMountpointMounted(mountPoint)) {
296048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        LOGW("Rename attempt when src mounted");
297048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        errno = EBUSY;
298048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        goto out_err;
299048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
300048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
30196956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id2);
30296956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat    if (isMountpointMounted(mountPoint)) {
30396956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat        LOGW("Rename attempt when dst mounted");
30496956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat        errno = EBUSY;
30596956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat        goto out_err;
30696956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat    }
30796956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat
308048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    if (!access(asecFilename2, F_OK)) {
309048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        LOGE("Rename attempt when dst exists");
310048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        errno = EADDRINUSE;
311048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        goto out_err;
312048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
313048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
314048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    if (rename(asecFilename1, asecFilename2)) {
315048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        LOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno));
316048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        goto out_err;
317048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
318048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
319048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename1);
320048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename2);
321048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    return 0;
322048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
323048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehatout_err:
324048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename1);
325048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename2);
326048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    return -1;
327048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat}
328048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
3294ba8948dc16463053e21cda5744f519a555080d0San Mehat#define ASEC_UNMOUNT_RETRIES 5
3304ba8948dc16463053e21cda5744f519a555080d0San Mehatint VolumeManager::unmountAsec(const char *id, bool force) {
331a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
332a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
333a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
3343bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
3353bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
336a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
3370586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (!isMountpointMounted(mountPoint)) {
338b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGE("Unmount request for ASEC %s when not mounted", id);
339b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        errno = EINVAL;
340b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
341b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
34223969931fad6e993832208f099f6eea0f6f76eb5San Mehat
343b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    int i, rc;
3448c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat    for (i = 1; i <= ASEC_UNMOUNT_RETRIES; i++) {
345b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        rc = umount(mountPoint);
346b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (!rc) {
347b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            break;
348a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
349b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (rc && (errno == EINVAL || errno == ENOENT)) {
350b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            rc = 0;
351b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            break;
352a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
353b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGW("ASEC %s unmount attempt %d failed (%s)",
3548c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat              id, i, strerror(errno));
3558c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
3564ba8948dc16463053e21cda5744f519a555080d0San Mehat        int action = 0; // default is to just complain
3574ba8948dc16463053e21cda5744f519a555080d0San Mehat
3584ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (force) {
3594ba8948dc16463053e21cda5744f519a555080d0San Mehat            if (i > (ASEC_UNMOUNT_RETRIES - 2))
3604ba8948dc16463053e21cda5744f519a555080d0San Mehat                action = 2; // SIGKILL
3614ba8948dc16463053e21cda5744f519a555080d0San Mehat            else if (i > (ASEC_UNMOUNT_RETRIES - 3))
3624ba8948dc16463053e21cda5744f519a555080d0San Mehat                action = 1; // SIGHUP
3634ba8948dc16463053e21cda5744f519a555080d0San Mehat        }
3648c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
365586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        Process::killProcessesWithOpenFiles(mountPoint, action);
3668c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat        usleep(1000 * 1000);
367b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
368b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
369b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (rc) {
3704ba8948dc16463053e21cda5744f519a555080d0San Mehat        errno = EBUSY;
3714ba8948dc16463053e21cda5744f519a555080d0San Mehat        LOGE("Failed to unmount container %s (%s)", id, strerror(errno));
372b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
373b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
374b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
375f5c61980969a0b49bda37b5dc94ffe675ebd5a5aSan Mehat    if (rmdir(mountPoint)) {
376f5c61980969a0b49bda37b5dc94ffe675ebd5a5aSan Mehat        LOGE("Failed to rmdir mountpoint (%s)", strerror(errno));
377f5c61980969a0b49bda37b5dc94ffe675ebd5a5aSan Mehat    }
37888705166ab82057090a070c6d4200c3d9db76f11San Mehat
379b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (Devmapper::destroy(id) && errno != ENXIO) {
380b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
381a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
382a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
383a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
384a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
385a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
386a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
38788705166ab82057090a070c6d4200c3d9db76f11San Mehat
38888705166ab82057090a070c6d4200c3d9db76f11San Mehat    AsecIdCollection::iterator it;
38988705166ab82057090a070c6d4200c3d9db76f11San Mehat    for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) {
39088705166ab82057090a070c6d4200c3d9db76f11San Mehat        if (!strcmp(*it, id)) {
39188705166ab82057090a070c6d4200c3d9db76f11San Mehat            free(*it);
39288705166ab82057090a070c6d4200c3d9db76f11San Mehat            mActiveContainers->erase(it);
39388705166ab82057090a070c6d4200c3d9db76f11San Mehat            break;
39488705166ab82057090a070c6d4200c3d9db76f11San Mehat        }
39588705166ab82057090a070c6d4200c3d9db76f11San Mehat    }
39688705166ab82057090a070c6d4200c3d9db76f11San Mehat    if (it == mActiveContainers->end()) {
39788705166ab82057090a070c6d4200c3d9db76f11San Mehat        LOGW("mActiveContainers is inconsistent!");
39888705166ab82057090a070c6d4200c3d9db76f11San Mehat    }
399b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    return 0;
400b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat}
401b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
4024ba8948dc16463053e21cda5744f519a555080d0San Mehatint VolumeManager::destroyAsec(const char *id, bool force) {
403b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char asecFileName[255];
404b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char mountPoint[255];
405b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
4063bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
407b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
4080586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (isMountpointMounted(mountPoint)) {
40968f8ebdb24dfe1fe94de2c8fc11084ebfab9fa5dSan Mehat        LOGD("Unmounting container before destroy");
4104ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (unmountAsec(id, force)) {
4110586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat            LOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
4120586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat            return -1;
4130586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        }
4140586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    }
415a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
4160586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (unlink(asecFileName)) {
41768f8ebdb24dfe1fe94de2c8fc11084ebfab9fa5dSan Mehat        LOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno));
4180586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        return -1;
4190586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    }
420a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
421a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s destroyed", id);
422a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
423a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
424a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
425a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
426a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
427a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
428a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
4293bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
4303bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
431a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
432a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (isMountpointMounted(mountPoint)) {
433a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC %s already mounted", id);
434a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EBUSY;
435a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
436a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
437a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
438a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
439a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
4408da6bcb006f4e4257cdd685e35e910a6334f6ceaSan Mehat        if (Loop::create(asecFileName, loopDevice, sizeof(loopDevice))) {
441a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            LOGE("ASEC loop device creation failed (%s)", strerror(errno));
442a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return -1;
443a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
444b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGD("New loop device created at %s", loopDevice);
445b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
446b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGD("Found active loopback for %s at %s", asecFileName, loopDevice);
447b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
448b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
449b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char dmDevice[255];
450b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    bool cleanupDm = false;
451b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (strcmp(key, "none")) {
452b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (Devmapper::lookupActive(id, dmDevice, sizeof(dmDevice))) {
453b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            unsigned int nr_sec = 0;
454b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            int fd;
455b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
456b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if ((fd = open(loopDevice, O_RDWR)) < 0) {
457b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                LOGE("Failed to open loopdevice (%s)", strerror(errno));
458b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                Loop::destroyByDevice(loopDevice);
459b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                return -1;
460b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
461b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
462b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
463b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                LOGE("Failed to get loop size (%s)", strerror(errno));
464b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                Loop::destroyByDevice(loopDevice);
465b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                close(fd);
466b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                return -1;
467b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
468b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            close(fd);
4698b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat            if (Devmapper::create(id, loopDevice, key, nr_sec,
470b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                                  dmDevice, sizeof(dmDevice))) {
471b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                LOGE("ASEC device mapping failed (%s)", strerror(errno));
472b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                Loop::destroyByDevice(loopDevice);
473b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                return -1;
474b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
475b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            LOGD("New devmapper instance created at %s", dmDevice);
476b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        } else {
477b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            LOGD("Found active devmapper for %s at %s", asecFileName, dmDevice);
478b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
479b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        cleanupDm = true;
480b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
481b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        strcpy(dmDevice, loopDevice);
482a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
483a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
484a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (mkdir(mountPoint, 0777)) {
485b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (errno != EEXIST) {
486b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            LOGE("Mountpoint creation failed (%s)", strerror(errno));
487b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if (cleanupDm) {
488b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                Devmapper::destroy(id);
489b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
490b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Loop::destroyByDevice(loopDevice);
491b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            return -1;
492b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
493a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
494a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
495b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (Fat::doMount(dmDevice, mountPoint, true, false, ownerUid, 0,
496cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat                     0222, false)) {
497cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat//                     0227, false)) {
498a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC mount failed (%s)", strerror(errno));
499b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (cleanupDm) {
500b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Devmapper::destroy(id);
501b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
502b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        Loop::destroyByDevice(loopDevice);
503a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
504a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
505a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
50688705166ab82057090a070c6d4200c3d9db76f11San Mehat    mActiveContainers->push_back(strdup(id));
507a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s mounted", id);
508a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
509a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
510a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
51149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint VolumeManager::mountVolume(const char *label) {
51249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
51349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
51449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
51549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
51649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
51749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
51849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
519a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->mountVol();
520a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
521a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
522a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareAvailable(const char *method, bool *avail) {
523a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
524a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
525a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
526a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
527a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
528a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
529a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (mUsbMassStorageConnected)
530a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        *avail = true;
531a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else
532a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        *avail = false;
533a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
534a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
535a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
536eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehatint VolumeManager::shareEnabled(const char *label, const char *method, bool *enabled) {
537eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    Volume *v = lookupVolume(label);
538eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
539eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    if (!v) {
540eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        errno = ENOENT;
541eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        return -1;
542eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    }
543eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
544eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    if (strcmp(method, "ums")) {
545eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        errno = ENOSYS;
546eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        return -1;
547eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    }
548eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
549eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    if (v->getState() != Volume::State_Shared) {
550eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        *enabled = false;
551b9aed74b146beb7499ebc5775e8ae179d16900efSan Mehat    } else {
552b9aed74b146beb7499ebc5775e8ae179d16900efSan Mehat        *enabled = true;
553eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    }
554eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    return 0;
555eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat}
556eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
557a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::simulate(const char *cmd, const char *arg) {
558a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
559a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!strcmp(cmd, "ums")) {
560a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(arg, "connect")) {
561a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(true);
562a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else if (!strcmp(arg, "disconnect")) {
563a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(false);
564a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
565a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            errno = EINVAL;
566a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            return -1;
567a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
568a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
569a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
570a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
571a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
572a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
573a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
574a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
575a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareVolume(const char *label, const char *method) {
576a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
577a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
578a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
579a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
580a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
581a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
582a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
583a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    /*
584a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * Eventually, we'll want to support additional share back-ends,
585a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * some of which may work while the media is mounted. For now,
586a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * we just support UMS
587a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     */
588a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
589a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
590a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
591a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
592a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
593a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
594a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
595a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
596a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
597a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
59849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Idle) {
599a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // You need to unmount manually befoe sharing
60049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
60149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
60249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
60349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
604a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t d = v->getDiskDevice();
605a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
606a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // This volume does not support raw disk access
607a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
608a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
609a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
610a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
611a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
612a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
613a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
614a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
615a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
616a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
6170cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file",
6180cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat                   O_WRONLY)) < 0) {
619a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to open ums lunfile (%s)", strerror(errno));
620a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
621a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
622a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
623a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, nodepath, strlen(nodepath)) < 0) {
624a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
625a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
626a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
627a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
628a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
629a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
630a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeShared();
631a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
632a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
633a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
634a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::unshareVolume(const char *label, const char *method) {
635a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
636a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
637a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
638a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
639a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
640a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
641a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
642a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
643a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
644a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
645a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
646a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
647a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() != Volume::State_Shared) {
648a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
649a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
650a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
651a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
652a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t d = v->getDiskDevice();
653a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
654a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
655a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
656a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
657a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
658a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
659a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
6600cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file", O_WRONLY)) < 0) {
661a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to open ums lunfile (%s)", strerror(errno));
662a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
663a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
664a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
665a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char ch = 0;
666a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, &ch, 1) < 0) {
667a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
668a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
669a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
670a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
671a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
672a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
673a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeUnshared();
674a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
67549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
67649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
6774ba8948dc16463053e21cda5744f519a555080d0San Mehatint VolumeManager::unmountVolume(const char *label, bool force) {
67849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
67949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
68049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
68149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
68249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
68349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
68449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
685a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
686a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
687a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
688a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
689a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
69049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Mounted) {
691a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Attempt to unmount volume which isn't mounted (%d)\n",
692a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             v->getState());
69349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
69449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
69549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
69649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
69788705166ab82057090a070c6d4200c3d9db76f11San Mehat    while(mActiveContainers->size()) {
69888705166ab82057090a070c6d4200c3d9db76f11San Mehat        AsecIdCollection::iterator it = mActiveContainers->begin();
69988705166ab82057090a070c6d4200c3d9db76f11San Mehat        LOGI("Unmounting ASEC %s (dependant on %s)", *it, v->getMountpoint());
7004ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (unmountAsec(*it, force)) {
7010e382532f32e97f90056250f2b13c59840d2c6b4San Mehat            LOGE("Failed to unmount ASEC %s (%s)", *it, strerror(errno), v->getMountpoint());
7020e382532f32e97f90056250f2b13c59840d2c6b4San Mehat            return -1;
70388705166ab82057090a070c6d4200c3d9db76f11San Mehat        }
70488705166ab82057090a070c6d4200c3d9db76f11San Mehat    }
70588705166ab82057090a070c6d4200c3d9db76f11San Mehat
7064ba8948dc16463053e21cda5744f519a555080d0San Mehat    return v->unmountVol(force);
70749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
70849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
709a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat/*
710a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * Looks up a volume by it's label or mount-point
711a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat */
71249e2bce5b74129c26a35e25d4693cbfe98c4688eSan MehatVolume *VolumeManager::lookupVolume(const char *label) {
71349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    VolumeCollection::iterator i;
71449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
71549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
716a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (label[0] == '/') {
717a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getMountpoint()))
718a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
719a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
720a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getLabel()))
721a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
722a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
72349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
72449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    return NULL;
72549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
726a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
727a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatbool VolumeManager::isMountpointMounted(const char *mp)
728a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat{
729a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char device[256];
730a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mount_path[256];
731a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char rest[256];
732a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    FILE *fp;
733a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char line[1024];
734a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
735a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!(fp = fopen("/proc/mounts", "r"))) {
736a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Error opening /proc/mounts (%s)", strerror(errno));
737a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return false;
738a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
739a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
740a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    while(fgets(line, sizeof(line), fp)) {
741a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        line[strlen(line)-1] = '\0';
742a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
743a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (!strcmp(mount_path, mp)) {
744a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            fclose(fp);
745a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return true;
746a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
747a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
748a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
749a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
750a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    fclose(fp);
751a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return false;
752a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
753a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
754