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