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 1749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <stdlib.h> 18f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <string.h> 1949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <dirent.h> 2049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <errno.h> 2149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <fcntl.h> 2249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 2349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <sys/types.h> 2449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <sys/stat.h> 2549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <sys/types.h> 2649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <sys/mman.h> 27a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include <sys/mount.h> 2829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall#include <sys/param.h> 29a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 30a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include <linux/kdev_t.h> 31a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 32a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include <cutils/properties.h> 33a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 342a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat#include <diskconfig/diskconfig.h> 35f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 369092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood#include <private/android_filesystem_config.h> 379092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood 38f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#define LOG_TAG "Vold" 39f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 40ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey#include <cutils/fs.h> 41f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <cutils/log.h> 42f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 430de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey#include <string> 440de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 45f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "Volume.h" 46a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "VolumeManager.h" 47a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "ResponseCode.h" 48bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include "Fat.h" 49586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include "Process.h" 5029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall#include "cryptfs.h" 51f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 52a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatextern "C" void dos_partition_dec(void const *pp, struct dos_partition *d); 53a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatextern "C" void dos_partition_enc(void *pp, struct dos_partition *d); 5449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 553bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 563bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat/* 57ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey * Media directory - stuff that only media_rw user can see 583bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat */ 59ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkeyconst char *Volume::MEDIA_DIR = "/mnt/media_rw"; 603bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 613bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat/* 62ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey * Fuse directory - location where fuse wrapped filesystems go 633bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat */ 64ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkeyconst char *Volume::FUSE_DIR = "/storage"; 653bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 663bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat/* 67344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * Path to external storage where *only* root can access ASEC image files 683bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat */ 69344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootconst char *Volume::SEC_ASECDIR_EXT = "/mnt/secure/asec"; 703bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 713bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat/* 72344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * Path to internal storage where *only* root can access ASEC image files 73344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root */ 74344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootconst char *Volume::SEC_ASECDIR_INT = "/data/app-asec"; 758c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey 76344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root/* 773bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat * Path to where secure containers are mounted 783bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat */ 793bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatconst char *Volume::ASECDIR = "/mnt/asec"; 803bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 81fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root/* 82508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root * Path to where OBBs are mounted 83fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root */ 84508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootconst char *Volume::LOOPDIR = "/mnt/obb"; 85fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root 860de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkeyconst char *Volume::BLKID_PATH = "/system/bin/blkid"; 870de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 88a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatstatic const char *stateToStr(int state) { 89a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (state == Volume::State_Init) 90a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return "Initializing"; 91a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat else if (state == Volume::State_NoMedia) 92a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return "No-Media"; 93a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat else if (state == Volume::State_Idle) 94a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return "Idle-Unmounted"; 95a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat else if (state == Volume::State_Pending) 96a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return "Pending"; 97a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat else if (state == Volume::State_Mounted) 98a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return "Mounted"; 99a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat else if (state == Volume::State_Unmounting) 100a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return "Unmounting"; 101a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat else if (state == Volume::State_Checking) 102a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return "Checking"; 103a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat else if (state == Volume::State_Formatting) 104a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return "Formatting"; 105a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat else if (state == Volume::State_Shared) 106a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return "Shared-Unmounted"; 107a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat else if (state == Volume::State_SharedMnt) 108a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return "Shared-Mounted"; 109a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat else 110a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return "Unknown-Error"; 111a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 11249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 113ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff SharkeyVolume::Volume(VolumeManager *vm, const fstab_rec* rec, int flags) { 114a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat mVm = vm; 115d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat mDebug = false; 116ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey mLabel = strdup(rec->label); 1170de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey mUuid = NULL; 1180de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey mUserLabel = NULL; 119f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat mState = Volume::State_Init; 120ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey mFlags = flags; 121a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat mCurrentlyMountedKdev = -1; 122ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey mPartIdx = rec->partnum; 123507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer mRetryMount = false; 124f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 125f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 126f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolume::~Volume() { 127f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat free(mLabel); 1280de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey free(mUuid); 1290de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey free(mUserLabel); 130cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat} 131cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat 132d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehatvoid Volume::setDebug(bool enable) { 133d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat mDebug = enable; 134d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat} 135d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 136a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatdev_t Volume::getDiskDevice() { 137a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return MKDEV(0, 0); 138a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}; 139a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1402dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwooddev_t Volume::getShareDevice() { 1412dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood return getDiskDevice(); 1422dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood} 1432dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood 144a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid Volume::handleVolumeShared() { 145a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 146a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 147a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid Volume::handleVolumeUnshared() { 148a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 149a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 1503e971277db0d87652af5622c989233e7159ab909Mark Salyzynint Volume::handleBlockEvent(NetlinkEvent * /*evt*/) { 151f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat errno = ENOSYS; 152f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat return -1; 153f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 154f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 1550de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkeyvoid Volume::setUuid(const char* uuid) { 1560de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey char msg[256]; 1570de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 1580de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey if (mUuid) { 1590de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey free(mUuid); 1600de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey } 1610de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 1620de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey if (uuid) { 1630de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey mUuid = strdup(uuid); 1640de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey snprintf(msg, sizeof(msg), "%s %s \"%s\"", getLabel(), 1650de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey getFuseMountpoint(), mUuid); 1660de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey } else { 1670de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey mUuid = NULL; 1680de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey snprintf(msg, sizeof(msg), "%s %s", getLabel(), getFuseMountpoint()); 1690de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey } 1700de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 1710de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeUuidChange, msg, 1720de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey false); 1730de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey} 1740de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 1750de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkeyvoid Volume::setUserLabel(const char* userLabel) { 1760de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey char msg[256]; 1770de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 1780de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey if (mUserLabel) { 1790de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey free(mUserLabel); 1800de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey } 1810de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 1820de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey if (userLabel) { 1830de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey mUserLabel = strdup(userLabel); 1840de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey snprintf(msg, sizeof(msg), "%s %s \"%s\"", getLabel(), 1850de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey getFuseMountpoint(), mUserLabel); 1860de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey } else { 1870de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey mUserLabel = NULL; 1880de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey snprintf(msg, sizeof(msg), "%s %s", getLabel(), getFuseMountpoint()); 1890de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey } 1900de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 1910de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeUserLabelChange, 1920de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey msg, false); 1930de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey} 1940de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 195f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatvoid Volume::setState(int state) { 196a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char msg[255]; 197a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat int oldState = mState; 198a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 199a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (oldState == state) { 20097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("Duplicate state (%d)\n", state); 201a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return; 202a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 203a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 204507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer if ((oldState == Volume::State_Pending) && (state != Volume::State_Idle)) { 205507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer mRetryMount = false; 206507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer } 207507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer 208f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat mState = state; 209a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 21097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("Volume %s state changing %d (%s) -> %d (%s)", mLabel, 211a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat oldState, stateToStr(oldState), mState, stateToStr(mState)); 212a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat snprintf(msg, sizeof(msg), 213a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat "Volume %s %s state changed from %d (%s) to %d (%s)", getLabel(), 214ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey getFuseMountpoint(), oldState, stateToStr(oldState), mState, 215a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat stateToStr(mState)); 216a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 217a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange, 218a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat msg, false); 219f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 22049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 221dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehatint Volume::createDeviceNode(const char *path, int major, int minor) { 222dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat mode_t mode = 0660 | S_IFBLK; 223dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat dev_t dev = (major << 8) | minor; 224dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat if (mknod(path, mode, dev) < 0) { 225dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat if (errno != EEXIST) { 226dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat return -1; 227dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat } 228dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat } 229dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat return 0; 230dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat} 231dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat 2329caab76c6b5aefdeeb1715a3695491ca793b8c18Ken Sumrallint Volume::formatVol(bool wipe) { 23349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 234a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (getState() == Volume::State_NoMedia) { 235a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = ENODEV; 23649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return -1; 237a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } else if (getState() != Volume::State_Idle) { 238a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = EBUSY; 239a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 240a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 241a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 242a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (isMountpointMounted(getMountpoint())) { 24397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("Volume is idle but appears to be mounted - fixing"); 244a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat setState(Volume::State_Mounted); 245a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat // mCurrentlyMountedKdev = XXX 246a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = EBUSY; 247a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 248a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 249a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 250a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood bool formatEntireDevice = (mPartIdx == -1); 251a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char devicePath[255]; 252a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat dev_t diskNode = getDiskDevice(); 253cc21d6ea5881a9f576296317bde8d818b3e4fc01Blair Prescott dev_t partNode = 254cc21d6ea5881a9f576296317bde8d818b3e4fc01Blair Prescott MKDEV(MAJOR(diskNode), 255cc21d6ea5881a9f576296317bde8d818b3e4fc01Blair Prescott MINOR(diskNode) + (formatEntireDevice ? 1 : mPartIdx)); 256a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 2572a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat setState(Volume::State_Formatting); 258a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 25964382de1f93b84ca59f607da4b4fdbd77f1af67dChih-Wei Huang int ret = -1; 260a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood // Only initialize the MBR if we are formatting the entire device 261a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood if (formatEntireDevice) { 262a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood sprintf(devicePath, "/dev/block/vold/%d:%d", 263346c5b20cbbced7edacf240015c4a89e5b2ca44fColin Cross major(diskNode), minor(diskNode)); 264a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood 265a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood if (initializeMbr(devicePath)) { 266a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood SLOGE("Failed to initialize MBR (%s)", strerror(errno)); 267a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood goto err; 268a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood } 269a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 270a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 271a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat sprintf(devicePath, "/dev/block/vold/%d:%d", 272346c5b20cbbced7edacf240015c4a89e5b2ca44fColin Cross major(partNode), minor(partNode)); 273a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 274a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood if (mDebug) { 275a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood SLOGI("Formatting volume %s (%s)", getLabel(), devicePath); 276a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood } 277a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood 2789caab76c6b5aefdeeb1715a3695491ca793b8c18Ken Sumrall if (Fat::format(devicePath, 0, wipe)) { 27997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Failed to format (%s)", strerror(errno)); 280a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat goto err; 281a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 282a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 28364382de1f93b84ca59f607da4b4fdbd77f1af67dChih-Wei Huang ret = 0; 28464382de1f93b84ca59f607da4b4fdbd77f1af67dChih-Wei Huang 285a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehaterr: 28664382de1f93b84ca59f607da4b4fdbd77f1af67dChih-Wei Huang setState(Volume::State_Idle); 28764382de1f93b84ca59f607da4b4fdbd77f1af67dChih-Wei Huang return ret; 288a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 289a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 290a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatbool Volume::isMountpointMounted(const char *path) { 291a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char device[256]; 292a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char mount_path[256]; 293a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char rest[256]; 294a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat FILE *fp; 295a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char line[1024]; 296a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 297a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (!(fp = fopen("/proc/mounts", "r"))) { 29897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Error opening /proc/mounts (%s)", strerror(errno)); 299a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return false; 30049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 30149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 302a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat while(fgets(line, sizeof(line), fp)) { 303a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat line[strlen(line)-1] = '\0'; 304a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat sscanf(line, "%255s %255s %255s\n", device, mount_path, rest); 305a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (!strcmp(mount_path, path)) { 306a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat fclose(fp); 307a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return true; 308a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 309a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 310dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat 311a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat fclose(fp); 312a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return false; 313a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 314a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 315a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint Volume::mountVol() { 316a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat dev_t deviceNodes[4]; 317a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat int n, i, rc = 0; 318a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char errmsg[255]; 319ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey 320ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey int flags = getFlags(); 321ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey bool providesAsec = (flags & VOL_PROVIDES_ASEC) != 0; 322ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey 323ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey // TODO: handle "bind" style mounts, for emulated storage 324ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey 32529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall char decrypt_state[PROPERTY_VALUE_MAX]; 32629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall char crypto_state[PROPERTY_VALUE_MAX]; 32729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall char encrypt_progress[PROPERTY_VALUE_MAX]; 32829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 32929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall property_get("vold.decrypt", decrypt_state, ""); 33029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall property_get("vold.encrypt_progress", encrypt_progress, ""); 33129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 33229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall /* Don't try to mount the volumes if we have not yet entered the disk password 33329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * or are in the process of encrypting. 33429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall */ 33529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall if ((getState() == Volume::State_NoMedia) || 336ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey ((!strcmp(decrypt_state, "1") || encrypt_progress[0]) && providesAsec)) { 337a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat snprintf(errmsg, sizeof(errmsg), 338a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat "Volume %s %s mount failed - no media", 339ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey getLabel(), getFuseMountpoint()); 340a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat mVm->getBroadcaster()->sendBroadcast( 341a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat ResponseCode::VolumeMountFailedNoMedia, 342a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errmsg, false); 343a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = ENODEV; 344a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 345a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } else if (getState() != Volume::State_Idle) { 346a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = EBUSY; 347507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer if (getState() == Volume::State_Pending) { 348507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer mRetryMount = true; 349507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer } 35049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return -1; 35149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 35249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 353a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (isMountpointMounted(getMountpoint())) { 35497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("Volume is idle but appears to be mounted - fixing"); 355a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat setState(Volume::State_Mounted); 356a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat // mCurrentlyMountedKdev = XXX 357a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return 0; 358a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 359a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 360a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat n = getDeviceNodes((dev_t *) &deviceNodes, 4); 361a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (!n) { 36297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Failed to get device nodes (%s)\n", strerror(errno)); 36349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return -1; 36449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 36549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 36629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall /* If we're running encrypted, and the volume is marked as encryptable and nonremovable, 367ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey * and also marked as providing Asec storage, then we need to decrypt 36829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * that partition, and update the volume object to point to it's new decrypted 36929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * block device 37029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall */ 37129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall property_get("ro.crypto.state", crypto_state, ""); 372ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey if (providesAsec && 37329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall ((flags & (VOL_NONREMOVABLE | VOL_ENCRYPTABLE))==(VOL_NONREMOVABLE | VOL_ENCRYPTABLE)) && 37429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall !strcmp(crypto_state, "encrypted") && !isDecrypted()) { 37529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall char new_sys_path[MAXPATHLEN]; 37629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall char nodepath[256]; 37729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall int new_major, new_minor; 37829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 37929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall if (n != 1) { 38029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall /* We only expect one device node returned when mounting encryptable volumes */ 38159846b654e8b4a22a1be11cd21d6c5b81375abd2Colin Cross SLOGE("Too many device nodes returned when mounting %s\n", getMountpoint()); 38229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall return -1; 38329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall } 38429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 38529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall if (cryptfs_setup_volume(getLabel(), MAJOR(deviceNodes[0]), MINOR(deviceNodes[0]), 38629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall new_sys_path, sizeof(new_sys_path), 38729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall &new_major, &new_minor)) { 38859846b654e8b4a22a1be11cd21d6c5b81375abd2Colin Cross SLOGE("Cannot setup encryption mapping for %s\n", getMountpoint()); 38929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall return -1; 39029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall } 39129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall /* We now have the new sysfs path for the decrypted block device, and the 39229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * majore and minor numbers for it. So, create the device, update the 39329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall * path to the new sysfs path, and continue. 39429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall */ 39529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall snprintf(nodepath, 39629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall sizeof(nodepath), "/dev/block/vold/%d:%d", 39729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall new_major, new_minor); 39829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall if (createDeviceNode(nodepath, new_major, new_minor)) { 39929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall SLOGE("Error making device node '%s' (%s)", nodepath, 40029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall strerror(errno)); 40129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall } 40229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 40329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall // Todo: Either create sys filename from nodepath, or pass in bogus path so 40429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall // vold ignores state changes on this internal device. 40529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall updateDeviceInfo(nodepath, new_major, new_minor); 40629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 40729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall /* Get the device nodes again, because they just changed */ 40829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall n = getDeviceNodes((dev_t *) &deviceNodes, 4); 40929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall if (!n) { 41029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall SLOGE("Failed to get device nodes (%s)\n", strerror(errno)); 41129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall return -1; 41229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall } 41329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall } 41429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall 415a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat for (i = 0; i < n; i++) { 416a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char devicePath[255]; 417dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat 418346c5b20cbbced7edacf240015c4a89e5b2ca44fColin Cross sprintf(devicePath, "/dev/block/vold/%d:%d", major(deviceNodes[i]), 419346c5b20cbbced7edacf240015c4a89e5b2ca44fColin Cross minor(deviceNodes[i])); 420a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 42197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGI("%s being considered for volume %s\n", devicePath, getLabel()); 422a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 423a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = 0; 424bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat setState(Volume::State_Checking); 425bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 4263bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat if (Fat::check(devicePath)) { 427a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (errno == ENODATA) { 42897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("%s does not contain a FAT filesystem\n", devicePath); 429a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat continue; 430a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 431eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat errno = EIO; 432eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat /* Badness - abort the mount */ 43397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno)); 434eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat setState(Volume::State_Idle); 435eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat return -1; 436a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 437a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 438a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = 0; 4399092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood int gid; 4409092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood 441ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey if (Fat::doMount(devicePath, getMountpoint(), false, false, false, 442ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) { 44397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno)); 4443bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat continue; 445a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 446a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 4470de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey extractMetadata(devicePath); 448cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat 449ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey if (providesAsec && mountAsecExternal() != 0) { 450ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey SLOGE("Failed to mount secure area (%s)", strerror(errno)); 451ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey umount(getMountpoint()); 4523bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat setState(Volume::State_Idle); 4533bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat return -1; 4543bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat } 4553bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 456ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey char service[64]; 457ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey snprintf(service, 64, "fuse_%s", getLabel()); 458ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey property_set("ctl.start", service); 459ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey 4603bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat setState(Volume::State_Mounted); 4613bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat mCurrentlyMountedKdev = deviceNodes[i]; 4623bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat return 0; 463a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 464a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 46597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Volume %s found no suitable devices for mounting :(\n", getLabel()); 46649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat setState(Volume::State_Idle); 467a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 468eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat return -1; 469a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 470a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 471ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkeyint Volume::mountAsecExternal() { 472ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey char legacy_path[PATH_MAX]; 473ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey char secure_path[PATH_MAX]; 4743bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 475ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey snprintf(legacy_path, PATH_MAX, "%s/android_secure", getMountpoint()); 476ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey snprintf(secure_path, PATH_MAX, "%s/.android_secure", getMountpoint()); 477a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 478ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey // Recover legacy secure path 479ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey if (!access(legacy_path, R_OK | X_OK) && access(secure_path, R_OK | X_OK)) { 480ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey if (rename(legacy_path, secure_path)) { 481ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey SLOGE("Failed to rename legacy asec dir (%s)", strerror(errno)); 4823bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat } 4833bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat } 4843bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 485ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey if (fs_prepare_dir(secure_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) != 0) { 4868c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey SLOGW("fs_prepare_dir failed: %s", strerror(errno)); 487a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 488a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 489a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 490ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey if (mount(secure_path, SEC_ASECDIR_EXT, "", MS_BIND, NULL)) { 491ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey SLOGE("Failed to bind mount points %s -> %s (%s)", secure_path, 492ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey SEC_ASECDIR_EXT, strerror(errno)); 4933bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat return -1; 4943bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat } 4953bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 4963bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat return 0; 4973bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat} 4983bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 4993bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatint Volume::doUnmount(const char *path, bool force) { 5003bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat int retries = 10; 5013bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 502d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat if (mDebug) { 50397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGD("Unmounting {%s}, force = %d", path, force); 504d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat } 505d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat 5063bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat while (retries--) { 5073bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat if (!umount(path) || errno == EINVAL || errno == ENOENT) { 50897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGI("%s sucessfully unmounted", path); 5093bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat return 0; 5103bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat } 5118c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat 5124ba8948dc16463053e21cda5744f519a555080d0San Mehat int action = 0; 5138c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat 5144ba8948dc16463053e21cda5744f519a555080d0San Mehat if (force) { 5153bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat if (retries == 1) { 5164ba8948dc16463053e21cda5744f519a555080d0San Mehat action = 2; // SIGKILL 5173bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat } else if (retries == 2) { 5184ba8948dc16463053e21cda5744f519a555080d0San Mehat action = 1; // SIGHUP 5194ba8948dc16463053e21cda5744f519a555080d0San Mehat } 5204ba8948dc16463053e21cda5744f519a555080d0San Mehat } 5218c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat 52297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGW("Failed to unmount %s (%s, retries %d, action %d)", 5233bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat path, strerror(errno), retries, action); 5243bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 5253bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat Process::killProcessesWithOpenFiles(path, action); 5264ba8948dc16463053e21cda5744f519a555080d0San Mehat usleep(1000*1000); 527a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 5283bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat errno = EBUSY; 52997ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Giving up on unmount %s (%s)", path, strerror(errno)); 5303bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat return -1; 5313bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat} 532a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 5330b8b59719357fb80c330442787f7d5b1e332263bKen Sumrallint Volume::unmountVol(bool force, bool revert) { 5343bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat int i, rc; 5353bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 536ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey int flags = getFlags(); 537ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey bool providesAsec = (flags & VOL_PROVIDES_ASEC) != 0; 538ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey 5393bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat if (getState() != Volume::State_Mounted) { 54097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Volume %s unmount request when not mounted", getLabel()); 5413bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat errno = EINVAL; 542319b1043bbbd410aa2d572d88b5936f26072d026Ken Sumrall return UNMOUNT_NOT_MOUNTED_ERR; 5433bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat } 5443bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 5453bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat setState(Volume::State_Unmounting); 5463bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat usleep(1000 * 1000); // Give the framework some time to react 5473bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 548ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey char service[64]; 549ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey snprintf(service, 64, "fuse_%s", getLabel()); 550ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey property_set("ctl.stop", service); 551ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey /* Give it a chance to stop. I wish we had a synchronous way to determine this... */ 552ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey sleep(1); 553ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey 554ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey // TODO: determine failure mode if FUSE times out 555ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey 556ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey if (providesAsec && doUnmount(Volume::SEC_ASECDIR_EXT, force) != 0) { 557ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey SLOGE("Failed to unmount secure area on %s (%s)", getMountpoint(), strerror(errno)); 558ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey goto out_mounted; 5593bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat } 5603bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 561ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey /* Now that the fuse daemon is dead, unmount it */ 562ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey if (doUnmount(getFuseMountpoint(), force) != 0) { 563ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey SLOGE("Failed to unmount %s (%s)", getFuseMountpoint(), strerror(errno)); 564ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey goto fail_remount_secure; 5653bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat } 5663bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 567ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey /* Unmount the real sd card */ 568ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey if (doUnmount(getMountpoint(), force) != 0) { 569ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey SLOGE("Failed to unmount %s (%s)", getMountpoint(), strerror(errno)); 570ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey goto fail_remount_secure; 5713bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat } 5723bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 573ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey SLOGI("%s unmounted successfully", getMountpoint()); 5743bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 5750b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall /* If this is an encrypted volume, and we've been asked to undo 5760b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall * the crypto mapping, then revert the dm-crypt mapping, and revert 5770b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall * the device info to the original values. 5780b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall */ 5790b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall if (revert && isDecrypted()) { 5800b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall cryptfs_revert_volume(getLabel()); 5810b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall revertDeviceInfo(); 5820b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall SLOGI("Encrypted volume %s reverted successfully", getMountpoint()); 5830b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall } 5840b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall 5850de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey setUuid(NULL); 5860de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey setUserLabel(NULL); 5873bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat setState(Volume::State_Idle); 5883bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat mCurrentlyMountedKdev = -1; 5893bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat return 0; 5903bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 591ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkeyfail_remount_secure: 592ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey if (providesAsec && mountAsecExternal() != 0) { 593ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey SLOGE("Failed to remount secure area (%s)", strerror(errno)); 5943bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat goto out_nomedia; 595a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 596a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 597ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkeyout_mounted: 598a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat setState(Volume::State_Mounted); 599a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 6003bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat 6013bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatout_nomedia: 6023bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat setState(Volume::State_NoMedia); 6033bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat return -1; 604a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 605ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey 606a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint Volume::initializeMbr(const char *deviceNode) { 6072a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat struct disk_info dinfo; 608a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 6092a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat memset(&dinfo, 0, sizeof(dinfo)); 610a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 6112a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat if (!(dinfo.part_lst = (struct part_info *) malloc(MAX_NUM_PARTS * sizeof(struct part_info)))) { 61297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Failed to malloc prt_lst"); 613a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 614a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 615a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 6162a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat memset(dinfo.part_lst, 0, MAX_NUM_PARTS * sizeof(struct part_info)); 6172a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat dinfo.device = strdup(deviceNode); 6182a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat dinfo.scheme = PART_SCHEME_MBR; 6192a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat dinfo.sect_size = 512; 6202a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat dinfo.skip_lba = 2048; 6212a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat dinfo.num_lba = 0; 6222a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat dinfo.num_parts = 1; 623a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 6242a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat struct part_info *pinfo = &dinfo.part_lst[0]; 625a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 6262a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat pinfo->name = strdup("android_sdcard"); 6272a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat pinfo->flags |= PART_ACTIVE_FLAG; 6282a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat pinfo->type = PC_PART_TYPE_FAT32; 6292a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat pinfo->len_kb = -1; 630a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 6312a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat int rc = apply_disk_config(&dinfo, 0); 632a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 6332a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat if (rc) { 63497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat SLOGE("Failed to apply disk configuration (%d)", rc); 6352a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat goto out; 636a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 6372a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat 6382a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat out: 6392a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat free(pinfo->name); 6402a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat free(dinfo.device); 6412a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat free(dinfo.part_lst); 6422a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat 6432a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat return rc; 644a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 6450de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 6460de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey/* 6470de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey * Use blkid to extract UUID and label from device, since it handles many 6480de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey * obscure edge cases around partition types and formats. Always broadcasts 6490de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey * updated metadata values. 6500de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey */ 6510de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkeyint Volume::extractMetadata(const char* devicePath) { 6520de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey int res = 0; 6530de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 6540de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey std::string cmd; 6550de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey cmd = BLKID_PATH; 6560de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey cmd += " -c /dev/null "; 6570de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey cmd += devicePath; 6580de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 6590de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey FILE* fp = popen(cmd.c_str(), "r"); 6600de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey if (!fp) { 6610de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey ALOGE("Failed to run %s: %s", cmd.c_str(), strerror(errno)); 6620de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey res = -1; 6630de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey goto done; 6640de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey } 6650de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 6660de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey char line[1024]; 6670de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey char value[128]; 6680de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey if (fgets(line, sizeof(line), fp) != NULL) { 6698c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey ALOGD("blkid identified as %s", line); 6700de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 6716bcd362edd1f0ad97807276ff7f9f16991df99a4Jeff Sharkey char* start = strstr(line, "UUID="); 6726bcd362edd1f0ad97807276ff7f9f16991df99a4Jeff Sharkey if (start != NULL && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) { 6730de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey setUuid(value); 6740de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey } else { 6750de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey setUuid(NULL); 6760de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey } 6770de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 6786bcd362edd1f0ad97807276ff7f9f16991df99a4Jeff Sharkey start = strstr(line, "LABEL="); 6796bcd362edd1f0ad97807276ff7f9f16991df99a4Jeff Sharkey if (start != NULL && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) { 6800de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey setUserLabel(value); 6810de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey } else { 6820de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey setUserLabel(NULL); 6830de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey } 6840de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey } else { 6858c2c15b1c611708c85b3f1ba86b6db79c5c004d5Jeff Sharkey ALOGW("blkid failed to identify %s", devicePath); 6860de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey res = -1; 6870de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey } 6880de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 6890de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey pclose(fp); 6900de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey 6910de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkeydone: 6920de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey if (res == -1) { 6930de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey setUuid(NULL); 6940de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey setUserLabel(NULL); 6950de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey } 6960de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey return res; 6970de365fc0af30ae48c2037e1057f2a813029a618Jeff Sharkey} 698