VolumeManager.cpp revision 344ca10856f3d3087a3288ce8f91ad83665d93fb
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>
22344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <fts.h>
23344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <unistd.h>
24a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include <sys/stat.h>
25a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include <sys/types.h>
26a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include <sys/mount.h>
27a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
28a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include <linux/kdev_t.h>
29f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
30f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#define LOG_TAG "Vold"
31f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
327b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root#include <openssl/md5.h>
337b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root
34f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <cutils/log.h>
35f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
36fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat#include <sysutils/NetlinkEvent.h>
37fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat
38344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include <private/android_filesystem_config.h>
39344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
40f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "VolumeManager.h"
41ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehat#include "DirectVolume.h"
42a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "ResponseCode.h"
43a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include "Loop.h"
44344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root#include "Ext4.h"
45a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat#include "Fat.h"
46b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat#include "Devmapper.h"
47586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include "Process.h"
48fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat#include "Asec.h"
4929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall#include "cryptfs.h"
5023969931fad6e993832208f099f6eea0f6f76eb5San Mehat
5197f2fc110b2ace7914671c2f5852379bd78922e4Mike Lockwood#define MASS_STORAGE_FILE_PATH  "/sys/class/android_usb/android0/f_mass_storage/lun/file"
5297f2fc110b2ace7914671c2f5852379bd78922e4Mike Lockwood
53f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::sInstance = NULL;
54f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
55f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager *VolumeManager::Instance() {
56f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!sInstance)
57f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        sInstance = new VolumeManager();
58f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return sInstance;
59f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
60f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
61f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::VolumeManager() {
62d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    mDebug = false;
63f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mVolumes = new VolumeCollection();
6488705166ab82057090a070c6d4200c3d9db76f11San Mehat    mActiveContainers = new AsecIdCollection();
65f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mBroadcaster = NULL;
66a28056b38275003895ff5d9576681aca01544822Mike Lockwood    mUmsSharingCount = 0;
67a28056b38275003895ff5d9576681aca01544822Mike Lockwood    mSavedDirtyRatio = -1;
68a28056b38275003895ff5d9576681aca01544822Mike Lockwood    // set dirty ratio to 0 when UMS is active
69a28056b38275003895ff5d9576681aca01544822Mike Lockwood    mUmsDirtyRatio = 0;
703b17005083be230509480ea65ae67c237142fadaKen Sumrall    mVolManagerDisabled = 0;
71f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
72f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
73f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolumeManager::~VolumeManager() {
7488705166ab82057090a070c6d4200c3d9db76f11San Mehat    delete mVolumes;
7588705166ab82057090a070c6d4200c3d9db76f11San Mehat    delete mActiveContainers;
76f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
77f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
78d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehatchar *VolumeManager::asecHash(const char *id, char *buffer, size_t len) {
79acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    static const char* digits = "0123456789abcdef";
80acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root
817b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root    unsigned char sig[MD5_DIGEST_LENGTH];
82d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
83acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    if (buffer == NULL) {
84acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        SLOGE("Destination buffer is NULL");
85acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        errno = ESPIPE;
86acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        return NULL;
87acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    } else if (id == NULL) {
88acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        SLOGE("Source buffer is NULL");
89acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        errno = ESPIPE;
90acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        return NULL;
91acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    } else if (len < MD5_ASCII_LENGTH_PLUS_NULL) {
92acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        SLOGE("Target hash buffer size < %d bytes (%d)",
93acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root                MD5_ASCII_LENGTH_PLUS_NULL, len);
94d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        errno = ESPIPE;
95d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return NULL;
96d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
977b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root
987b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root    MD5(reinterpret_cast<const unsigned char*>(id), strlen(id), sig);
99d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
100acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    char *p = buffer;
1017b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root    for (int i = 0; i < MD5_DIGEST_LENGTH; i++) {
102acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        *p++ = digits[sig[i] >> 4];
103acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root        *p++ = digits[sig[i] & 0x0F];
104d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
105acc9e7dcca8978fc809fa5b4d9b819c515a980ffKenny Root    *p = '\0';
106d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
107d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    return buffer;
108d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat}
109d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
110d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehatvoid VolumeManager::setDebug(bool enable) {
111d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    mDebug = enable;
112d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    VolumeCollection::iterator it;
113d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
114d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        (*it)->setDebug(enable);
115d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
116d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat}
117d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
118f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::start() {
119f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
120f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
121f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
122f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::stop() {
123f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
124f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
125f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
126f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::addVolume(Volume *v) {
127f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mVolumes->push_back(v);
128f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
129f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
130f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
131fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehatvoid VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
132fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    const char *devpath = evt->findParam("DEVPATH");
133f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
134fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat    /* Lookup a volume to handle this device */
135f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator it;
136f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    bool hit = false;
137f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (it = mVolumes->begin(); it != mVolumes->end(); ++it) {
138fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehat        if (!(*it)->handleBlockEvent(evt)) {
139a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
14097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGD("Device '%s' event handled by volume %s\n", devpath, (*it)->getLabel());
141a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
142f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            hit = true;
143f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            break;
144f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        }
145f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
146f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
147f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!hit) {
148a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#ifdef NETLINK_DEBUG
14997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("No volumes handled block event for '%s'", devpath);
150a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#endif
151f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
152f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
153f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
154f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint VolumeManager::listVolumes(SocketClient *cli) {
155f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeCollection::iterator i;
156f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
157f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
158f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        char *buffer;
159f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        asprintf(&buffer, "%s %s %d",
160f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getLabel(), (*i)->getMountpoint(),
161f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat                 (*i)->getState());
162a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        cli->sendMsg(ResponseCode::VolumeListResult, buffer, false);
163f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        free(buffer);
164f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
165a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    cli->sendMsg(ResponseCode::CommandOkay, "Volumes listed.", false);
166f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return 0;
167f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
16849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
169a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::formatVolume(const char *label) {
170a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
171a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
172a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
173a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
174a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
175a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
176a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1773b17005083be230509480ea65ae67c237142fadaKen Sumrall    if (mVolManagerDisabled) {
1783b17005083be230509480ea65ae67c237142fadaKen Sumrall        errno = EBUSY;
1793b17005083be230509480ea65ae67c237142fadaKen Sumrall        return -1;
1803b17005083be230509480ea65ae67c237142fadaKen Sumrall    }
1813b17005083be230509480ea65ae67c237142fadaKen Sumrall
182a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->formatVol();
183a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
184a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
185508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootint VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) {
186508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    char idHash[33];
187508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    if (!asecHash(sourceFile, idHash, sizeof(idHash))) {
188508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        SLOGE("Hash of '%s' failed (%s)", sourceFile, strerror(errno));
189508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        return -1;
190508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    }
191508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
192508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    memset(mountPath, 0, mountPathLen);
193508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    snprintf(mountPath, mountPathLen, "%s/%s", Volume::LOOPDIR, idHash);
194508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
195508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    if (access(mountPath, F_OK)) {
196508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        errno = ENOENT;
197508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        return -1;
198508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    }
199508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
200508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    return 0;
201508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root}
202508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
203a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
20488ac2c06539485942bf414efda2d39647fa1a415San Mehat    char asecFileName[255];
205344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
206344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
207344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id);
208344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
209344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
21088ac2c06539485942bf414efda2d39647fa1a415San Mehat
21188ac2c06539485942bf414efda2d39647fa1a415San Mehat    memset(buffer, 0, maxlen);
21288ac2c06539485942bf414efda2d39647fa1a415San Mehat    if (access(asecFileName, F_OK)) {
21388ac2c06539485942bf414efda2d39647fa1a415San Mehat        errno = ENOENT;
21488ac2c06539485942bf414efda2d39647fa1a415San Mehat        return -1;
21588ac2c06539485942bf414efda2d39647fa1a415San Mehat    }
216a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
2173bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(buffer, maxlen, "%s/%s", Volume::ASECDIR, id);
218a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
219a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
220a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
221736910ca99a40b9add4353bf619e778c40938948Dianne Hackbornint VolumeManager::getAsecFilesystemPath(const char *id, char *buffer, int maxlen) {
222736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn    char asecFileName[255];
223344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
224344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
225344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id);
226344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
227344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
228736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn
229736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn    memset(buffer, 0, maxlen);
230736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn    if (access(asecFileName, F_OK)) {
231736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn        errno = ENOENT;
232736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn        return -1;
233736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn    }
234736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn
235736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn    snprintf(buffer, maxlen, "%s", asecFileName);
236736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn    return 0;
237736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn}
238736910ca99a40b9add4353bf619e778c40938948Dianne Hackborn
239344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootint VolumeManager::createAsec(const char *id, unsigned int numSectors, const char *fstype,
240344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        const char *key, const int ownerUid, bool isExternal) {
241fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    struct asec_superblock sb;
242fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    memset(&sb, 0, sizeof(sb));
243fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
244344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    const bool wantFilesystem = strcmp(fstype, "none");
245344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    bool usingExt4 = false;
246344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (wantFilesystem) {
247344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        usingExt4 = !strcmp(fstype, "ext4");
248344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (usingExt4) {
249344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            sb.c_opts |= ASEC_SB_C_OPTS_EXT4;
250344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        } else if (strcmp(fstype, "fat")) {
251344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            SLOGE("Invalid filesystem type %s", fstype);
252344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            errno = EINVAL;
253344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            return -1;
254344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        }
255344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
256344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
257fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    sb.magic = ASEC_SB_MAGIC;
258fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    sb.ver = ASEC_SB_VER;
259a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
260d31e380bd9689dd9629b510ffe324707e261b439San Mehat    if (numSectors < ((1024*1024)/512)) {
26197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Invalid container size specified (%d sectors)", numSectors);
262d31e380bd9689dd9629b510ffe324707e261b439San Mehat        errno = EINVAL;
263d31e380bd9689dd9629b510ffe324707e261b439San Mehat        return -1;
264d31e380bd9689dd9629b510ffe324707e261b439San Mehat    }
265d31e380bd9689dd9629b510ffe324707e261b439San Mehat
266a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (lookupVolume(id)) {
26797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC id '%s' currently exists", id);
268a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EADDRINUSE;
269a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
270a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
271a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
272a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
273344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
274344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (!findAsec(id, asecFileName, sizeof(asecFileName))) {
275344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
276344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                asecFileName, strerror(errno));
277344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        errno = EADDRINUSE;
278344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
279344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
280344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
281344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    const char *asecDir = isExternal ? Volume::SEC_ASECDIR_EXT : Volume::SEC_ASECDIR_INT;
282344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
283344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", asecDir, id);
284a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
285a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!access(asecFileName, F_OK)) {
28697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC file '%s' currently exists - destroy it first! (%s)",
287344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                asecFileName, strerror(errno));
288a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EADDRINUSE;
289a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
290a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
291a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
292fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    /*
293fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     * Add some headroom
294fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     */
295fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    unsigned fatSize = (((numSectors * 4) / 512) + 1) * 2;
296fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    unsigned numImgSectors = numSectors + fatSize + 2;
297fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
298fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (numImgSectors % 63) {
299fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        numImgSectors += (63 - (numImgSectors % 63));
300fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
301fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
302fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    // Add +1 for our superblock which is at the end
303fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (Loop::createImageFile(asecFileName, numImgSectors + 1)) {
30497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC image file creation failed (%s)", strerror(errno));
305a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
306a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
307a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
308d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    char idHash[33];
309d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!asecHash(id, idHash, sizeof(idHash))) {
31097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
311d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        unlink(asecFileName);
312d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
313d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
314d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
315a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
316d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
31797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
318a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        unlink(asecFileName);
319a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
320a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
321a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
322b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char dmDevice[255];
323b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    bool cleanupDm = false;
324a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
325b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (strcmp(key, "none")) {
326fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        // XXX: This is all we support for now
327fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH;
328d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (Devmapper::create(idHash, loopDevice, key, numImgSectors, dmDevice,
329b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                             sizeof(dmDevice))) {
33097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("ASEC device mapping failed (%s)", strerror(errno));
331b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Loop::destroyByDevice(loopDevice);
332b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            unlink(asecFileName);
333b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            return -1;
334b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
335b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        cleanupDm = true;
336b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
337fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        sb.c_cipher = ASEC_SB_C_CIPHER_NONE;
338b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        strcpy(dmDevice, loopDevice);
339b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
340b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
341fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    /*
342fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     * Drop down the superblock at the end of the file
343fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat     */
344fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
345fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    int sbfd = open(loopDevice, O_RDWR);
346fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (sbfd < 0) {
34797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to open new DM device for superblock write (%s)", strerror(errno));
348fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        if (cleanupDm) {
349d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            Devmapper::destroy(idHash);
350fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        }
351fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
352fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        unlink(asecFileName);
353fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
354fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
355fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
356fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) {
357fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        close(sbfd);
35897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to lseek for superblock (%s)", strerror(errno));
359fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        if (cleanupDm) {
360d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            Devmapper::destroy(idHash);
361fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        }
362fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
363fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        unlink(asecFileName);
364fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
365fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
366fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
367fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (write(sbfd, &sb, sizeof(sb)) != sizeof(sb)) {
368fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        close(sbfd);
36997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to write superblock (%s)", strerror(errno));
370fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        if (cleanupDm) {
371d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            Devmapper::destroy(idHash);
372fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        }
373fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
374fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        unlink(asecFileName);
375fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
376fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
377fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    close(sbfd);
378fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
379344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (wantFilesystem) {
380344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        int formatStatus;
381344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (usingExt4) {
382344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            formatStatus = Ext4::format(dmDevice);
383344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        } else {
384344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            formatStatus = Fat::format(dmDevice, numImgSectors);
385b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
386a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
387344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (formatStatus < 0) {
388344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            SLOGE("ASEC fs format failed (%s)", strerror(errno));
389b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if (cleanupDm) {
390d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                Devmapper::destroy(idHash);
391b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
392eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            Loop::destroyByDevice(loopDevice);
393eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            unlink(asecFileName);
394eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat            return -1;
395eb13a90bb96b329d8e24a6c3d4720ae88451d301San Mehat        }
396344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
397a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        char mountPoint[255];
398a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat
399a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
400344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (mkdir(mountPoint, 0000)) {
401a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            if (errno != EEXIST) {
40297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                SLOGE("Mountpoint creation failed (%s)", strerror(errno));
403a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                if (cleanupDm) {
404d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                    Devmapper::destroy(idHash);
405a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                }
406a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                Loop::destroyByDevice(loopDevice);
407a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                unlink(asecFileName);
408a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat                return -1;
409a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            }
410a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat        }
411a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
412344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        int mountStatus;
413344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (usingExt4) {
414344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            mountStatus = Ext4::doMount(dmDevice, mountPoint, false, false, false);
415344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        } else {
416344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            mountStatus = Fat::doMount(dmDevice, mountPoint, false, false, false, ownerUid, 0, 0000,
417344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                    false);
418344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        }
419344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
420344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (mountStatus) {
42197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("ASEC FAT mount failed (%s)", strerror(errno));
422a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            if (cleanupDm) {
423d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                Devmapper::destroy(idHash);
424a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            }
425a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            Loop::destroyByDevice(loopDevice);
426a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            unlink(asecFileName);
427a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat            return -1;
428b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
429344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
430344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (usingExt4) {
431344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            int dirfd = open(mountPoint, O_DIRECTORY);
432344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            if (dirfd >= 0) {
433344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                if (fchown(dirfd, ownerUid, AID_SYSTEM)
434344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                        || fchmod(dirfd, S_IRUSR | S_IWUSR | S_IXUSR | S_ISGID | S_IRGRP | S_IXGRP)) {
435344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                    SLOGI("Cannot chown/chmod new ASEC mount point %s", mountPoint);
436344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                }
437344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                close(dirfd);
438344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            }
439344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        }
440a1091cb0c448a933068f9120fe6946c09812bfb6San Mehat    } else {
44197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGI("Created raw secure container %s (no filesystem)", id);
442a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
44388705166ab82057090a070c6d4200c3d9db76f11San Mehat
444cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root    mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
445a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
446a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
447a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
448a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::finalizeAsec(const char *id) {
449a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
450a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
451a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
452a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
453344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
454344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id);
455344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
456344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
457a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
458d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    char idHash[33];
459d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!asecHash(id, idHash, sizeof(idHash))) {
46097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
461d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
462d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
463d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
464d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
46597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to finalize %s (%s)", id, strerror(errno));
466a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
467a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
468a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
469344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    unsigned int nr_sec = 0;
470344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    struct asec_superblock sb;
471344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
472344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
473344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
474344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
475344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
4763bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
477344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
478344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    int result = 0;
479344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) {
480344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        result = Ext4::doMount(loopDevice, mountPoint, true, true, true);
481344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    } else {
482344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        result = Fat::doMount(loopDevice, mountPoint, true, true, true, 0, 0, 0227, false);
483344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
484344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
485344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (result) {
48697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC finalize mount failed (%s)", strerror(errno));
487a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
488a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
489a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
490d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (mDebug) {
49197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGD("ASEC %s finalized", id);
492d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
493a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
494a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
495a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
496344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootint VolumeManager::fixupAsecPermissions(const char *id, gid_t gid, const char* filename) {
497344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    char asecFileName[255];
498344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    char loopDevice[255];
499344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    char mountPoint[255];
500344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
501344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (gid < AID_APP) {
502344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Group ID is not in application range");
503344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
504344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
505344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
506344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
507344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id);
508344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
509344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
510344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
511344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    char idHash[33];
512344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (!asecHash(id, idHash, sizeof(idHash))) {
513344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
514344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
515344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
516344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
517344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
518344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Unable fix permissions during lookup on %s (%s)", id, strerror(errno));
519344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
520344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
521344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
522344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    unsigned int nr_sec = 0;
523344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    struct asec_superblock sb;
524344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
525344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
526344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
527344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
528344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
529344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
530344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
531344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    int result = 0;
532344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if ((sb.c_opts & ASEC_SB_C_OPTS_EXT4) == 0) {
533344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return 0;
534344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
535344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
536344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    int ret = Ext4::doMount(loopDevice, mountPoint,
537344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            false /* read-only */,
538344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            true  /* remount */,
539344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            false /* executable */);
540344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (ret) {
541344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Unable remount to fix permissions for %s (%s)", id, strerror(errno));
542344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
543344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
544344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
545344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    char *paths[] = { mountPoint, NULL };
546344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
547344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    FTS *fts = fts_open(paths, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, NULL);
548344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (fts) {
549344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        // Traverse the entire hierarchy and chown to system UID.
550344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        for (FTSENT *ftsent = fts_read(fts); ftsent != NULL; ftsent = fts_read(fts)) {
551344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            // We don't care about the lost+found directory.
552344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            if (!strcmp(ftsent->fts_name, "lost+found")) {
553344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                continue;
554344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            }
555344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
556344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            /*
557344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root             * There can only be one file marked as private right now.
558344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root             * This should be more robust, but it satisfies the requirements
559344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root             * we have for right now.
560344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root             */
561344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            const bool privateFile = !strcmp(ftsent->fts_name, filename);
562344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
563344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            int fd = open(ftsent->fts_accpath, O_NOFOLLOW);
564344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            if (fd < 0) {
565344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                SLOGE("Couldn't open file %s: %s", ftsent->fts_accpath, strerror(errno));
566344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                result = -1;
567344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                continue;
568344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            }
569344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
570344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            result |= fchown(fd, AID_SYSTEM, privateFile? gid : AID_SYSTEM);
571344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
572344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            if (ftsent->fts_info & FTS_D) {
573344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                result |= fchmod(fd, 0711);
574344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            } else {
575344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                result |= fchmod(fd, privateFile ? 0640 : 0644);
576344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            }
577344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            close(fd);
578344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        }
579344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        fts_close(fts);
580344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
581344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        // Finally make the directory readable by everyone.
582344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        int dirfd = open(mountPoint, O_DIRECTORY);
583344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (dirfd < 0 || fchmod(dirfd, 0755)) {
584344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            SLOGE("Couldn't change owner of existing directory %s: %s", mountPoint, strerror(errno));
585344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            result |= -1;
586344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        }
587344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        close(dirfd);
588344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    } else {
589344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        result |= -1;
590344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
591344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
592344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    result |= Ext4::doMount(loopDevice, mountPoint,
593344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            true /* read-only */,
594344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            true /* remount */,
595344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            true /* execute */);
596344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
597344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (result) {
598344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("ASEC fix permissions failed (%s)", strerror(errno));
599344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
600344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
601344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
602344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (mDebug) {
603344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGD("ASEC %s permissions fixed", id);
604344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
605344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    return 0;
606344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root}
607344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
608048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehatint VolumeManager::renameAsec(const char *id1, const char *id2) {
609344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    char asecFilename1[255];
610048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    char *asecFilename2;
611048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    char mountPoint[255];
612048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
613344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    const char *dir;
614344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
615344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id1, asecFilename1, sizeof(asecFilename1), &dir)) {
616344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id1);
617344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
618344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
619344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
620344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    asprintf(&asecFilename2, "%s/%s.asec", dir, id2);
621048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
6223bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id1);
623048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    if (isMountpointMounted(mountPoint)) {
62497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Rename attempt when src mounted");
625048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        errno = EBUSY;
626048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        goto out_err;
627048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
628048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
62996956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id2);
63096956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat    if (isMountpointMounted(mountPoint)) {
63197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Rename attempt when dst mounted");
63296956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat        errno = EBUSY;
63396956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat        goto out_err;
63496956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat    }
63596956ed0e220cb62a4a96136976ded0d8c2d9075San Mehat
636048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    if (!access(asecFilename2, F_OK)) {
63797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Rename attempt when dst exists");
638048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        errno = EADDRINUSE;
639048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        goto out_err;
640048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
641048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
642048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    if (rename(asecFilename1, asecFilename2)) {
64397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Rename of '%s' to '%s' failed (%s)", asecFilename1, asecFilename2, strerror(errno));
644048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat        goto out_err;
645048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    }
646048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
647048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename2);
648048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    return 0;
649048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
650048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehatout_err:
651048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    free(asecFilename2);
652048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat    return -1;
653048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat}
654048b0801fcd6fcfbb8fa812284c751181e4821b8San Mehat
655fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root#define UNMOUNT_RETRIES 5
656fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root#define UNMOUNT_SLEEP_BETWEEN_RETRY_MS (1000 * 1000)
6574ba8948dc16463053e21cda5744f519a555080d0San Mehatint VolumeManager::unmountAsec(const char *id, bool force) {
658a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
659a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
660a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
661344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
662344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id);
663344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
664344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
665344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
6663bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
667a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
668d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    char idHash[33];
669d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!asecHash(id, idHash, sizeof(idHash))) {
67097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
671d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
672d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
673d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
674fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    return unmountLoopImage(id, idHash, asecFileName, mountPoint, force);
675fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root}
676fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
677508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootint VolumeManager::unmountObb(const char *fileName, bool force) {
678fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char mountPoint[255];
679fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
680fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char idHash[33];
681fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (!asecHash(fileName, idHash, sizeof(idHash))) {
682fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Hash of '%s' failed (%s)", fileName, strerror(errno));
683fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
684fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
685fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
686fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::LOOPDIR, idHash);
687fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
688fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    return unmountLoopImage(fileName, idHash, fileName, mountPoint, force);
689fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root}
690fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
691fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Rootint VolumeManager::unmountLoopImage(const char *id, const char *idHash,
692fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        const char *fileName, const char *mountPoint, bool force) {
6930586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (!isMountpointMounted(mountPoint)) {
694fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Unmount request for %s when not mounted", id);
695918e5f9f10b9c1ff929683743ffbf229027ce240Kenny Root        errno = ENOENT;
696b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
697b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
69823969931fad6e993832208f099f6eea0f6f76eb5San Mehat
699b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    int i, rc;
700fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    for (i = 1; i <= UNMOUNT_RETRIES; i++) {
701b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        rc = umount(mountPoint);
702b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (!rc) {
703b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            break;
704a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
705b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (rc && (errno == EINVAL || errno == ENOENT)) {
706fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            SLOGI("Container %s unmounted OK", id);
707b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            rc = 0;
708b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            break;
709a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
710fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGW("%s unmount attempt %d failed (%s)",
7118c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat              id, i, strerror(errno));
7128c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
7134ba8948dc16463053e21cda5744f519a555080d0San Mehat        int action = 0; // default is to just complain
7144ba8948dc16463053e21cda5744f519a555080d0San Mehat
7154ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (force) {
716fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            if (i > (UNMOUNT_RETRIES - 2))
7174ba8948dc16463053e21cda5744f519a555080d0San Mehat                action = 2; // SIGKILL
718fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            else if (i > (UNMOUNT_RETRIES - 3))
7194ba8948dc16463053e21cda5744f519a555080d0San Mehat                action = 1; // SIGHUP
7204ba8948dc16463053e21cda5744f519a555080d0San Mehat        }
7218c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
722586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat        Process::killProcessesWithOpenFiles(mountPoint, action);
723fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
724b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
725b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
726b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    if (rc) {
7274ba8948dc16463053e21cda5744f519a555080d0San Mehat        errno = EBUSY;
72897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to unmount container %s (%s)", id, strerror(errno));
729b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        return -1;
730b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
731b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
73212f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    int retries = 10;
73312f4b89046b54de1bdc188b7057ba77d7566e573San Mehat
73412f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    while(retries--) {
73512f4b89046b54de1bdc188b7057ba77d7566e573San Mehat        if (!rmdir(mountPoint)) {
73612f4b89046b54de1bdc188b7057ba77d7566e573San Mehat            break;
73712f4b89046b54de1bdc188b7057ba77d7566e573San Mehat        }
73812f4b89046b54de1bdc188b7057ba77d7566e573San Mehat
73997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Failed to rmdir %s (%s)", mountPoint, strerror(errno));
740fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        usleep(UNMOUNT_SLEEP_BETWEEN_RETRY_MS);
74112f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    }
74212f4b89046b54de1bdc188b7057ba77d7566e573San Mehat
74312f4b89046b54de1bdc188b7057ba77d7566e573San Mehat    if (!retries) {
74497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Timed out trying to rmdir %s (%s)", mountPoint, strerror(errno));
745f5c61980969a0b49bda37b5dc94ffe675ebd5a5aSan Mehat    }
74688705166ab82057090a070c6d4200c3d9db76f11San Mehat
747d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (Devmapper::destroy(idHash) && errno != ENXIO) {
74897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to destroy devmapper instance (%s)", strerror(errno));
749a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
750a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
751a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
752d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
753a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        Loop::destroyByDevice(loopDevice);
754d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    } else {
755fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGW("Failed to find loop device for {%s} (%s)", fileName, strerror(errno));
756a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
75788705166ab82057090a070c6d4200c3d9db76f11San Mehat
75888705166ab82057090a070c6d4200c3d9db76f11San Mehat    AsecIdCollection::iterator it;
75988705166ab82057090a070c6d4200c3d9db76f11San Mehat    for (it = mActiveContainers->begin(); it != mActiveContainers->end(); ++it) {
760cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        ContainerData* cd = *it;
761cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        if (!strcmp(cd->id, id)) {
76288705166ab82057090a070c6d4200c3d9db76f11San Mehat            free(*it);
76388705166ab82057090a070c6d4200c3d9db76f11San Mehat            mActiveContainers->erase(it);
76488705166ab82057090a070c6d4200c3d9db76f11San Mehat            break;
76588705166ab82057090a070c6d4200c3d9db76f11San Mehat        }
76688705166ab82057090a070c6d4200c3d9db76f11San Mehat    }
76788705166ab82057090a070c6d4200c3d9db76f11San Mehat    if (it == mActiveContainers->end()) {
76897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("mActiveContainers is inconsistent!");
76988705166ab82057090a070c6d4200c3d9db76f11San Mehat    }
770b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    return 0;
771b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat}
772b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
7734ba8948dc16463053e21cda5744f519a555080d0San Mehatint VolumeManager::destroyAsec(const char *id, bool force) {
774b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char asecFileName[255];
775b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char mountPoint[255];
776b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
777344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
778344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id);
779344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
780344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
781344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
78255013f7131ffe094e1c7d929cfc32b3b25096a9bSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
783b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
7840586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (isMountpointMounted(mountPoint)) {
785d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (mDebug) {
78697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGD("Unmounting container before destroy");
787d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        }
7884ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (unmountAsec(id, force)) {
78997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Failed to unmount asec %s for destroy (%s)", id, strerror(errno));
7900586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat            return -1;
7910586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        }
7920586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    }
793a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
7940586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    if (unlink(asecFileName)) {
79597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to unlink asec '%s' (%s)", asecFileName, strerror(errno));
7960586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat        return -1;
7970586d54053ee00e6d6523d4f125282ccb9a24aabSan Mehat    }
798a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
799d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (mDebug) {
80097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGD("ASEC %s destroyed", id);
801d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
802a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
803a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
804a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
805344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootbool VolumeManager::isAsecInDirectory(const char *dir, const char *asecName) const {
806344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    int dirfd = open(dir, O_DIRECTORY);
807344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (dirfd < 0) {
808344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't open internal ASEC dir (%s)", strerror(errno));
809344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
810344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
811344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
812344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    bool ret = false;
813344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
814344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (!faccessat(dirfd, asecName, F_OK, AT_SYMLINK_NOFOLLOW)) {
815344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        ret = true;
816344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
817344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
818344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    close(dirfd);
819344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
820344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    return ret;
821344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root}
822344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
823344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootint VolumeManager::findAsec(const char *id, char *asecPath, size_t asecPathLen,
824344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        const char **directory) const {
825344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    int dirfd, fd;
826344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    const int idLen = strlen(id);
827344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    char *asecName;
828344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
829344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (asprintf(&asecName, "%s.asec", id) < 0) {
830344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't allocate string to write ASEC name");
831344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
832344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
833344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
834344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    const char *dir;
835344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (isAsecInDirectory(Volume::SEC_ASECDIR_INT, asecName)) {
836344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        dir = Volume::SEC_ASECDIR_INT;
837344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    } else if (isAsecInDirectory(Volume::SEC_ASECDIR_EXT, asecName)) {
838344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        dir = Volume::SEC_ASECDIR_EXT;
839344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    } else {
840344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        free(asecName);
841344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
842344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
843344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
844344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (directory != NULL) {
845344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        *directory = dir;
846344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
847344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
848344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (asecPath != NULL) {
849344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        int written = snprintf(asecPath, asecPathLen, "%s/%s", dir, asecName);
850344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        if (written < 0 || static_cast<size_t>(written) >= asecPathLen) {
851344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            free(asecName);
852344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root            return -1;
853344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        }
854344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
855344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
856344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    free(asecName);
857344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    return 0;
858344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root}
859344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
860a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatint VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
861a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char asecFileName[255];
862a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mountPoint[255];
863a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
864344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
865344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Couldn't find ASEC %s", id);
866344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        return -1;
867344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
868344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
8693bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);
870a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
871a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (isMountpointMounted(mountPoint)) {
87297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC %s already mounted", id);
873a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        errno = EBUSY;
874a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
875a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
876a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
877d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    char idHash[33];
878d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (!asecHash(id, idHash, sizeof(idHash))) {
87997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
880d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        return -1;
881d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
8827b18a7b36f61574c0f0bdde0a7409dc36676fa12Kenny Root
883a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char loopDevice[255];
884d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
885d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (Loop::create(idHash, asecFileName, loopDevice, sizeof(loopDevice))) {
88697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("ASEC loop device creation failed (%s)", strerror(errno));
887a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return -1;
888a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
889d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (mDebug) {
89097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGD("New loop device created at %s", loopDevice);
891d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        }
892b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
893d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (mDebug) {
89497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGD("Found active loopback for %s at %s", asecFileName, loopDevice);
895d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        }
896b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    }
897b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat
898b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    char dmDevice[255];
899b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    bool cleanupDm = false;
900fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    int fd;
901fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    unsigned int nr_sec = 0;
902fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    struct asec_superblock sb;
903344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
904344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (Loop::lookupInfo(loopDevice, &sb, &nr_sec)) {
905fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
906fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
907fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
908d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (mDebug) {
90997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
910d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
911fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
91297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
913fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        Loop::destroyByDevice(loopDevice);
914fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        errno = EMEDIUMTYPE;
915fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat        return -1;
916fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    }
917fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    nr_sec--; // We don't want the devmapping to extend onto our superblock
918fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat
919fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (strcmp(key, "none")) {
920d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat        if (Devmapper::lookupActive(idHash, dmDevice, sizeof(dmDevice))) {
921d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            if (Devmapper::create(idHash, loopDevice, key, nr_sec,
922b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                                  dmDevice, sizeof(dmDevice))) {
92397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                SLOGE("ASEC device mapping failed (%s)", strerror(errno));
924b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                Loop::destroyByDevice(loopDevice);
925b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat                return -1;
926b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
927d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            if (mDebug) {
92897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                SLOGD("New devmapper instance created at %s", dmDevice);
929d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            }
930b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        } else {
931d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            if (mDebug) {
93297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                SLOGD("Found active devmapper for %s at %s", asecFileName, dmDevice);
933d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            }
934b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
935b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        cleanupDm = true;
936b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat    } else {
937b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        strcpy(dmDevice, loopDevice);
938a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
939a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
940344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (mkdir(mountPoint, 0000)) {
941b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (errno != EEXIST) {
94297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Mountpoint creation failed (%s)", strerror(errno));
943b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            if (cleanupDm) {
944d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat                Devmapper::destroy(idHash);
945b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            }
946b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            Loop::destroyByDevice(loopDevice);
947b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat            return -1;
948b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
949a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
950a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
951344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    int result;
952344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (sb.c_opts & ASEC_SB_C_OPTS_EXT4) {
953344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        result = Ext4::doMount(dmDevice, mountPoint, true, false, true);
954344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    } else {
955344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        result = Fat::doMount(dmDevice, mountPoint, true, false, true, ownerUid, 0, 0222, false);
956344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    }
957344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root
958344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (result) {
95997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("ASEC mount failed (%s)", strerror(errno));
960b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        if (cleanupDm) {
961d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            Devmapper::destroy(idHash);
962b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        }
963b78a32c1d5eeb243bdac0eaf18effb1897f1ee67San Mehat        Loop::destroyByDevice(loopDevice);
964a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return -1;
965a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
966a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
967cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root    mActiveContainers->push_back(new ContainerData(strdup(id), ASEC));
968d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (mDebug) {
96997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGD("ASEC %s mounted", id);
970d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
971a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return 0;
972a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
973a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
974fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root/**
975fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root * Mounts an image file <code>img</code>.
976fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root */
977508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootint VolumeManager::mountObb(const char *img, const char *key, int ownerUid) {
978fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char mountPoint[255];
979fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
980fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char idHash[33];
981fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (!asecHash(img, idHash, sizeof(idHash))) {
982fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Hash of '%s' failed (%s)", img, strerror(errno));
983fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
984fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
985fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
986fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::LOOPDIR, idHash);
987fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
988fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (isMountpointMounted(mountPoint)) {
989fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Image %s already mounted", img);
990fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        errno = EBUSY;
991fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
992fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
993fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
994fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char loopDevice[255];
995fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (Loop::lookupActive(idHash, loopDevice, sizeof(loopDevice))) {
996fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (Loop::create(idHash, img, loopDevice, sizeof(loopDevice))) {
997fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            SLOGE("Image loop device creation failed (%s)", strerror(errno));
998fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            return -1;
999fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
1000fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (mDebug) {
1001fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            SLOGD("New loop device created at %s", loopDevice);
1002fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
1003fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    } else {
1004fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (mDebug) {
1005fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            SLOGD("Found active loopback for %s at %s", img, loopDevice);
1006fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
1007fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1008fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1009fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    char dmDevice[255];
1010fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    bool cleanupDm = false;
1011fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    int fd;
1012fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    unsigned int nr_sec = 0;
1013fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1014fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if ((fd = open(loopDevice, O_RDWR)) < 0) {
1015fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Failed to open loopdevice (%s)", strerror(errno));
1016fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        Loop::destroyByDevice(loopDevice);
1017fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
1018fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1019fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1020fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
1021fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Failed to get loop size (%s)", strerror(errno));
1022fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        Loop::destroyByDevice(loopDevice);
1023fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        close(fd);
1024fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
1025fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1026fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1027fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    close(fd);
1028fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1029fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (strcmp(key, "none")) {
1030fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (Devmapper::lookupActive(idHash, dmDevice, sizeof(dmDevice))) {
1031fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            if (Devmapper::create(idHash, loopDevice, key, nr_sec,
1032fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                                  dmDevice, sizeof(dmDevice))) {
1033fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                SLOGE("ASEC device mapping failed (%s)", strerror(errno));
1034fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                Loop::destroyByDevice(loopDevice);
1035fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                return -1;
1036fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            }
1037fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            if (mDebug) {
1038fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                SLOGD("New devmapper instance created at %s", dmDevice);
1039fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            }
1040fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        } else {
1041fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            if (mDebug) {
1042fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                SLOGD("Found active devmapper for %s at %s", img, dmDevice);
1043fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            }
1044fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
1045fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        cleanupDm = true;
1046fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    } else {
1047fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        strcpy(dmDevice, loopDevice);
1048fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1049fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1050fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (mkdir(mountPoint, 0755)) {
1051fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (errno != EEXIST) {
1052fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            SLOGE("Mountpoint creation failed (%s)", strerror(errno));
1053fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            if (cleanupDm) {
1054fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                Devmapper::destroy(idHash);
1055fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            }
1056fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            Loop::destroyByDevice(loopDevice);
1057fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            return -1;
1058fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
1059fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1060fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1061a3e06084564c86ff618c40f185f3676b8b629b94Kenny Root    if (Fat::doMount(dmDevice, mountPoint, true, false, true, ownerUid, 0,
1062fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root                     0227, false)) {
1063fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGE("Image mount failed (%s)", strerror(errno));
1064fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        if (cleanupDm) {
1065fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root            Devmapper::destroy(idHash);
1066fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        }
1067fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        Loop::destroyByDevice(loopDevice);
1068fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        return -1;
1069fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1070fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
1071cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root    mActiveContainers->push_back(new ContainerData(strdup(img), OBB));
1072fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    if (mDebug) {
1073fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root        SLOGD("Image %s mounted", img);
1074fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    }
1075fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root    return 0;
1076fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root}
1077fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
107849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint VolumeManager::mountVolume(const char *label) {
107949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
108049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
108149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
108249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
108349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
108449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
108549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
1086a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return v->mountVol();
1087a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
1088a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1089508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootint VolumeManager::listMountedObbs(SocketClient* cli) {
1090508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    char device[256];
1091508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    char mount_path[256];
1092508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    char rest[256];
1093508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    FILE *fp;
1094508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    char line[1024];
1095508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
1096508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    if (!(fp = fopen("/proc/mounts", "r"))) {
1097508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
1098508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        return -1;
1099508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    }
1100508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
1101508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    // Create a string to compare against that has a trailing slash
1102508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    int loopDirLen = sizeof(Volume::LOOPDIR);
1103508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    char loopDir[loopDirLen + 2];
1104508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    strcpy(loopDir, Volume::LOOPDIR);
1105508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    loopDir[loopDirLen++] = '/';
1106508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    loopDir[loopDirLen] = '\0';
1107508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
1108508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    while(fgets(line, sizeof(line), fp)) {
1109508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        line[strlen(line)-1] = '\0';
1110508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
1111508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        /*
1112508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root         * Should look like:
1113508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root         * /dev/block/loop0 /mnt/obb/fc99df1323fd36424f864dcb76b76d65 ...
1114508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root         */
1115508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
1116508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
1117508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        if (!strncmp(mount_path, loopDir, loopDirLen)) {
1118508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root            int fd = open(device, O_RDONLY);
1119508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root            if (fd >= 0) {
1120508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                struct loop_info64 li;
1121508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                if (ioctl(fd, LOOP_GET_STATUS64, &li) >= 0) {
1122508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                    cli->sendMsg(ResponseCode::AsecListResult,
1123508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                            (const char*) li.lo_file_name, false);
1124508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                }
1125508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root                close(fd);
1126508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root            }
1127508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root        }
1128508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    }
1129508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
1130508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    fclose(fp);
1131508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root    return 0;
1132508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root}
1133508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root
1134eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehatint VolumeManager::shareEnabled(const char *label, const char *method, bool *enabled) {
1135eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    Volume *v = lookupVolume(label);
1136eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
1137eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    if (!v) {
1138eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        errno = ENOENT;
1139eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        return -1;
1140eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    }
1141eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
1142eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    if (strcmp(method, "ums")) {
1143eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        errno = ENOSYS;
1144eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        return -1;
1145eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    }
1146eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
1147eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    if (v->getState() != Volume::State_Shared) {
1148eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat        *enabled = false;
1149b9aed74b146beb7499ebc5775e8ae179d16900efSan Mehat    } else {
1150b9aed74b146beb7499ebc5775e8ae179d16900efSan Mehat        *enabled = true;
1151eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    }
1152eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    return 0;
1153eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat}
1154eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat
1155a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::shareVolume(const char *label, const char *method) {
1156a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
1157a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1158a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
1159a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
1160a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1161a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1162a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1163a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    /*
1164a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * Eventually, we'll want to support additional share back-ends,
1165a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * some of which may work while the media is mounted. For now,
1166a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     * we just support UMS
1167a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat     */
1168a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
1169a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
1170a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1171a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1172a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1173a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
1174a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
1175a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1176a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1177a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
117849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Idle) {
1179a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // You need to unmount manually befoe sharing
118049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
118149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
118249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
118349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
11843b17005083be230509480ea65ae67c237142fadaKen Sumrall    if (mVolManagerDisabled) {
11853b17005083be230509480ea65ae67c237142fadaKen Sumrall        errno = EBUSY;
11863b17005083be230509480ea65ae67c237142fadaKen Sumrall        return -1;
11873b17005083be230509480ea65ae67c237142fadaKen Sumrall    }
11883b17005083be230509480ea65ae67c237142fadaKen Sumrall
11892dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood    dev_t d = v->getShareDevice();
1190a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if ((MAJOR(d) == 0) && (MINOR(d) == 0)) {
1191a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // This volume does not support raw disk access
1192a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
1193a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1194a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1195a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1196a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
1197a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char nodepath[255];
1198a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(nodepath,
1199a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             sizeof(nodepath), "/dev/block/vold/%d:%d",
1200a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             MAJOR(d), MINOR(d));
1201a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
120297f2fc110b2ace7914671c2f5852379bd78922e4Mike Lockwood    if ((fd = open(MASS_STORAGE_FILE_PATH, O_WRONLY)) < 0) {
120397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to open ums lunfile (%s)", strerror(errno));
1204a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1205a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1206a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1207a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, nodepath, strlen(nodepath)) < 0) {
120897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));
1209a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
1210a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1211a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1212a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1213a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
1214a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeShared();
1215a28056b38275003895ff5d9576681aca01544822Mike Lockwood    if (mUmsSharingCount++ == 0) {
1216a28056b38275003895ff5d9576681aca01544822Mike Lockwood        FILE* fp;
1217a28056b38275003895ff5d9576681aca01544822Mike Lockwood        mSavedDirtyRatio = -1; // in case we fail
1218a28056b38275003895ff5d9576681aca01544822Mike Lockwood        if ((fp = fopen("/proc/sys/vm/dirty_ratio", "r+"))) {
1219a28056b38275003895ff5d9576681aca01544822Mike Lockwood            char line[16];
1220a28056b38275003895ff5d9576681aca01544822Mike Lockwood            if (fgets(line, sizeof(line), fp) && sscanf(line, "%d", &mSavedDirtyRatio)) {
1221a28056b38275003895ff5d9576681aca01544822Mike Lockwood                fprintf(fp, "%d\n", mUmsDirtyRatio);
1222a28056b38275003895ff5d9576681aca01544822Mike Lockwood            } else {
1223a28056b38275003895ff5d9576681aca01544822Mike Lockwood                SLOGE("Failed to read dirty_ratio (%s)", strerror(errno));
1224a28056b38275003895ff5d9576681aca01544822Mike Lockwood            }
1225a28056b38275003895ff5d9576681aca01544822Mike Lockwood            fclose(fp);
1226a28056b38275003895ff5d9576681aca01544822Mike Lockwood        } else {
1227a28056b38275003895ff5d9576681aca01544822Mike Lockwood            SLOGE("Failed to open /proc/sys/vm/dirty_ratio (%s)", strerror(errno));
1228a28056b38275003895ff5d9576681aca01544822Mike Lockwood        }
1229a28056b38275003895ff5d9576681aca01544822Mike Lockwood    }
1230a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
1231a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
1232a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1233a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint VolumeManager::unshareVolume(const char *label, const char *method) {
1234a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    Volume *v = lookupVolume(label);
1235a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1236a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!v) {
1237a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOENT;
1238a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1239a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1240a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1241a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (strcmp(method, "ums")) {
1242a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENOSYS;
1243a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1244a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1245a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1246a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() != Volume::State_Shared) {
1247a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
1248a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1249a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1250a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1251a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd;
125297f2fc110b2ace7914671c2f5852379bd78922e4Mike Lockwood    if ((fd = open(MASS_STORAGE_FILE_PATH, O_WRONLY)) < 0) {
125397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to open ums lunfile (%s)", strerror(errno));
1254a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1255a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1256a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1257a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char ch = 0;
1258a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, &ch, 1) < 0) {
125997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to write to ums lunfile (%s)", strerror(errno));
1260a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
1261a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1262a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1263a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1264a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
1265a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    v->handleVolumeUnshared();
1266a28056b38275003895ff5d9576681aca01544822Mike Lockwood    if (--mUmsSharingCount == 0 && mSavedDirtyRatio != -1) {
1267a28056b38275003895ff5d9576681aca01544822Mike Lockwood        FILE* fp;
1268a28056b38275003895ff5d9576681aca01544822Mike Lockwood        if ((fp = fopen("/proc/sys/vm/dirty_ratio", "r+"))) {
1269a28056b38275003895ff5d9576681aca01544822Mike Lockwood            fprintf(fp, "%d\n", mSavedDirtyRatio);
1270a28056b38275003895ff5d9576681aca01544822Mike Lockwood            fclose(fp);
1271a28056b38275003895ff5d9576681aca01544822Mike Lockwood        } else {
1272a28056b38275003895ff5d9576681aca01544822Mike Lockwood            SLOGE("Failed to open /proc/sys/vm/dirty_ratio (%s)", strerror(errno));
1273a28056b38275003895ff5d9576681aca01544822Mike Lockwood        }
1274a28056b38275003895ff5d9576681aca01544822Mike Lockwood        mSavedDirtyRatio = -1;
1275a28056b38275003895ff5d9576681aca01544822Mike Lockwood    }
1276a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
127749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
127849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
12793b17005083be230509480ea65ae67c237142fadaKen Sumrallextern "C" int vold_disableVol(const char *label) {
128029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    VolumeManager *vm = VolumeManager::Instance();
12813b17005083be230509480ea65ae67c237142fadaKen Sumrall    vm->disableVolumeManager();
12823b17005083be230509480ea65ae67c237142fadaKen Sumrall    vm->unshareVolume(label, "ums");
12830b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall    return vm->unmountVolume(label, true, false);
128429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall}
128529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
128629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallextern "C" int vold_getNumDirectVolumes(void) {
128729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    VolumeManager *vm = VolumeManager::Instance();
128829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    return vm->getNumDirectVolumes();
128929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall}
129029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
129129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallint VolumeManager::getNumDirectVolumes(void) {
129229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    VolumeCollection::iterator i;
129329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    int n=0;
129429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
129529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
129629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        if ((*i)->getShareDevice() != (dev_t)0) {
129729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            n++;
129829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        }
129929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    }
130029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    return n;
130129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall}
130229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
130329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallextern "C" int vold_getDirectVolumeList(struct volume_info *vol_list) {
130429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    VolumeManager *vm = VolumeManager::Instance();
130529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    return vm->getDirectVolumeList(vol_list);
130629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall}
130729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
130829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrallint VolumeManager::getDirectVolumeList(struct volume_info *vol_list) {
130929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    VolumeCollection::iterator i;
131029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    int n=0;
131129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    dev_t d;
131229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
131329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
131429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        if ((d=(*i)->getShareDevice()) != (dev_t)0) {
131529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            (*i)->getVolInfo(&vol_list[n]);
131629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            snprintf(vol_list[n].blk_dev, sizeof(vol_list[n].blk_dev),
131729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall                     "/dev/block/vold/%d:%d",MAJOR(d), MINOR(d));
131829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            n++;
131929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        }
132029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    }
132129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
132229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    return 0;
132329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall}
132429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
13250b8b59719357fb80c330442787f7d5b1e332263bKen Sumrallint VolumeManager::unmountVolume(const char *label, bool force, bool revert) {
132649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    Volume *v = lookupVolume(label);
132749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
132849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (!v) {
132949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = ENOENT;
133049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
133149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
133249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
1333a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (v->getState() == Volume::State_NoMedia) {
1334a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
1335a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
1336a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
1337a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
133849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (v->getState() != Volume::State_Mounted) {
133997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Attempt to unmount volume which isn't mounted (%d)\n",
1340a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             v->getState());
134149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        errno = EBUSY;
1342319b1043bbbd410aa2d572d88b5936f26072d026Ken Sumrall        return UNMOUNT_NOT_MOUNTED_ERR;
134349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
134449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
13451a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat    cleanupAsec(v, force);
134688705166ab82057090a070c6d4200c3d9db76f11San Mehat
13470b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall    return v->unmountVol(force, revert);
134849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
134949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
1350a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat/*
1351a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat * Looks up a volume by it's label or mount-point
1352a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat */
135349e2bce5b74129c26a35e25d4693cbfe98c4688eSan MehatVolume *VolumeManager::lookupVolume(const char *label) {
135449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    VolumeCollection::iterator i;
135549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
135649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
1357a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (label[0] == '/') {
1358a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getMountpoint()))
1359a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
1360a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
1361a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (!strcmp(label, (*i)->getLabel()))
1362a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                return (*i);
1363a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
136449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
136549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    return NULL;
136649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
1367a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1368a19b250bd273455933ca3502cf2c2e0a803aff77San Mehatbool VolumeManager::isMountpointMounted(const char *mp)
1369a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat{
1370a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char device[256];
1371a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char mount_path[256];
1372a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char rest[256];
1373a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    FILE *fp;
1374a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    char line[1024];
1375a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1376a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    if (!(fp = fopen("/proc/mounts", "r"))) {
137797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
1378a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        return false;
1379a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
1380a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1381a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    while(fgets(line, sizeof(line), fp)) {
1382a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        line[strlen(line)-1] = '\0';
1383a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
1384a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        if (!strcmp(mount_path, mp)) {
1385a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            fclose(fp);
1386a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat            return true;
1387a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat        }
1388a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    }
1389a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
1390a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    fclose(fp);
1391a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat    return false;
1392a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat}
1393a19b250bd273455933ca3502cf2c2e0a803aff77San Mehat
13941a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehatint VolumeManager::cleanupAsec(Volume *v, bool force) {
13951a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat    while(mActiveContainers->size()) {
13961a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat        AsecIdCollection::iterator it = mActiveContainers->begin();
1397cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        ContainerData* cd = *it;
1398cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        SLOGI("Unmounting ASEC %s (dependant on %s)", cd->id, v->getMountpoint());
1399cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        if (cd->type == ASEC) {
1400cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root            if (unmountAsec(cd->id, force)) {
1401cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root                SLOGE("Failed to unmount ASEC %s (%s)", cd->id, strerror(errno));
1402cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root                return -1;
1403cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root            }
1404cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        } else if (cd->type == OBB) {
1405cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root            if (unmountObb(cd->id, force)) {
1406cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root                SLOGE("Failed to unmount OBB %s (%s)", cd->id, strerror(errno));
1407cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root                return -1;
1408cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root            }
1409cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root        } else {
1410cbacf78eff70bd43bb899e164ec2ab409bc0904cKenny Root            SLOGE("Unknown container type %d!", cd->type);
14111a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat            return -1;
14121a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat        }
14131a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat    }
14141a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat    return 0;
14151a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat}
14161a06edaf4db4e9c520624bcc06e0e13ee470d90eSan Mehat
1417