VolumeManager.cpp revision 29d8da8cefa99e436c13295d4c9bad060ca18a6d
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
307b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root#include <openssl/md5.h>
317b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root
32f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <cutils/log.h>
33f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
34fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat#include <sysutils/NetlinkEvent.h>
35fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat
36f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "VolumeManager.h"
37ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehat#include "DirectVolume.h"
38a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "ResponseCode.h"
39a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include "Loop.h"
40a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include "Fat.h"
41b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include "Devmapper.h"
42586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include "Process.h"
43fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat#include "Asec.h"
4429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall#include "cryptfs.h"
4523969931fad6e993832208f099f6eea0f6f76eb5San Mehat
46f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::sInstance = NULL;
47f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
48f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::Instance() {
49f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!sInstance)
50f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        sInstance = new VolumeManager();
51f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return sInstance;
52f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
53f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
54f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::VolumeManager() {
55d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    mDebug = false;
56f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mVolumes = new VolumeCollection();
5788705166ab82057090a070c6d4200c3d9db76f11San Mehat    mActiveContainers = new AsecIdCollection();
58f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mBroadcaster = NULL;
5999635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    mUsbMassStorageEnabled = false;
6099635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    mUsbConnected = false;
61a28056b38275003895ff5d9576681aca01544822Mike Lockwood    mUmsSharingCount = 0;
62a28056b38275003895ff5d9576681aca01544822Mike Lockwood    mSavedDirtyRatio = -1;
63a28056b38275003895ff5d9576681aca01544822Mike Lockwood    // set dirty ratio to 0 when UMS is active
64a28056b38275003895ff5d9576681aca01544822Mike Lockwood    mUmsDirtyRatio = 0;
6599635f6c289fe2528c226403ea215c917ce86037Mike Lockwood
6699635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    readInitialState();
6799635f6c289fe2528c226403ea215c917ce86037Mike Lockwood}
6899635f6c289fe2528c226403ea215c917ce86037Mike Lockwood
6999635f6c289fe2528c226403ea215c917ce86037Mike Lockwoodvoid VolumeManager::readInitialState() {
7099635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    FILE *fp;
7199635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    char state[255];
7299635f6c289fe2528c226403ea215c917ce86037Mike Lockwood
7399635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    /*
7499635f6c289fe2528c226403ea215c917ce86037Mike Lockwood     * Read the initial mass storage enabled state
7599635f6c289fe2528c226403ea215c917ce86037Mike Lockwood     */
7699635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    if ((fp = fopen("/sys/devices/virtual/usb_composite/usb_mass_storage/enable", "r"))) {
7799635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        if (fgets(state, sizeof(state), fp)) {
7899635f6c289fe2528c226403ea215c917ce86037Mike Lockwood            mUsbMassStorageEnabled = !strncmp(state, "1", 1);
7999635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        } else {
8099635f6c289fe2528c226403ea215c917ce86037Mike Lockwood            SLOGE("Failed to read usb_mass_storage enabled state (%s)", strerror(errno));
8199635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        }
8299635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        fclose(fp);
8399635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    } else {
8499635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        SLOGD("USB mass storage support is not enabled in the kernel");
8599635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    }
8699635f6c289fe2528c226403ea215c917ce86037Mike Lockwood
8799635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    /*
8899635f6c289fe2528c226403ea215c917ce86037Mike Lockwood     * Read the initial USB connected state
8999635f6c289fe2528c226403ea215c917ce86037Mike Lockwood     */
9099635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    if ((fp = fopen("/sys/devices/virtual/switch/usb_configuration/state", "r"))) {
9199635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        if (fgets(state, sizeof(state), fp)) {
9299635f6c289fe2528c226403ea215c917ce86037Mike Lockwood            mUsbConnected = !strncmp(state, "1", 1);
9399635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        } else {
9499635f6c289fe2528c226403ea215c917ce86037Mike Lockwood            SLOGE("Failed to read usb_configuration switch (%s)", strerror(errno));
9599635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        }
9699635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        fclose(fp);
9799635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    } else {
9899635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        SLOGD("usb_configuration switch is not enabled in the kernel");
9999635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    }
100f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
101f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
102f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::~VolumeManager() {
10388705166ab82057090a070c6d4200c3d9db76f11San Mehat    delete mVolumes;
10488705166ab82057090a070c6d4200c3d9db76f11San Mehat    delete mActiveContainers;
105f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
106f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
107d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehatchar *VolumeManager::asecHash(const char *id, char *buffer, size_t len) {
108acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    static const char* digits = "0123456789abcdef";
109acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root
1107b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root    unsigned char sig[MD5_DIGEST_LENGTH];
111d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
112acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    if (buffer == NULL) {
113acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        SLOGE("Destination buffer is NULL");
114acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        errno = ESPIPE;
115acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        return NULL;
116acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    } else if (id == NULL) {
117acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        SLOGE("Source buffer is NULL");
118acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        errno = ESPIPE;
119acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        return NULL;
120acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    } else if (len < MD5_ASCII_LENGTH_PLUS_NULL) {
121acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        SLOGE("Target hash buffer size < %d bytes (%d)",
122acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root                MD5_ASCII_LENGTH_PLUS_NULL, len);
123d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        errno = ESPIPE;
124d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return NULL;
125d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
1267b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root
1277b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root    MD5(reinterpret_cast<const unsigned char*>(id), strlen(id), sig);
128d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
129acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    char *p = buffer;
1307b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root    for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
131acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        *p++ = digits[sig[i] >> 4];
132acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        *p++ = digits[sig[i] & 0x0F];
133d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
134acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    *p = '\0';
135d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
136d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    return buffer;
137d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat}
138d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
139d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehatvoid VolumeManager::setDebug(bool enable) {
140d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    mDebug = enable;
141d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    VolumeCollection::iterator it;
142d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
143d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        (*it)->setDebug(enable);
144d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
145d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat}
146d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
147f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::start() {
148f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
149f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
150f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
151f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::stop() {
152f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
153f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
154f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
155f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::addVolume(Volume *v) {
156f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mVolumes->push_back(v);
157f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
158f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
159f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
16099635f6c289fe2528c226403ea215c917ce86037Mike Lockwoodvoid VolumeManager::notifyUmsAvailable(bool available) {
161a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char msg[255];
162a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
163a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(msg, sizeof(msg), "Share method ums now %s",
16499635f6c289fe2528c226403ea215c917ce86037Mike Lockwood             (available ? "available" : "unavailable"));
16599635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    SLOGD(msg);
166a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    getBroadcaster()->sendBroadcast(ResponseCode::ShareAvailabilityChange,
167a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                    msg, false);
168a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
169a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
170a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid VolumeManager::handleSwitchEvent(NetlinkEvent *evt) {
1710cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    const char *devpath = evt->findParam("DEVPATH");
172a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    const char *name = evt->findParam("SWITCH_NAME");
173a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    const char *state = evt->findParam("SWITCH_STATE");
174a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1750cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if (!name || !state) {
17697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Switch %s event missing name/state info", devpath);
1770cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat        return;
1780cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    }
1790cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat
18099635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    bool oldAvailable = massStorageAvailable();
18199635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    if (!strcmp(name, "usb_configuration")) {
18299635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        mUsbConnected = !strcmp(state, "1");
18399635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        SLOGD("USB %s", mUsbConnected ? "connected" : "disconnected");
18499635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        bool newAvailable = massStorageAvailable();
18599635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        if (newAvailable != oldAvailable) {
18699635f6c289fe2528c226403ea215c917ce86037Mike Lockwood            notifyUmsAvailable(newAvailable);
187a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
188a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
189a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
19099635f6c289fe2528c226403ea215c917ce86037Mike Lockwoodvoid VolumeManager::handleUsbCompositeEvent(NetlinkEvent *evt) {
19199635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    const char *function = evt->findParam("FUNCTION");
19299635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    const char *enabled = evt->findParam("ENABLED");
19399635f6c289fe2528c226403ea215c917ce86037Mike Lockwood
19499635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    if (!function || !enabled) {
19599635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        SLOGW("usb_composite event missing function/enabled info");
19699635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        return;
19799635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    }
19899635f6c289fe2528c226403ea215c917ce86037Mike Lockwood
19999635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    if (!strcmp(function, "usb_mass_storage")) {
20099635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        bool oldAvailable = massStorageAvailable();
20199635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        mUsbMassStorageEnabled = !strcmp(enabled, "1");
20299635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        SLOGD("usb_mass_storage function %s", mUsbMassStorageEnabled ? "enabled" : "disabled");
20399635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        bool newAvailable = massStorageAvailable();
20499635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        if (newAvailable != oldAvailable) {
20599635f6c289fe2528c226403ea215c917ce86037Mike Lockwood            notifyUmsAvailable(newAvailable);
20699635f6c289fe2528c226403ea215c917ce86037Mike Lockwood        }
20799635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    }
20899635f6c289fe2528c226403ea215c917ce86037Mike Lockwood}
209a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
210fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehatvoid VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
211fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    const char *devpath = evt->findParam("DEVPATH");
212f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
213fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    /* Lookup a volume to handle this device */
214f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator it;
215f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    bool hit = false;
216f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
217fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat        if (!(*it)->handleBlockEvent(evt)) {
218a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
21997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
220a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
221f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            hit = true;
222f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            break;
223f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        }
224f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
225f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
226f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!hit) {
227a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
22897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("No volumes handled block event for '%s'", devpath);
229a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
230f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
231f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
232f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
233f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::listVolumes(SocketClient *cli) {
234f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator i;
235f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
236f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
237f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        char *buffer;
238f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        asprintf(&buffer, "%s %s %d",
239f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getLabel(), (*i)->getMountpoint(),
240f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getState());
241a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
242f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        free(buffer);
243f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
244a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false);
245f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
246f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
24749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
248a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::formatVolume(const char *label) {
249a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
250a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
251a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
252a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
253a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
254a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
255a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
256a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->formatVol();
257a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
258a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
259508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootint VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) {
260508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    char idHash[33];
261508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    if (!asecHash(sourceFile, idHash, sizeof(idHash))) {
262508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        SLOGE("Hash of '%s' failed (%s)", sourceFile, strerror(errno));
263508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        return -1;
264508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    }
265508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
266508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    memset(mountPath, 0, mountPathLen);
267508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    snprintf(mountPath, mountPathLen, "%s/%s", Volume::LOOPDIR, idHash);
268508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
269508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    if (access(mountPath, F_OK)) {
270508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        errno = ENOENT;
271508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        return -1;
272508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    }
273508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
274508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    return 0;
275508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root}
276508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
277a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
27888ac2c06539485942bf414efda2d39647fa1a415San Mehat    char asecFileName[255];
27988ac2c06539485942bf414efda2d39647fa1a415San Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
28088ac2c06539485942bf414efda2d39647fa1a415San Mehat
28188ac2c06539485942bf414efda2d39647fa1a415San Mehat    memset(buffer, 0, maxlen);
28288ac2c06539485942bf414efda2d39647fa1a415San Mehat    if (access(asecFileName, F_OK)) {
28388ac2c06539485942bf414efda2d39647fa1a415San Mehat        errno = ENOENT;
28488ac2c06539485942bf414efda2d39647fa1a415San Mehat        return -1;
28588ac2c06539485942bf414efda2d39647fa1a415San Mehat    }
286a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
2873bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(buffer, maxlen, "%s/%s", Volume::ASECDIR, id);
288a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
289a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
290a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
2918b8f71b1d760411279f3b07a5c97709f052c689eSan Mehatint VolumeManager::createAsec(const char *id, unsigned int numSectors,
292a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat                              const char *fstype, const char *key, int ownerUid) {
293fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    struct asec_superblock sb;
294fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    memset(&sb, 0, sizeof(sb));
295fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
296fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    sb.magic = ASEC_SB_MAGIC;
297fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    sb.ver = ASEC_SB_VER;
298a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
299d31e380bd9689dd9629b510ffe324707e261b439San Mehat    if (numSectors < ((1024*1024)/512)) {
30097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Invalid container size specified (%d sectors)", numSectors);
301d31e380bd9689dd9629b510ffe324707e261b439San Mehat        errno = EINVAL;
302d31e380bd9689dd9629b510ffe324707e261b439San Mehat        return -1;
303d31e380bd9689dd9629b510ffe324707e261b439San Mehat    }
304d31e380bd9689dd9629b510ffe324707e261b439San Mehat
305a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (lookupVolume(id)) {
30697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC id '%s' currently exists", id);
307a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EADDRINUSE;
308a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
309a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
310a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
311a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
3123bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
313a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
314a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!access(asecFileName, F_OK)) {
31597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
316a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat             asecFileName, strerror(errno));
317a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EADDRINUSE;
318a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
319a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
320a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
321fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    /*
322fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     * Add some headroom
323fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     */
324fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    unsigned fatSize = (((numSectors * 4) / 512) + 1) * 2;
325fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    unsigned numImgSectors = numSectors + fatSize + 2;
326fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
327fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (numImgSectors % 63) {
328fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        numImgSectors += (63 - (numImgSectors % 63));
329fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
330fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
331fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    // Add +1 for our superblock which is at the end
332fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (Loop::createImageFile(asecFileName, numImgSectors + 1)) {
33397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC image file creation failed (%s)", strerror(errno));
334a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
335a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
336a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
337d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    char idHash[33];
338d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!asecHash(id, idHash, sizeof(idHash))) {
33997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
340d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        unlink(asecFileName);
341d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
342d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
343d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
344a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
345d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
34697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
347a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
348a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
349a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
350a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
351b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char dmDevice[255];
352b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    bool cleanupDm = false;
353a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
354b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (strcmp(key, "none")) {
355fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        // XXX: This is all we support for now
356fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH;
357d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (Devmapper::create(idHash, loopDevice, key, numImgSectors, dmDevice,
358b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                             sizeof(dmDevice))) {
35997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("ASEC device mapping failed (%s)", strerror(errno));
360b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Loop::destroyByDevice(loopDevice);
361b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            unlink(asecFileName);
362b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            return -1;
363b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
364b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        cleanupDm = true;
365b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
366fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        sb.c_cipher = ASEC_SB_C_CIPHER_NONE;
367b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        strcpy(dmDevice, loopDevice);
368b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
369b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
370fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    /*
371fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     * Drop down the superblock at the end of the file
372fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     */
373fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
374fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    int sbfd = open(loopDevice, O_RDWR);
375fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (sbfd < 0) {
37697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to open new DM device for superblock write (%s)", strerror(errno));
377fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        if (cleanupDm) {
378d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            Devmapper::destroy(idHash);
379fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        }
380fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
381fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        unlink(asecFileName);
382fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
383fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
384fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
385fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) {
386fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        close(sbfd);
38797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to lseek for superblock (%s)", strerror(errno));
388fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        if (cleanupDm) {
389d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            Devmapper::destroy(idHash);
390fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        }
391fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
392fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        unlink(asecFileName);
393fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
394fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
395fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
396fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (write(sbfd, &sb, sizeof(sb)) != sizeof(sb)) {
397fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        close(sbfd);
39897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to write superblock (%s)", strerror(errno));
399fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        if (cleanupDm) {
400d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            Devmapper::destroy(idHash);
401fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        }
402fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
403fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        unlink(asecFileName);
404fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
405fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
406fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    close(sbfd);
407fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
408a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat    if (strcmp(fstype, "none")) {
409a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        if (strcmp(fstype, "fat")) {
41097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGW("Unknown fstype '%s' specified for container", fstype);
411b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
412a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
413fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        if (Fat::format(dmDevice, numImgSectors)) {
41497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("ASEC FAT format failed (%s)", strerror(errno));
415b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if (cleanupDm) {
416d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                Devmapper::destroy(idHash);
417b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
418eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            Loop::destroyByDevice(loopDevice);
419eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            unlink(asecFileName);
420eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            return -1;
421eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat        }
422a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        char mountPoint[255];
423a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat
424a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
425a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        if (mkdir(mountPoint, 0777)) {
426a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            if (errno != EEXIST) {
42797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                SLOGE("Mountpoint creation failed (%s)", strerror(errno));
428a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                if (cleanupDm) {
429d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                    Devmapper::destroy(idHash);
430a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                }
431a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                Loop::destroyByDevice(loopDevice);
432a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                unlink(asecFileName);
433a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                return -1;
434a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            }
435a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        }
436a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
437a3e06084564c86ff618c40f185f3676b8b629b94Kenny Root        if (Fat::doMount(dmDevice, mountPoint, false, false, false, ownerUid,
438a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                         0, 0000, false)) {
43997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("ASEC FAT mount failed (%s)", strerror(errno));
440a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            if (cleanupDm) {
441d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                Devmapper::destroy(idHash);
442a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            }
443a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            Loop::destroyByDevice(loopDevice);
444a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            unlink(asecFileName);
445a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            return -1;
446b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
447a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat    } else {
44897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGI("Created raw secure container %s (no filesystem)", id);
449a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
45088705166ab82057090a070c6d4200c3d9db76f11San Mehat
451cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root    mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
452a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
453a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
454a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
455a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::finalizeAsec(const char *id) {
456a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
457a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
458a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
459a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
4603bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
461a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
462d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    char idHash[33];
463d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!asecHash(id, idHash, sizeof(idHash))) {
46497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
465d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
466d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
467d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
468d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
46997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to finalize %s (%s)", id, strerror(errno));
470a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
471a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
472a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
4733bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
474fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat    // XXX:
475a3e06084564c86ff618c40f185f3676b8b629b94Kenny Root    if (Fat::doMount(loopDevice, mountPoint, true, true, true, 0, 0, 0227, false)) {
47697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC finalize mount failed (%s)", strerror(errno));
477a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
478a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
479a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
480d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (mDebug) {
48197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGD("ASEC %s finalized", id);
482d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
483a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
484a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
485a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
486048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehatint VolumeManager::renameAsec(const char *id1, const char *id2) {
487048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    char *asecFilename1;
488048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    char *asecFilename2;
489048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    char mountPoint[255];
490048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
4913bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    asprintf(&asecFilename1, "%s/%s.asec", Volume::SEC_ASECDIR, id1);
4923bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    asprintf(&asecFilename2, "%s/%s.asec", Volume::SEC_ASECDIR, id2);
493048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
4943bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id1);
495048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    if (isMountpointMounted(mountPoint)) {
49697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Rename attempt when src mounted");
497048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        errno = EBUSY;
498048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        goto out_err;
499048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
500048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
50196956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id2);
50296956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat    if (isMountpointMounted(mountPoint)) {
50397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Rename attempt when dst mounted");
50496956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat        errno = EBUSY;
50596956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat        goto out_err;
50696956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat    }
50796956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat
508048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    if (!access(asecFilename2, F_OK)) {
50997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Rename attempt when dst exists");
510048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        errno = EADDRINUSE;
511048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        goto out_err;
512048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
513048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
514048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    if (rename(asecFilename1, asecFilename2)) {
51597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno));
516048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        goto out_err;
517048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
518048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
519048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename1);
520048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename2);
521048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    return 0;
522048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
523048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehatout_err:
524048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename1);
525048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename2);
526048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    return -1;
527048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat}
528048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
529fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root#define UNMOUNT_RETRIES 5
530fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root#define UNMOUNT_SLEEP_BETWEEN_RETRY_MS (1000 * 1000)
5314ba8948dc16463053e21cda5744f519a555080d0San Mehatint VolumeManager::unmountAsec(const char *id, bool force) {
532a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
533a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
534a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
5353bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
5363bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
537a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
538d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    char idHash[33];
539d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!asecHash(id, idHash, sizeof(idHash))) {
54097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
541d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
542d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
543d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
544fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    return unmountLoopImage(id, idHash, asecFileName, mountPoint, force);
545fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root}
546fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
547508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootint VolumeManager::unmountObb(const char *fileName, bool force) {
548fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char mountPoint[255];
549fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
550fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char idHash[33];
551fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (!asecHash(fileName, idHash, sizeof(idHash))) {
552fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Hash of '%s' failed (%s)", fileName, strerror(errno));
553fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
554fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
555fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
556fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::LOOPDIR, idHash);
557fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
558fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    return unmountLoopImage(fileName, idHash, fileName, mountPoint, force);
559fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root}
560fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
561fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Rootint VolumeManager::unmountLoopImage(const char *id, const char *idHash,
562fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        const char *fileName, const char *mountPoint, bool force) {
5630586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (!isMountpointMounted(mountPoint)) {
564fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Unmount request for %s when not mounted", id);
565918e5f9f10b9c1ff929683743ffbf229027ce240Kenny Root        errno = ENOENT;
566b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
567b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
56823969931fad6e993832208f099f6eea0f6f76eb5San Mehat
569b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    int i, rc;
570fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    for (i = 1; i <= UNMOUNT_RETRIES; i++) {
571b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        rc = umount(mountPoint);
572b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (!rc) {
573b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            break;
574a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
575b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (rc && (errno == EINVAL || errno == ENOENT)) {
576fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            SLOGI("Container %s unmounted OK", id);
577b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            rc = 0;
578b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            break;
579a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
580fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGW("%s unmount attempt %d failed (%s)",
5818c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat              id, i, strerror(errno));
5828c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
5834ba8948dc16463053e21cda5744f519a555080d0San Mehat        int action = 0; // default is to just complain
5844ba8948dc16463053e21cda5744f519a555080d0San Mehat
5854ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (force) {
586fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            if (i > (UNMOUNT_RETRIES - 2))
5874ba8948dc16463053e21cda5744f519a555080d0San Mehat                action = 2; // SIGKILL
588fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            else if (i > (UNMOUNT_RETRIES - 3))
5894ba8948dc16463053e21cda5744f519a555080d0San Mehat                action = 1; // SIGHUP
5904ba8948dc16463053e21cda5744f519a555080d0San Mehat        }
5918c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
592586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        Process::killProcessesWithOpenFiles(mountPoint, action);
593fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
594b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
595b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
596b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (rc) {
5974ba8948dc16463053e21cda5744f519a555080d0San Mehat        errno = EBUSY;
59897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to unmount container %s (%s)", id, strerror(errno));
599b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
600b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
601b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
60212f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    int retries = 10;
60312f4b89046b54de1bdc188b7057ba77d7566e573San Mehat
60412f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    while(retries--) {
60512f4b89046b54de1bdc188b7057ba77d7566e573San Mehat        if (!rmdir(mountPoint)) {
60612f4b89046b54de1bdc188b7057ba77d7566e573San Mehat            break;
60712f4b89046b54de1bdc188b7057ba77d7566e573San Mehat        }
60812f4b89046b54de1bdc188b7057ba77d7566e573San Mehat
60997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Failed to rmdir %s (%s)", mountPoint, strerror(errno));
610fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
61112f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    }
61212f4b89046b54de1bdc188b7057ba77d7566e573San Mehat
61312f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    if (!retries) {
61497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno));
615f5c61980969a0b49bda37b5dc94ffe675ebd5a5aSan Mehat    }
61688705166ab82057090a070c6d4200c3d9db76f11San Mehat
617d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (Devmapper::destroy(idHash) && errno != ENXIO) {
61897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
619a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
620a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
621a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
622d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
623a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
624d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    } else {
625fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGW("Failed to find loop device for {%s} (%s)", fileName, strerror(errno));
626a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
62788705166ab82057090a070c6d4200c3d9db76f11San Mehat
62888705166ab82057090a070c6d4200c3d9db76f11San Mehat    AsecIdCollection::iterator it;
62988705166ab82057090a070c6d4200c3d9db76f11San Mehat    for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) {
630cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        ContainerData* cd = *it;
631cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        if (!strcmp(cd->id, id)) {
63288705166ab82057090a070c6d4200c3d9db76f11San Mehat            free(*it);
63388705166ab82057090a070c6d4200c3d9db76f11San Mehat            mActiveContainers->erase(it);
63488705166ab82057090a070c6d4200c3d9db76f11San Mehat            break;
63588705166ab82057090a070c6d4200c3d9db76f11San Mehat        }
63688705166ab82057090a070c6d4200c3d9db76f11San Mehat    }
63788705166ab82057090a070c6d4200c3d9db76f11San Mehat    if (it == mActiveContainers->end()) {
63897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("mActiveContainers is inconsistent!");
63988705166ab82057090a070c6d4200c3d9db76f11San Mehat    }
640b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    return 0;
641b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat}
642b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
6434ba8948dc16463053e21cda5744f519a555080d0San Mehatint VolumeManager::destroyAsec(const char *id, bool force) {
644b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char asecFileName[255];
645b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char mountPoint[255];
646b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
6473bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
64855013f7131ffe094e1c7d929cfc32b3b25096a9bSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
649b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
6500586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (isMountpointMounted(mountPoint)) {
651d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (mDebug) {
65297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGD("Unmounting container before destroy");
653d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        }
6544ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (unmountAsec(id, force)) {
65597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
6560586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat            return -1;
6570586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        }
6580586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    }
659a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
6600586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (unlink(asecFileName)) {
66197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno));
6620586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        return -1;
6630586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    }
664a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
665d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (mDebug) {
66697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGD("ASEC %s destroyed", id);
667d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
668a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
669a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
670a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
671a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
672a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
673a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
674a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
6753bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
6763bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
677a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
678a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (isMountpointMounted(mountPoint)) {
67997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC %s already mounted", id);
680a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EBUSY;
681a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
682a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
683a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
684d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    char idHash[33];
685d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!asecHash(id, idHash, sizeof(idHash))) {
68697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
687d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
688d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
6897b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root
690a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
691d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
692d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
69397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
694a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return -1;
695a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
696d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (mDebug) {
69797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGD("New loop device created at %s", loopDevice);
698d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        }
699b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
700d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (mDebug) {
70197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGD("Found active loopback for %s at %s", asecFileName, loopDevice);
702d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        }
703b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
704b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
705b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char dmDevice[255];
706b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    bool cleanupDm = false;
707fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    int fd;
708fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    unsigned int nr_sec = 0;
709b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
710fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if ((fd = open(loopDevice, O_RDWR)) < 0) {
71197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to open loopdevice (%s)", strerror(errno));
712fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
713fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
714fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
715b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
716fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
71797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to get loop size (%s)", strerror(errno));
718fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
719fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        close(fd);
720fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
721fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
722fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
723fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    /*
724fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     * Validate superblock
725fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     */
726fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    struct asec_superblock sb;
727fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    memset(&sb, 0, sizeof(sb));
728fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (lseek(fd, ((nr_sec-1) * 512), SEEK_SET) < 0) {
72997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("lseek failed (%s)", strerror(errno));
730fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        close(fd);
731fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
732fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
733fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
734fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) {
73597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("superblock read failed (%s)", strerror(errno));
736fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        close(fd);
737fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
738fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
739fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
740fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
741fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    close(fd);
742fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
743d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (mDebug) {
74497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
745d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
746fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
74797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
748fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
749fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        errno = EMEDIUMTYPE;
750fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
751fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
752fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    nr_sec--; // We don't want the devmapping to extend onto our superblock
753fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
754fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (strcmp(key, "none")) {
755d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (Devmapper::lookupActive(idHash, dmDevice, sizeof(dmDevice))) {
756d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            if (Devmapper::create(idHash, loopDevice, key, nr_sec,
757b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                                  dmDevice, sizeof(dmDevice))) {
75897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                SLOGE("ASEC device mapping failed (%s)", strerror(errno));
759b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                Loop::destroyByDevice(loopDevice);
760b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                return -1;
761b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
762d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            if (mDebug) {
76397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                SLOGD("New devmapper instance created at %s", dmDevice);
764d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            }
765b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        } else {
766d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            if (mDebug) {
76797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                SLOGD("Found active devmapper for %s at %s", asecFileName, dmDevice);
768d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            }
769b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
770b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        cleanupDm = true;
771b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
772b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        strcpy(dmDevice, loopDevice);
773a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
774a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
775a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (mkdir(mountPoint, 0777)) {
776b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (errno != EEXIST) {
77797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Mountpoint creation failed (%s)", strerror(errno));
778b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if (cleanupDm) {
779d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                Devmapper::destroy(idHash);
780b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
781b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Loop::destroyByDevice(loopDevice);
782b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            return -1;
783b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
784a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
785a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
786a3e06084564c86ff618c40f185f3676b8b629b94Kenny Root    if (Fat::doMount(dmDevice, mountPoint, true, false, true, ownerUid, 0,
787cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat                     0222, false)) {
788cff5ec3d360b699ad13df05670efe0d0a7386fbeSan Mehat//                     0227, false)) {
78997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC mount failed (%s)", strerror(errno));
790b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (cleanupDm) {
791d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            Devmapper::destroy(idHash);
792b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
793b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        Loop::destroyByDevice(loopDevice);
794a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
795a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
796a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
797cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root    mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
798d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (mDebug) {
79997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGD("ASEC %s mounted", id);
800d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
801a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
802a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
803a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
804fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root/**
805fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root * Mounts an image file <code>img</code>.
806fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root */
807508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootint VolumeManager::mountObb(const char *img, const char *key, int ownerUid) {
808fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char mountPoint[255];
809fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
810fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char idHash[33];
811fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (!asecHash(img, idHash, sizeof(idHash))) {
812fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Hash of '%s' failed (%s)", img, strerror(errno));
813fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
814fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
815fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
816fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::LOOPDIR, idHash);
817fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
818fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (isMountpointMounted(mountPoint)) {
819fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Image %s already mounted", img);
820fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        errno = EBUSY;
821fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
822fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
823fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
824fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char loopDevice[255];
825fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
826fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (Loop::create(idHash, img, loopDevice, sizeof(loopDevice))) {
827fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            SLOGE("Image loop device creation failed (%s)", strerror(errno));
828fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            return -1;
829fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
830fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (mDebug) {
831fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            SLOGD("New loop device created at %s", loopDevice);
832fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
833fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    } else {
834fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (mDebug) {
835fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            SLOGD("Found active loopback for %s at %s", img, loopDevice);
836fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
837fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
838fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
839fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char dmDevice[255];
840fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    bool cleanupDm = false;
841fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    int fd;
842fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    unsigned int nr_sec = 0;
843fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
844fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if ((fd = open(loopDevice, O_RDWR)) < 0) {
845fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Failed to open loopdevice (%s)", strerror(errno));
846fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        Loop::destroyByDevice(loopDevice);
847fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
848fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
849fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
850fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
851fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Failed to get loop size (%s)", strerror(errno));
852fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        Loop::destroyByDevice(loopDevice);
853fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        close(fd);
854fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
855fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
856fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
857fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    close(fd);
858fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
859fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (strcmp(key, "none")) {
860fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (Devmapper::lookupActive(idHash, dmDevice, sizeof(dmDevice))) {
861fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            if (Devmapper::create(idHash, loopDevice, key, nr_sec,
862fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                                  dmDevice, sizeof(dmDevice))) {
863fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                SLOGE("ASEC device mapping failed (%s)", strerror(errno));
864fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                Loop::destroyByDevice(loopDevice);
865fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                return -1;
866fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            }
867fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            if (mDebug) {
868fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                SLOGD("New devmapper instance created at %s", dmDevice);
869fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            }
870fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        } else {
871fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            if (mDebug) {
872fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                SLOGD("Found active devmapper for %s at %s", img, dmDevice);
873fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            }
874fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
875fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        cleanupDm = true;
876fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    } else {
877fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        strcpy(dmDevice, loopDevice);
878fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
879fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
880fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (mkdir(mountPoint, 0755)) {
881fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (errno != EEXIST) {
882fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            SLOGE("Mountpoint creation failed (%s)", strerror(errno));
883fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            if (cleanupDm) {
884fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                Devmapper::destroy(idHash);
885fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            }
886fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            Loop::destroyByDevice(loopDevice);
887fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            return -1;
888fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
889fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
890fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
891a3e06084564c86ff618c40f185f3676b8b629b94Kenny Root    if (Fat::doMount(dmDevice, mountPoint, true, false, true, ownerUid, 0,
892fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                     0227, false)) {
893fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Image mount failed (%s)", strerror(errno));
894fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (cleanupDm) {
895fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            Devmapper::destroy(idHash);
896fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
897fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        Loop::destroyByDevice(loopDevice);
898fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
899fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
900fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
901cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root    mActiveContainers->push_back(new ContainerData(strdup(img), OBB));
902fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (mDebug) {
903fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGD("Image %s mounted", img);
904fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
905fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    return 0;
906fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root}
907fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
90849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint VolumeManager::mountVolume(const char *label) {
90949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
91049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
91149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
91249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
91349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
91449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
91549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
916a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->mountVol();
917a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
918a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
919508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootint VolumeManager::listMountedObbs(SocketClient* cli) {
920508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    char device[256];
921508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    char mount_path[256];
922508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    char rest[256];
923508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    FILE *fp;
924508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    char line[1024];
925508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
926508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    if (!(fp = fopen("/proc/mounts", "r"))) {
927508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
928508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        return -1;
929508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    }
930508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
931508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    // Create a string to compare against that has a trailing slash
932508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    int loopDirLen = sizeof(Volume::LOOPDIR);
933508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    char loopDir[loopDirLen + 2];
934508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    strcpy(loopDir, Volume::LOOPDIR);
935508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    loopDir[loopDirLen++] = '/';
936508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    loopDir[loopDirLen] = '\0';
937508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
938508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    while(fgets(line, sizeof(line), fp)) {
939508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        line[strlen(line)-1] = '\0';
940508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
941508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        /*
942508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root         * Should look like:
943508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root         * /dev/block/loop0 /mnt/obb/fc99df1323fd36424f864dcb76b76d65 ...
944508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root         */
945508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
946508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
947508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        if (!strncmp(mount_path, loopDir, loopDirLen)) {
948508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root            int fd = open(device, O_RDONLY);
949508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root            if (fd >= 0) {
950508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                struct loop_info64 li;
951508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                if (ioctl(fd, LOOP_GET_STATUS64, &li) >= 0) {
952508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                    cli->sendMsg(ResponseCode::AsecListResult,
953508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                            (const char*) li.lo_file_name, false);
954508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                }
955508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                close(fd);
956508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root            }
957508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        }
958508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    }
959508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
960508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    fclose(fp);
961508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    return 0;
962508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root}
963508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
964a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareAvailable(const char *method, bool *avail) {
965a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
966a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
967a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
968a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
969a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
970a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
97199635f6c289fe2528c226403ea215c917ce86037Mike Lockwood    *avail = massStorageAvailable();
972a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
973a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
974a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
975eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehatint VolumeManager::shareEnabled(const char *label, const char *method, bool *enabled) {
976eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    Volume *v = lookupVolume(label);
977eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
978eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    if (!v) {
979eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        errno = ENOENT;
980eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        return -1;
981eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    }
982eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
983eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    if (strcmp(method, "ums")) {
984eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        errno = ENOSYS;
985eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        return -1;
986eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    }
987eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
988eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    if (v->getState() != Volume::State_Shared) {
989eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        *enabled = false;
990b9aed74b146beb7499ebc5775e8ae179d16900efSan Mehat    } else {
991b9aed74b146beb7499ebc5775e8ae179d16900efSan Mehat        *enabled = true;
992eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    }
993eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    return 0;
994eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat}
995eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
996a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::simulate(const char *cmd, const char *arg) {
997a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
998a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!strcmp(cmd, "ums")) {
999a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(arg, "connect")) {
100099635f6c289fe2528c226403ea215c917ce86037Mike Lockwood            notifyUmsAvailable(true);
1001a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else if (!strcmp(arg, "disconnect")) {
100299635f6c289fe2528c226403ea215c917ce86037Mike Lockwood            notifyUmsAvailable(false);
1003a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
1004a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            errno = EINVAL;
1005a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            return -1;
1006a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
1007a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else {
1008a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
1009a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1010a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1011a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
1012a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
1013a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1014a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareVolume(const char *label, const char *method) {
1015a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
1016a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1017a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
1018a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
1019a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1020a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1021a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1022a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    /*
1023a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * Eventually, we'll want to support additional share back-ends,
1024a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * some of which may work while the media is mounted. For now,
1025a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * we just support UMS
1026a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     */
1027a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
1028a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
1029a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1030a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1031a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1032a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
1033a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
1034a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1035a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1036a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
103749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Idle) {
1038a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // You need to unmount manually befoe sharing
103949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
104049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
104149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
104249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
10432dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood    dev_t d = v->getShareDevice();
1044a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
1045a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // This volume does not support raw disk access
1046a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
1047a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1048a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1049a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1050a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
1051a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
1052a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
1053a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
1054a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
1055a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
10560cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file",
10570cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat                   O_WRONLY)) < 0) {
105897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to open ums lunfile (%s)", strerror(errno));
1059a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1060a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1061a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1062a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, nodepath, strlen(nodepath)) < 0) {
106397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));
1064a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
1065a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1066a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1067a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1068a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
1069a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeShared();
1070a28056b38275003895ff5d9576681aca01544822Mike Lockwood    if (mUmsSharingCount++ == 0) {
1071a28056b38275003895ff5d9576681aca01544822Mike Lockwood        FILE* fp;
1072a28056b38275003895ff5d9576681aca01544822Mike Lockwood        mSavedDirtyRatio = -1; // in case we fail
1073a28056b38275003895ff5d9576681aca01544822Mike Lockwood        if ((fp = fopen("/proc/sys/vm/dirty_ratio", "r+"))) {
1074a28056b38275003895ff5d9576681aca01544822Mike Lockwood            char line[16];
1075a28056b38275003895ff5d9576681aca01544822Mike Lockwood            if (fgets(line, sizeof(line), fp) && sscanf(line, "%d", &mSavedDirtyRatio)) {
1076a28056b38275003895ff5d9576681aca01544822Mike Lockwood                fprintf(fp, "%d\n", mUmsDirtyRatio);
1077a28056b38275003895ff5d9576681aca01544822Mike Lockwood            } else {
1078a28056b38275003895ff5d9576681aca01544822Mike Lockwood                SLOGE("Failed to read dirty_ratio (%s)", strerror(errno));
1079a28056b38275003895ff5d9576681aca01544822Mike Lockwood            }
1080a28056b38275003895ff5d9576681aca01544822Mike Lockwood            fclose(fp);
1081a28056b38275003895ff5d9576681aca01544822Mike Lockwood        } else {
1082a28056b38275003895ff5d9576681aca01544822Mike Lockwood            SLOGE("Failed to open /proc/sys/vm/dirty_ratio (%s)", strerror(errno));
1083a28056b38275003895ff5d9576681aca01544822Mike Lockwood        }
1084a28056b38275003895ff5d9576681aca01544822Mike Lockwood    }
1085a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
1086a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
1087a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1088a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::unshareVolume(const char *label, const char *method) {
1089a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
1090a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1091a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
1092a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
1093a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1094a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1095a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1096a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
1097a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
1098a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1099a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1100a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1101a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() != Volume::State_Shared) {
1102a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
1103a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1104a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1105a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1106a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
11070cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat    if ((fd = open("/sys/devices/platform/usb_mass_storage/lun0/file", O_WRONLY)) < 0) {
110897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to open ums lunfile (%s)", strerror(errno));
1109a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1110a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1111a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1112a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char ch = 0;
1113a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, &ch, 1) < 0) {
111497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));
1115a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
1116a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1117a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1118a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1119a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
1120a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeUnshared();
1121a28056b38275003895ff5d9576681aca01544822Mike Lockwood    if (--mUmsSharingCount == 0 && mSavedDirtyRatio != -1) {
1122a28056b38275003895ff5d9576681aca01544822Mike Lockwood        FILE* fp;
1123a28056b38275003895ff5d9576681aca01544822Mike Lockwood        if ((fp = fopen("/proc/sys/vm/dirty_ratio", "r+"))) {
1124a28056b38275003895ff5d9576681aca01544822Mike Lockwood            fprintf(fp, "%d\n", mSavedDirtyRatio);
1125a28056b38275003895ff5d9576681aca01544822Mike Lockwood            fclose(fp);
1126a28056b38275003895ff5d9576681aca01544822Mike Lockwood        } else {
1127a28056b38275003895ff5d9576681aca01544822Mike Lockwood            SLOGE("Failed to open /proc/sys/vm/dirty_ratio (%s)", strerror(errno));
1128a28056b38275003895ff5d9576681aca01544822Mike Lockwood        }
1129a28056b38275003895ff5d9576681aca01544822Mike Lockwood        mSavedDirtyRatio = -1;
1130a28056b38275003895ff5d9576681aca01544822Mike Lockwood    }
1131a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
113249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
113349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
113429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallextern "C" int vold_unmountVol(const char *label) {
113529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    VolumeManager *vm = VolumeManager::Instance();
113629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    return vm->unmountVolume(label, true);
113729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall}
113829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
113929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallextern "C" int vold_getNumDirectVolumes(void) {
114029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    VolumeManager *vm = VolumeManager::Instance();
114129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    return vm->getNumDirectVolumes();
114229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall}
114329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
114429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallint VolumeManager::getNumDirectVolumes(void) {
114529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    VolumeCollection::iterator i;
114629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    int n=0;
114729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
114829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
114929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        if ((*i)->getShareDevice() != (dev_t)0) {
115029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            n++;
115129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        }
115229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    }
115329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    return n;
115429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall}
115529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
115629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallextern "C" int vold_getDirectVolumeList(struct volume_info *vol_list) {
115729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    VolumeManager *vm = VolumeManager::Instance();
115829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    return vm->getDirectVolumeList(vol_list);
115929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall}
116029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
116129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallint VolumeManager::getDirectVolumeList(struct volume_info *vol_list) {
116229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    VolumeCollection::iterator i;
116329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    int n=0;
116429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    dev_t d;
116529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
116629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
116729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        if ((d=(*i)->getShareDevice()) != (dev_t)0) {
116829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            (*i)->getVolInfo(&vol_list[n]);
116929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            snprintf(vol_list[n].blk_dev, sizeof(vol_list[n].blk_dev),
117029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall                     "/dev/block/vold/%d:%d",MAJOR(d), MINOR(d));
117129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            n++;
117229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        }
117329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    }
117429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
117529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    return 0;
117629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall}
117729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
11784ba8948dc16463053e21cda5744f519a555080d0San Mehatint VolumeManager::unmountVolume(const char *label, bool force) {
117949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
118049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
118149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
118249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
118349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
118449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
118549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
1186a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
1187a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
1188a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1189a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1190a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
119149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Mounted) {
119297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Attempt to unmount volume which isn't mounted (%d)\n",
1193a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             v->getState());
119449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
119549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
119649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
119749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
11981a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat    cleanupAsec(v, force);
119988705166ab82057090a070c6d4200c3d9db76f11San Mehat
12004ba8948dc16463053e21cda5744f519a555080d0San Mehat    return v->unmountVol(force);
120149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
120249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
1203a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat/*
1204a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * Looks up a volume by it's label or mount-point
1205a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat */
120649e2bce5b74129c26a35e25d4693cbfe98c4688eSan MehatVolume *VolumeManager::lookupVolume(const char *label) {
120749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    VolumeCollection::iterator i;
120849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
120949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
1210a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (label[0] == '/') {
1211a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getMountpoint()))
1212a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
1213a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
1214a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getLabel()))
1215a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
1216a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
121749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
121849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    return NULL;
121949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
1220a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1221a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatbool VolumeManager::isMountpointMounted(const char *mp)
1222a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat{
1223a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char device[256];
1224a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mount_path[256];
1225a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char rest[256];
1226a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    FILE *fp;
1227a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char line[1024];
1228a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1229a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!(fp = fopen("/proc/mounts", "r"))) {
123097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
1231a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return false;
1232a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
1233a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1234a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    while(fgets(line, sizeof(line), fp)) {
1235a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        line[strlen(line)-1] = '\0';
1236a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
1237a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (!strcmp(mount_path, mp)) {
1238a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            fclose(fp);
1239a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return true;
1240a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
1241a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
1242a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1243a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    fclose(fp);
1244a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return false;
1245a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
1246a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
12471a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehatint VolumeManager::cleanupAsec(Volume *v, bool force) {
12481a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat    while(mActiveContainers->size()) {
12491a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat        AsecIdCollection::iterator it = mActiveContainers->begin();
1250cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        ContainerData* cd = *it;
1251cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        SLOGI("Unmounting ASEC %s (dependant on %s)", cd->id, v->getMountpoint());
1252cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        if (cd->type == ASEC) {
1253cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root            if (unmountAsec(cd->id, force)) {
1254cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root                SLOGE("Failed to unmount ASEC %s (%s)", cd->id, strerror(errno));
1255cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root                return -1;
1256cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root            }
1257cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        } else if (cd->type == OBB) {
1258cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root            if (unmountObb(cd->id, force)) {
1259cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root                SLOGE("Failed to unmount OBB %s (%s)", cd->id, strerror(errno));
1260cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root                return -1;
1261cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root            }
1262cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        } else {
1263cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root            SLOGE("Unknown container type %d!", cd->type);
12641a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat            return -1;
12651a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat        }
12661a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat    }
12671a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat    return 0;
12681a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat}
12691a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat
1270