VolumeManager.cpp revision fcf24fe62f98c5d44431aa575555569c2c7a29b0
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"
41fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat#include "Asec.h"
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();
5488705166ab82057090a070c6d4200c3d9db76f11San Mehat    mActiveContainers = new AsecIdCollection();
55f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mBroadcaster = NULL;
56a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mUsbMassStorageConnected = false;
57f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
58f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
59f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::~VolumeManager() {
60f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    delete mBlockDevices;
6188705166ab82057090a070c6d4200c3d9db76f11San Mehat    delete mVolumes;
6288705166ab82057090a070c6d4200c3d9db76f11San Mehat    delete mActiveContainers;
63f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
64f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
65f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::start() {
66f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
67f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
68f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
69f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::stop() {
70f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
71f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
72f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
73f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::addVolume(Volume *v) {
74f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mVolumes->push_back(v);
75f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
76f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
77f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
78a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid VolumeManager::notifyUmsConnected(bool connected) {
79a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char msg[255];
80a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
81a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (connected) {
82a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mUsbMassStorageConnected = true;
83a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
84a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mUsbMassStorageConnected = false;
85a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
86a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(msg, sizeof(msg), "Share method ums now %s",
87a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             (connected ? "available" : "unavailable"));
88a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
89a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    getBroadcaster()->sendBroadcast(ResponseCode::ShareAvailabilityChange,
90a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                    msg, false);
91a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
92a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
93a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid VolumeManager::handleSwitchEvent(NetlinkEvent *evt) {
940cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    const char *devpath = evt->findParam("DEVPATH");
95a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    const char *name = evt->findParam("SWITCH_NAME");
96a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    const char *state = evt->findParam("SWITCH_STATE");
97a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
980cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if (!name || !state) {
990cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat        LOGW("Switch %s event missing name/state info", devpath);
1000cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat        return;
1010cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    }
1020cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat
103a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!strcmp(name, "usb_mass_storage")) {
104a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
105a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(state, "online"))  {
106a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(true);
107a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
108a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(false);
109a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
110a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
111a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Ignoring unknown switch '%s'", name);
112a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
113a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
114a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
115fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehatvoid VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
116fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    const char *devpath = evt->findParam("DEVPATH");
117f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
118fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    /* Lookup a volume to handle this device */
119f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator it;
120f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    bool hit = false;
121f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
122fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat        if (!(*it)->handleBlockEvent(evt)) {
123a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
124a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            LOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
125a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
126f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            hit = true;
127f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            break;
128f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        }
129f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
130f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
131f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!hit) {
132a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
133fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat        LOGW("No volumes handled block event for '%s'", devpath);
134a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
135f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
136f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
137f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
138f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::listVolumes(SocketClient *cli) {
139f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator i;
140f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
141f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
142f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        char *buffer;
143f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        asprintf(&buffer, "%s %s %d",
144f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getLabel(), (*i)->getMountpoint(),
145f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getState());
146a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
147f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        free(buffer);
148f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
149a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false);
150f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
151f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
15249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
153a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::formatVolume(const char *label) {
154a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
155a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
156a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
157a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
158a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
159a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
160a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
161a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->formatVol();
162a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
163a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
164a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
165a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1663bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(buffer, maxlen, "%s/%s", Volume::ASECDIR, id);
167a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
168a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
169a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1708b8f71b1d760411279f3b07a5c97709f052c689eSan Mehatint VolumeManager::createAsec(const char *id, unsigned int numSectors,
171a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                              const char *fstype, const char *key, int ownerUid) {
172fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    struct asec_superblock sb;
173fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    memset(&sb, 0, sizeof(sb));
174fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
175fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    sb.magic = ASEC_SB_MAGIC;
176fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    sb.ver = ASEC_SB_VER;
177a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
178d31e380bd9689dd9629b510ffe324707e261b439San Mehat    if (numSectors < ((1024*1024)/512)) {
179d31e380bd9689dd9629b510ffe324707e261b439San Mehat        LOGE("Invalid container size specified (%d sectors)", numSectors);
180d31e380bd9689dd9629b510ffe324707e261b439San Mehat        errno = EINVAL;
181d31e380bd9689dd9629b510ffe324707e261b439San Mehat        return -1;
182d31e380bd9689dd9629b510ffe324707e261b439San Mehat    }
183d31e380bd9689dd9629b510ffe324707e261b439San Mehat
184a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (lookupVolume(id)) {
1853bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        LOGE("ASEC id '%s' currently exists", id);
186a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EADDRINUSE;
187a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
188a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
189a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
190a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
1913bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
192a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
193a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!access(asecFileName, F_OK)) {
194a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
195a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             asecFileName, strerror(errno));
196a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EADDRINUSE;
197a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
198a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
199a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
200fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    /*
201fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     * Add some headroom
202fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     */
203fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    unsigned fatSize = (((numSectors * 4) / 512) + 1) * 2;
204fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    unsigned numImgSectors = numSectors + fatSize + 2;
205fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
206fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (numImgSectors % 63) {
207fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        numImgSectors += (63 - (numImgSectors % 63));
208fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
209fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
210fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    // Add +1 for our superblock which is at the end
211fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (Loop::createImageFile(asecFileName, numImgSectors + 1)) {
212a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC image file creation failed (%s)", strerror(errno));
213a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
214a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
215a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
216a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
2178da6bcb006f4e4257cdd685e35e910a6334f6ceaSan Mehat    if (Loop::create(asecFileName, loopDevice, sizeof(loopDevice))) {
218a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC loop device creation failed (%s)", strerror(errno));
219a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
220a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
221a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
222a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
223b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char dmDevice[255];
224b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    bool cleanupDm = false;
225a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
226b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (strcmp(key, "none")) {
227fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        // XXX: This is all we support for now
228fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH;
229fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        if (Devmapper::create(id, loopDevice, key, numImgSectors, dmDevice,
230b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                             sizeof(dmDevice))) {
231b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            LOGE("ASEC device mapping failed (%s)", strerror(errno));
232b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Loop::destroyByDevice(loopDevice);
233b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            unlink(asecFileName);
234b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            return -1;
235b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
236b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        cleanupDm = true;
237b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
238fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        sb.c_cipher = ASEC_SB_C_CIPHER_NONE;
239b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        strcpy(dmDevice, loopDevice);
240b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
241b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
242fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    /*
243fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     * Drop down the superblock at the end of the file
244fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     */
245fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
246fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    int sbfd = open(loopDevice, O_RDWR);
247fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (sbfd < 0) {
248fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        LOGE("Failed to open new DM device for superblock write (%s)", strerror(errno));
249fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        if (cleanupDm) {
250fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat            Devmapper::destroy(id);
251fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        }
252fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
253fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        unlink(asecFileName);
254fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
255fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
256fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
257fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) {
258fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        close(sbfd);
259fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        LOGE("Failed to lseek for superblock (%s)", strerror(errno));
260fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        if (cleanupDm) {
261fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat            Devmapper::destroy(id);
262fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        }
263fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
264fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        unlink(asecFileName);
265fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
266fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
267fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
268fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (write(sbfd, &sb, sizeof(sb)) != sizeof(sb)) {
269fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        close(sbfd);
270fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        LOGE("Failed to write superblock (%s)", strerror(errno));
271fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        if (cleanupDm) {
272fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat            Devmapper::destroy(id);
273fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        }
274fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
275fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        unlink(asecFileName);
276fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
277fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
278fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    close(sbfd);
279fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
280a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat    if (strcmp(fstype, "none")) {
281a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        if (strcmp(fstype, "fat")) {
282a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            LOGW("Unknown fstype '%s' specified for container", fstype);
283b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
284a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
285fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        if (Fat::format(dmDevice, numImgSectors)) {
286a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            LOGE("ASEC FAT format failed (%s)", strerror(errno));
287b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if (cleanupDm) {
288b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                Devmapper::destroy(id);
289b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
290eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            Loop::destroyByDevice(loopDevice);
291eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            unlink(asecFileName);
292eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            return -1;
293eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat        }
294a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        char mountPoint[255];
295a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat
296a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
297a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        if (mkdir(mountPoint, 0777)) {
298a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            if (errno != EEXIST) {
299a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                LOGE("Mountpoint creation failed (%s)", strerror(errno));
300a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                if (cleanupDm) {
301a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                    Devmapper::destroy(id);
302a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                }
303a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                Loop::destroyByDevice(loopDevice);
304a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                unlink(asecFileName);
305a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                return -1;
306a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            }
307a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        }
308a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
309a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        if (Fat::doMount(dmDevice, mountPoint, false, false, ownerUid,
310a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                         0, 0000, false)) {
311a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            LOGE("ASEC FAT mount failed (%s)", strerror(errno));
312a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            if (cleanupDm) {
313a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                Devmapper::destroy(id);
314a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            }
315a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            Loop::destroyByDevice(loopDevice);
316a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            unlink(asecFileName);
317a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            return -1;
318b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
319a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat    } else {
320a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        LOGI("Created raw secure container %s (no filesystem)", id);
321a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
32288705166ab82057090a070c6d4200c3d9db76f11San Mehat
32388705166ab82057090a070c6d4200c3d9db76f11San Mehat    mActiveContainers->push_back(strdup(id));
324a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
325a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
326a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
327a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::finalizeAsec(const char *id) {
328a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
329a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
330a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
331a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
3323bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
333a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
334a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
335a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Unable to finalize %s (%s)", id, strerror(errno));
336a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
337a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
338a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
3393bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
340fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    // XXX:
341fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    if (Fat::doMount(loopDevice, mountPoint, true, true, 0, 0, 0227, false)) {
342a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC finalize mount failed (%s)", strerror(errno));
343a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
344a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
345a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
346a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s finalized", id);
347a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
348a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
349a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
350048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehatint VolumeManager::renameAsec(const char *id1, const char *id2) {
351048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    char *asecFilename1;
352048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    char *asecFilename2;
353048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    char mountPoint[255];
354048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
3553bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    asprintf(&asecFilename1, "%s/%s.asec", Volume::SEC_ASECDIR, id1);
3563bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    asprintf(&asecFilename2, "%s/%s.asec", Volume::SEC_ASECDIR, id2);
357048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
3583bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id1);
359048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    if (isMountpointMounted(mountPoint)) {
360048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        LOGW("Rename attempt when src mounted");
361048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        errno = EBUSY;
362048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        goto out_err;
363048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
364048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
36596956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id2);
36696956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat    if (isMountpointMounted(mountPoint)) {
36796956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat        LOGW("Rename attempt when dst mounted");
36896956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat        errno = EBUSY;
36996956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat        goto out_err;
37096956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat    }
37196956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat
372048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    if (!access(asecFilename2, F_OK)) {
373048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        LOGE("Rename attempt when dst exists");
374048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        errno = EADDRINUSE;
375048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        goto out_err;
376048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
377048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
378048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    if (rename(asecFilename1, asecFilename2)) {
379048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        LOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno));
380048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        goto out_err;
381048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
382048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
383048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename1);
384048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename2);
385048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    return 0;
386048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
387048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehatout_err:
388048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename1);
389048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename2);
390048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    return -1;
391048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat}
392048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
3934ba8948dc16463053e21cda5744f519a555080d0San Mehat#define ASEC_UNMOUNT_RETRIES 5
3944ba8948dc16463053e21cda5744f519a555080d0San Mehatint VolumeManager::unmountAsec(const char *id, bool force) {
395a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
396a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
397a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
3983bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
3993bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
400a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
4010586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (!isMountpointMounted(mountPoint)) {
402b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGE("Unmount request for ASEC %s when not mounted", id);
403b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        errno = EINVAL;
404b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
405b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
40623969931fad6e993832208f099f6eea0f6f76eb5San Mehat
407b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    int i, rc;
4088c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat    for (i = 1; i <= ASEC_UNMOUNT_RETRIES; i++) {
409b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        rc = umount(mountPoint);
410b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (!rc) {
411b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            break;
412a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
413b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (rc && (errno == EINVAL || errno == ENOENT)) {
41412f4b89046b54de1bdc188b7057ba77d7566e573San Mehat            LOGI("Secure container %s unmounted OK", id);
415b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            rc = 0;
416b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            break;
417a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
418b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGW("ASEC %s unmount attempt %d failed (%s)",
4198c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat              id, i, strerror(errno));
4208c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
4214ba8948dc16463053e21cda5744f519a555080d0San Mehat        int action = 0; // default is to just complain
4224ba8948dc16463053e21cda5744f519a555080d0San Mehat
4234ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (force) {
4244ba8948dc16463053e21cda5744f519a555080d0San Mehat            if (i > (ASEC_UNMOUNT_RETRIES - 2))
4254ba8948dc16463053e21cda5744f519a555080d0San Mehat                action = 2; // SIGKILL
4264ba8948dc16463053e21cda5744f519a555080d0San Mehat            else if (i > (ASEC_UNMOUNT_RETRIES - 3))
4274ba8948dc16463053e21cda5744f519a555080d0San Mehat                action = 1; // SIGHUP
4284ba8948dc16463053e21cda5744f519a555080d0San Mehat        }
4298c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
430586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        Process::killProcessesWithOpenFiles(mountPoint, action);
4318c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat        usleep(1000 * 1000);
432b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
433b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
434b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (rc) {
4354ba8948dc16463053e21cda5744f519a555080d0San Mehat        errno = EBUSY;
4364ba8948dc16463053e21cda5744f519a555080d0San Mehat        LOGE("Failed to unmount container %s (%s)", id, strerror(errno));
437b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
438b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
439b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
44012f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    int retries = 10;
44112f4b89046b54de1bdc188b7057ba77d7566e573San Mehat
44212f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    while(retries--) {
44312f4b89046b54de1bdc188b7057ba77d7566e573San Mehat        if (!rmdir(mountPoint)) {
44412f4b89046b54de1bdc188b7057ba77d7566e573San Mehat            break;
44512f4b89046b54de1bdc188b7057ba77d7566e573San Mehat        }
44612f4b89046b54de1bdc188b7057ba77d7566e573San Mehat
44712f4b89046b54de1bdc188b7057ba77d7566e573San Mehat        LOGW("Failed to rmdir %s (%s)", mountPoint, strerror(errno));
44812f4b89046b54de1bdc188b7057ba77d7566e573San Mehat        usleep(1000 * 1000);
44912f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    }
45012f4b89046b54de1bdc188b7057ba77d7566e573San Mehat
45112f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    if (!retries) {
45212f4b89046b54de1bdc188b7057ba77d7566e573San Mehat        LOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno));
453f5c61980969a0b49bda37b5dc94ffe675ebd5a5aSan Mehat    }
45488705166ab82057090a070c6d4200c3d9db76f11San Mehat
455b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (Devmapper::destroy(id) && errno != ENXIO) {
456b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
457a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
458a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
459a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
460a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
461a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
462a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
46388705166ab82057090a070c6d4200c3d9db76f11San Mehat
46488705166ab82057090a070c6d4200c3d9db76f11San Mehat    AsecIdCollection::iterator it;
46588705166ab82057090a070c6d4200c3d9db76f11San Mehat    for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) {
46688705166ab82057090a070c6d4200c3d9db76f11San Mehat        if (!strcmp(*it, id)) {
46788705166ab82057090a070c6d4200c3d9db76f11San Mehat            free(*it);
46888705166ab82057090a070c6d4200c3d9db76f11San Mehat            mActiveContainers->erase(it);
46988705166ab82057090a070c6d4200c3d9db76f11San Mehat            break;
47088705166ab82057090a070c6d4200c3d9db76f11San Mehat        }
47188705166ab82057090a070c6d4200c3d9db76f11San Mehat    }
47288705166ab82057090a070c6d4200c3d9db76f11San Mehat    if (it == mActiveContainers->end()) {
47388705166ab82057090a070c6d4200c3d9db76f11San Mehat        LOGW("mActiveContainers is inconsistent!");
47488705166ab82057090a070c6d4200c3d9db76f11San Mehat    }
475b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    return 0;
476b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat}
477b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
4784ba8948dc16463053e21cda5744f519a555080d0San Mehatint VolumeManager::destroyAsec(const char *id, bool force) {
479b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char asecFileName[255];
480b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char mountPoint[255];
481b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
4823bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
48355013f7131ffe094e1c7d929cfc32b3b25096a9bSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
484b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
4850586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (isMountpointMounted(mountPoint)) {
48668f8ebdb24dfe1fe94de2c8fc11084ebfab9fa5dSan Mehat        LOGD("Unmounting container before destroy");
4874ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (unmountAsec(id, force)) {
4880586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat            LOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
4890586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat            return -1;
4900586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        }
4910586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    }
492a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
4930586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (unlink(asecFileName)) {
49468f8ebdb24dfe1fe94de2c8fc11084ebfab9fa5dSan Mehat        LOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno));
4950586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        return -1;
4960586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    }
497a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
498a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s destroyed", id);
499a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
500a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
501a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
502a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
503a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
504a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
505a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
5063bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
5073bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
508a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
509a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (isMountpointMounted(mountPoint)) {
510a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC %s already mounted", id);
511a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EBUSY;
512a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
513a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
514a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
515a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
516a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (Loop::lookupActive(asecFileName, loopDevice, sizeof(loopDevice))) {
5178da6bcb006f4e4257cdd685e35e910a6334f6ceaSan Mehat        if (Loop::create(asecFileName, loopDevice, sizeof(loopDevice))) {
518a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            LOGE("ASEC loop device creation failed (%s)", strerror(errno));
519a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return -1;
520a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
521b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGD("New loop device created at %s", loopDevice);
522b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
523b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        LOGD("Found active loopback for %s at %s", asecFileName, loopDevice);
524b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
525b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
526b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char dmDevice[255];
527b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    bool cleanupDm = false;
528fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    int fd;
529fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    unsigned int nr_sec = 0;
530b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
531fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if ((fd = open(loopDevice, O_RDWR)) < 0) {
532fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        LOGE("Failed to open loopdevice (%s)", strerror(errno));
533fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
534fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
535fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
536b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
537fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
538fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        LOGE("Failed to get loop size (%s)", strerror(errno));
539fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
540fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        close(fd);
541fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
542fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
543fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
544fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    /*
545fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     * Validate superblock
546fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     */
547fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    struct asec_superblock sb;
548fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    memset(&sb, 0, sizeof(sb));
549fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (lseek(fd, ((nr_sec-1) * 512), SEEK_SET) < 0) {
550fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        LOGE("lseek failed (%s)", strerror(errno));
551fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        close(fd);
552fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
553fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
554fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
555fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) {
556fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        LOGE("superblock read failed (%s)", strerror(errno));
557fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        close(fd);
558fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
559fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
560fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
561fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
562fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    close(fd);
563fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
564fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    LOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
565fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
566fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        LOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
567fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
568fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        errno = EMEDIUMTYPE;
569fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
570fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
571fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    nr_sec--; // We don't want the devmapping to extend onto our superblock
572fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
573fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (strcmp(key, "none")) {
574fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        if (Devmapper::lookupActive(id, dmDevice, sizeof(dmDevice))) {
5758b8f71b1d760411279f3b07a5c97709f052c689eSan Mehat            if (Devmapper::create(id, loopDevice, key, nr_sec,
576b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                                  dmDevice, sizeof(dmDevice))) {
577b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                LOGE("ASEC device mapping failed (%s)", strerror(errno));
578b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                Loop::destroyByDevice(loopDevice);
579b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                return -1;
580b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
581b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            LOGD("New devmapper instance created at %s", dmDevice);
582b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        } else {
583b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            LOGD("Found active devmapper for %s at %s", asecFileName, dmDevice);
584b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
585b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        cleanupDm = true;
586b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
587b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        strcpy(dmDevice, loopDevice);
588a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
589a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
590a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (mkdir(mountPoint, 0777)) {
591b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (errno != EEXIST) {
592b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            LOGE("Mountpoint creation failed (%s)", strerror(errno));
593b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if (cleanupDm) {
594b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                Devmapper::destroy(id);
595b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
596b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Loop::destroyByDevice(loopDevice);
597b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            return -1;
598b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
599a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
600a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
601b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (Fat::doMount(dmDevice, mountPoint, true, false, ownerUid, 0,
602cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat                     0222, false)) {
603cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat//                     0227, false)) {
604a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("ASEC mount failed (%s)", strerror(errno));
605b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (cleanupDm) {
606b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Devmapper::destroy(id);
607b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
608b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        Loop::destroyByDevice(loopDevice);
609a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
610a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
611a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
61288705166ab82057090a070c6d4200c3d9db76f11San Mehat    mActiveContainers->push_back(strdup(id));
613a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    LOGD("ASEC %s mounted", id);
614a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
615a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
616a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
61749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint VolumeManager::mountVolume(const char *label) {
61849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
61949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
62049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
62149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
62249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
62349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
62449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
625a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->mountVol();
626a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
627a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
628a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareAvailable(const char *method, bool *avail) {
629a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
630a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
631a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
632a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
633a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
634a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
635a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (mUsbMassStorageConnected)
636a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        *avail = true;
637a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else
638a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        *avail = false;
639a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
640a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
641a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
642eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehatint VolumeManager::shareEnabled(const char *label, const char *method, bool *enabled) {
643eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    Volume *v = lookupVolume(label);
644eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
645eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    if (!v) {
646eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        errno = ENOENT;
647eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        return -1;
648eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    }
649eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
650eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    if (strcmp(method, "ums")) {
651eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        errno = ENOSYS;
652eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        return -1;
653eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    }
654eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
655eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    if (v->getState() != Volume::State_Shared) {
656eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        *enabled = false;
657b9aed74b146beb7499ebc5775e8ae179d16900efSan Mehat    } else {
658b9aed74b146beb7499ebc5775e8ae179d16900efSan Mehat        *enabled = true;
659eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    }
660eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    return 0;
661eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat}
662eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
663a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::simulate(const char *cmd, const char *arg) {
664a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
665a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!strcmp(cmd, "ums")) {
666a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(arg, "connect")) {
667a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(true);
668a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else if (!strcmp(arg, "disconnect")) {
669a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            notifyUmsConnected(false);
670a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
671a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            errno = EINVAL;
672a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            return -1;
673a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
674a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
675a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
676a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
677a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
678a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
679a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
680a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
681a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareVolume(const char *label, const char *method) {
682a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
683a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
684a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
685a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
686a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
687a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
688a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
689a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    /*
690a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * Eventually, we'll want to support additional share back-ends,
691a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * some of which may work while the media is mounted. For now,
692a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * we just support UMS
693a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     */
694a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
695a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
696a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
697a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
698a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
699a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
700a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
701a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
702a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
703a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
70449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Idle) {
705a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // You need to unmount manually befoe sharing
70649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
70749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
70849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
70949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
710a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t d = v->getDiskDevice();
711a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
712a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // This volume does not support raw disk access
713a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
714a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
715a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
716a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
717a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
718a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
719a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
720a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
721a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
722a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
7230cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file",
7240cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat                   O_WRONLY)) < 0) {
725a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to open ums lunfile (%s)", strerror(errno));
726a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
727a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
728a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
729a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, nodepath, strlen(nodepath)) < 0) {
730a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
731a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
732a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
733a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
734a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
735a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
736a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeShared();
737a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
738a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
739a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
740a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::unshareVolume(const char *label, const char *method) {
741a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
742a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
743a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
744a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
745a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
746a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
747a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
748a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
749a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
750a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
751a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
752a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
753a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() != Volume::State_Shared) {
754a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
755a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
756a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
757a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
758a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t d = v->getDiskDevice();
759a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
760a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
761a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
762a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
763a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
764a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
765a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
7660cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file", O_WRONLY)) < 0) {
767a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to open ums lunfile (%s)", strerror(errno));
768a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
769a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
770a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
771a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char ch = 0;
772a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, &ch, 1) < 0) {
773a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to write to ums lunfile (%s)", strerror(errno));
774a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
775a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
776a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
777a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
778a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
779a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeUnshared();
780a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
78149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
78249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
7834ba8948dc16463053e21cda5744f519a555080d0San Mehatint VolumeManager::unmountVolume(const char *label, bool force) {
78449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
78549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
78649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
78749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
78849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
78949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
79049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
791a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
792a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
793a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
794a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
795a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
79649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Mounted) {
797a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Attempt to unmount volume which isn't mounted (%d)\n",
798a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             v->getState());
79949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
80049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
80149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
80249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
80388705166ab82057090a070c6d4200c3d9db76f11San Mehat    while(mActiveContainers->size()) {
80488705166ab82057090a070c6d4200c3d9db76f11San Mehat        AsecIdCollection::iterator it = mActiveContainers->begin();
80588705166ab82057090a070c6d4200c3d9db76f11San Mehat        LOGI("Unmounting ASEC %s (dependant on %s)", *it, v->getMountpoint());
8064ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (unmountAsec(*it, force)) {
80712f4b89046b54de1bdc188b7057ba77d7566e573San Mehat            LOGE("Failed to unmount ASEC %s (%s)", *it, strerror(errno));
8080e382532f32e97f90056250f2b13c59840d2c6b4San Mehat            return -1;
80988705166ab82057090a070c6d4200c3d9db76f11San Mehat        }
81088705166ab82057090a070c6d4200c3d9db76f11San Mehat    }
81188705166ab82057090a070c6d4200c3d9db76f11San Mehat
8124ba8948dc16463053e21cda5744f519a555080d0San Mehat    return v->unmountVol(force);
81349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
81449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
815a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat/*
816a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * Looks up a volume by it's label or mount-point
817a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat */
81849e2bce5b74129c26a35e25d4693cbfe98c4688eSan MehatVolume *VolumeManager::lookupVolume(const char *label) {
81949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    VolumeCollection::iterator i;
82049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
82149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
822a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (label[0] == '/') {
823a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getMountpoint()))
824a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
825a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
826a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getLabel()))
827a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
828a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
82949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
83049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    return NULL;
83149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
832a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
833a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatbool VolumeManager::isMountpointMounted(const char *mp)
834a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat{
835a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char device[256];
836a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mount_path[256];
837a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char rest[256];
838a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    FILE *fp;
839a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char line[1024];
840a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
841a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!(fp = fopen("/proc/mounts", "r"))) {
842a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        LOGE("Error opening /proc/mounts (%s)", strerror(errno));
843a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return false;
844a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
845a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
846a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    while(fgets(line, sizeof(line), fp)) {
847a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        line[strlen(line)-1] = '\0';
848a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
849a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (!strcmp(mount_path, mp)) {
850a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            fclose(fp);
851a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return true;
852a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
853a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
854a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
855a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
856a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    fclose(fp);
857a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return false;
858a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
859a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
860