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