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>
3137dcda68d334f70e1f7f69a9817def65fe3ee717Olivier Bailly#include <linux/fs.h>
32a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
33a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include <cutils/properties.h>
34a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
352a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat#include <diskconfig/diskconfig.h>
36f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
379092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood#include <private/android_filesystem_config.h>
389092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood
39f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#define LOG_TAG "Vold"
40f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
41f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <cutils/log.h>
42f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
43f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "Volume.h"
44a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "VolumeManager.h"
45a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "ResponseCode.h"
46bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include "Fat.h"
47586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include "Process.h"
4829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall#include "cryptfs.h"
49f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
50a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatextern "C" void dos_partition_dec(void const *pp, struct dos_partition *d);
51a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatextern "C" void dos_partition_enc(void *pp, struct dos_partition *d);
5249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
533bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
543bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat/*
553bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat * Secure directory - stuff that only root can see
563bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat */
573bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatconst char *Volume::SECDIR            = "/mnt/secure";
583bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
593bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat/*
603bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat * Secure staging directory - where media is mounted for preparation
613bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat */
623bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatconst char *Volume::SEC_STGDIR        = "/mnt/secure/staging";
633bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
643bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat/*
653bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat * Path to the directory on the media which contains publicly accessable
663bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat * asec imagefiles. This path will be obscured before the mount is
673bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat * exposed to non priviledged users.
683bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat */
6952c2ccb6d25b94b96685efd4803226727710fbaeSan Mehatconst char *Volume::SEC_STG_SECIMGDIR = "/mnt/secure/staging/.android_secure";
703bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
713bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat/*
72344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * Path to external storage where *only* root can access ASEC image files
733bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat */
74344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootconst char *Volume::SEC_ASECDIR_EXT   = "/mnt/secure/asec";
753bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
763bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat/*
77344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root * Path to internal storage where *only* root can access ASEC image files
78344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root */
79344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Rootconst char *Volume::SEC_ASECDIR_INT   = "/data/app-asec";
80344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root/*
813bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat * Path to where secure containers are mounted
823bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat */
833bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatconst char *Volume::ASECDIR           = "/mnt/asec";
843bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
85fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root/*
86508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Root * Path to where OBBs are mounted
87fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root */
88508c0e1605b795bbb51cb47d955b89f3df26ca94Kenny Rootconst char *Volume::LOOPDIR           = "/mnt/obb";
89fb7c4d5a8a1031cf0e493ff182dcf458e5fe8c77Kenny Root
90a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatstatic const char *stateToStr(int state) {
91a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (state == Volume::State_Init)
92a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Initializing";
93a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_NoMedia)
94a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "No-Media";
95a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Idle)
96a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Idle-Unmounted";
97a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Pending)
98a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Pending";
99a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Mounted)
100a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Mounted";
101a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Unmounting)
102a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Unmounting";
103a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Checking)
104a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Checking";
105a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Formatting)
106a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Formatting";
107a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Shared)
108a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Shared-Unmounted";
109a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_SharedMnt)
110a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Shared-Mounted";
111a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else
112a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Unknown-Error";
113a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
11449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
115a2677e4ad01f250b0765f04adf0acfa6627efc98San MehatVolume::Volume(VolumeManager *vm, const char *label, const char *mount_point) {
116a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mVm = vm;
117d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    mDebug = false;
118f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mLabel = strdup(label);
119f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mMountpoint = strdup(mount_point);
120f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mState = Volume::State_Init;
121a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mCurrentlyMountedKdev = -1;
122a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood    mPartIdx = -1;
123507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer    mRetryMount = false;
124f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
125f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
126f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolume::~Volume() {
127f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    free(mLabel);
128f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    free(mMountpoint);
129f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
130f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
131cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehatvoid Volume::protectFromAutorunStupidity() {
132cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    char filename[255];
133cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat
134cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    snprintf(filename, sizeof(filename), "%s/autorun.inf", SEC_STGDIR);
135cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    if (!access(filename, F_OK)) {
13697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Volume contains an autorun.inf! - removing");
137cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat        /*
138cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat         * Ensure the filename is all lower-case so
139cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat         * the process killer can find the inode.
140cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat         * Probably being paranoid here but meh.
141cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat         */
142cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat        rename(filename, filename);
143cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat        Process::killProcessesWithOpenFiles(filename, 2);
144cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat        if (unlink(filename)) {
14597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Failed to remove %s (%s)", filename, strerror(errno));
146cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat        }
147cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    }
148cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat}
149cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat
150d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehatvoid Volume::setDebug(bool enable) {
151d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    mDebug = enable;
152d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat}
153d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
154a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatdev_t Volume::getDiskDevice() {
155a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return MKDEV(0, 0);
156a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat};
157a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
1582dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwooddev_t Volume::getShareDevice() {
1592dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood    return getDiskDevice();
1602dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood}
1612dfe297ec47559dbe2297a72bea71cf515c03797Mike Lockwood
162a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid Volume::handleVolumeShared() {
163a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
164a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
165a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid Volume::handleVolumeUnshared() {
166a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
167a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
168fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehatint Volume::handleBlockEvent(NetlinkEvent *evt) {
169f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    errno = ENOSYS;
170f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return -1;
171f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
172f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
173f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatvoid Volume::setState(int state) {
174a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char msg[255];
175a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int oldState = mState;
176a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
177a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (oldState == state) {
17897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Duplicate state (%d)\n", state);
179a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return;
180a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
181a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
182507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer    if ((oldState == Volume::State_Pending) && (state != Volume::State_Idle)) {
183507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer        mRetryMount = false;
184507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer    }
185507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer
186f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mState = state;
187a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
18897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    SLOGD("Volume %s state changing %d (%s) -> %d (%s)", mLabel,
189a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat         oldState, stateToStr(oldState), mState, stateToStr(mState));
190a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(msg, sizeof(msg),
191a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             "Volume %s %s state changed from %d (%s) to %d (%s)", getLabel(),
192a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             getMountpoint(), oldState, stateToStr(oldState), mState,
193a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             stateToStr(mState));
194a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
195a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,
196a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                         msg, false);
197f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
19849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
199dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehatint Volume::createDeviceNode(const char *path, int major, int minor) {
200dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    mode_t mode = 0660 | S_IFBLK;
201dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    dev_t dev = (major << 8) | minor;
202dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    if (mknod(path, mode, dev) < 0) {
203dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat        if (errno != EEXIST) {
204dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat            return -1;
205dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat        }
206dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    }
207dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    return 0;
208dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat}
209dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat
210a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint Volume::formatVol() {
21149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
212a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (getState() == Volume::State_NoMedia) {
213a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
21449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
215a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else if (getState() != Volume::State_Idle) {
216a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EBUSY;
217a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
218a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
219a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
220a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (isMountpointMounted(getMountpoint())) {
22197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Volume is idle but appears to be mounted - fixing");
222a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        setState(Volume::State_Mounted);
223a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // mCurrentlyMountedKdev = XXX
224a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EBUSY;
225a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
226a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
227a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
228a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood    bool formatEntireDevice = (mPartIdx == -1);
229a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char devicePath[255];
230a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t diskNode = getDiskDevice();
231a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood    dev_t partNode = MKDEV(MAJOR(diskNode), (formatEntireDevice ? 1 : mPartIdx));
232a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
2332a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    setState(Volume::State_Formatting);
234a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
23564382de1f93b84ca59f607da4b4fdbd77f1af67dChih-Wei Huang    int ret = -1;
236a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood    // Only initialize the MBR if we are formatting the entire device
237a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood    if (formatEntireDevice) {
238a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood        sprintf(devicePath, "/dev/block/vold/%d:%d",
239a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood                MAJOR(diskNode), MINOR(diskNode));
240a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood
241a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood        if (initializeMbr(devicePath)) {
242a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood            SLOGE("Failed to initialize MBR (%s)", strerror(errno));
243a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood            goto err;
244a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood        }
245a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
246a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
247a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    sprintf(devicePath, "/dev/block/vold/%d:%d",
248a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            MAJOR(partNode), MINOR(partNode));
249a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
250a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood    if (mDebug) {
251a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood        SLOGI("Formatting volume %s (%s)", getLabel(), devicePath);
252a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood    }
253a4886f1f8ed72e24a302a91a0ab18bc54b6f585eMike Lockwood
254fcf24fe62f98c5d44431aa575555569c2c7a29b0San Mehat    if (Fat::format(devicePath, 0)) {
25597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to format (%s)", strerror(errno));
256a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        goto err;
257a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
258a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
25964382de1f93b84ca59f607da4b4fdbd77f1af67dChih-Wei Huang    ret = 0;
26064382de1f93b84ca59f607da4b4fdbd77f1af67dChih-Wei Huang
261a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehaterr:
26264382de1f93b84ca59f607da4b4fdbd77f1af67dChih-Wei Huang    setState(Volume::State_Idle);
26364382de1f93b84ca59f607da4b4fdbd77f1af67dChih-Wei Huang    return ret;
264a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
265a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
266a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatbool Volume::isMountpointMounted(const char *path) {
267a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char device[256];
268a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char mount_path[256];
269a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char rest[256];
270a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    FILE *fp;
271a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char line[1024];
272a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
273a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!(fp = fopen("/proc/mounts", "r"))) {
27497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
275a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return false;
27649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
27749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
278a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    while(fgets(line, sizeof(line), fp)) {
279a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        line[strlen(line)-1] = '\0';
280a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
281a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(mount_path, path)) {
282a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            fclose(fp);
283a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            return true;
284a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
285dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat
286a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
287dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat
288a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    fclose(fp);
289a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return false;
290a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
291a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
292a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint Volume::mountVol() {
293a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t deviceNodes[4];
294a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int n, i, rc = 0;
295a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char errmsg[255];
296850949485b390c0928ea2f4a7db47be73bebb718Mike Lockwood    const char* externalStorage = getenv("EXTERNAL_STORAGE");
297850949485b390c0928ea2f4a7db47be73bebb718Mike Lockwood    bool primaryStorage = externalStorage && !strcmp(getMountpoint(), externalStorage);
29829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    char decrypt_state[PROPERTY_VALUE_MAX];
29929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    char crypto_state[PROPERTY_VALUE_MAX];
30029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    char encrypt_progress[PROPERTY_VALUE_MAX];
30129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    int flags;
30229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
30329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    property_get("vold.decrypt", decrypt_state, "");
30429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    property_get("vold.encrypt_progress", encrypt_progress, "");
30529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
30629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    /* Don't try to mount the volumes if we have not yet entered the disk password
30729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall     * or are in the process of encrypting.
30829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall     */
30929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    if ((getState() == Volume::State_NoMedia) ||
31029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        ((!strcmp(decrypt_state, "1") || encrypt_progress[0]) && primaryStorage)) {
311a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        snprintf(errmsg, sizeof(errmsg),
312a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                 "Volume %s %s mount failed - no media",
313a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                 getLabel(), getMountpoint());
314a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mVm->getBroadcaster()->sendBroadcast(
315a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                         ResponseCode::VolumeMountFailedNoMedia,
316a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                         errmsg, false);
317a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
318a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
319a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else if (getState() != Volume::State_Idle) {
320a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EBUSY;
321507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer        if (getState() == Volume::State_Pending) {
322507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer            mRetryMount = true;
323507d31b86b38dffe7c60ca5c54b5e631f5a7cab3Joseph Lehrer        }
32449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
32549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
32649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
327a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (isMountpointMounted(getMountpoint())) {
32897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Volume is idle but appears to be mounted - fixing");
329a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        setState(Volume::State_Mounted);
330a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // mCurrentlyMountedKdev = XXX
331a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return 0;
332a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
333a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
334a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    n = getDeviceNodes((dev_t *) &deviceNodes, 4);
335a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!n) {
33697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to get device nodes (%s)\n", strerror(errno));
33749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
33849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
33949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
34029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    /* If we're running encrypted, and the volume is marked as encryptable and nonremovable,
34129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall     * and vold is asking to mount the primaryStorage device, then we need to decrypt
34229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall     * that partition, and update the volume object to point to it's new decrypted
34329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall     * block device
34429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall     */
34529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    property_get("ro.crypto.state", crypto_state, "");
34629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    flags = getFlags();
34729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    if (primaryStorage &&
34829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        ((flags & (VOL_NONREMOVABLE | VOL_ENCRYPTABLE))==(VOL_NONREMOVABLE | VOL_ENCRYPTABLE)) &&
34929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        !strcmp(crypto_state, "encrypted") && !isDecrypted()) {
35029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall       char new_sys_path[MAXPATHLEN];
35129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall       char nodepath[256];
35229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall       int new_major, new_minor;
35329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
35429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall       if (n != 1) {
35529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall           /* We only expect one device node returned when mounting encryptable volumes */
35629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall           SLOGE("Too many device nodes returned when mounting %d\n", getMountpoint());
35729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall           return -1;
35829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall       }
35929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
36029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall       if (cryptfs_setup_volume(getLabel(), MAJOR(deviceNodes[0]), MINOR(deviceNodes[0]),
36129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall                                new_sys_path, sizeof(new_sys_path),
36229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall                                &new_major, &new_minor)) {
36329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall           SLOGE("Cannot setup encryption mapping for %d\n", getMountpoint());
36429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall           return -1;
36529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall       }
36629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall       /* We now have the new sysfs path for the decrypted block device, and the
36729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        * majore and minor numbers for it.  So, create the device, update the
36829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        * path to the new sysfs path, and continue.
36929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        */
37029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        snprintf(nodepath,
37129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall                 sizeof(nodepath), "/dev/block/vold/%d:%d",
37229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall                 new_major, new_minor);
37329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        if (createDeviceNode(nodepath, new_major, new_minor)) {
37429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            SLOGE("Error making device node '%s' (%s)", nodepath,
37529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall                                                       strerror(errno));
37629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        }
37729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
37829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        // Todo: Either create sys filename from nodepath, or pass in bogus path so
37929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        //       vold ignores state changes on this internal device.
38029d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        updateDeviceInfo(nodepath, new_major, new_minor);
38129d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
38229d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        /* Get the device nodes again, because they just changed */
38329d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        n = getDeviceNodes((dev_t *) &deviceNodes, 4);
38429d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        if (!n) {
38529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            SLOGE("Failed to get device nodes (%s)\n", strerror(errno));
38629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall            return -1;
38729d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall        }
38829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall    }
38929d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
390a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    for (i = 0; i < n; i++) {
391a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        char devicePath[255];
392dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat
393a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]),
394a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                MINOR(deviceNodes[i]));
395a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
39697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGI("%s being considered for volume %s\n", devicePath, getLabel());
397a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
398a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = 0;
399bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat        setState(Volume::State_Checking);
400bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat
4013bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (Fat::check(devicePath)) {
402a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (errno == ENODATA) {
40397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                SLOGW("%s does not contain a FAT filesystem\n", devicePath);
404a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                continue;
405a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            }
406eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            errno = EIO;
407eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            /* Badness - abort the mount */
40897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno));
409eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            setState(Volume::State_Idle);
410eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            return -1;
411a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
412a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
4133bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        /*
4143bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat         * Mount the device on our internal staging mountpoint so we can
4153bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat         * muck with it before exposing it to non priviledged users.
4163bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat         */
417a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = 0;
4189092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood        int gid;
4199092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood
420850949485b390c0928ea2f4a7db47be73bebb718Mike Lockwood        if (primaryStorage) {
4219092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood            // Special case the primary SD card.
4229092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood            // For this we grant write access to the SDCARD_RW group.
4239092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood            gid = AID_SDCARD_RW;
4249092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood        } else {
4259092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood            // For secondary external storage we keep things locked up.
4269092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood            gid = AID_MEDIA_RW;
4279092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood        }
428a3e06084564c86ff618c40f185f3676b8b629b94Kenny Root        if (Fat::doMount(devicePath, "/mnt/secure/staging", false, false, false,
4299092b1dbd31406f6939045fbef70a297b8dbeb62Mike Lockwood                AID_SYSTEM, gid, 0702, true)) {
43097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno));
4313bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            continue;
432a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
433a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
43497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGI("Device %s, target %s mounted @ /mnt/secure/staging", devicePath, getMountpoint());
4353bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
436cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat        protectFromAutorunStupidity();
437cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat
438850949485b390c0928ea2f4a7db47be73bebb718Mike Lockwood        // only create android_secure on primary storage
439850949485b390c0928ea2f4a7db47be73bebb718Mike Lockwood        if (primaryStorage && createBindMounts()) {
44097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Failed to create bindmounts (%s)", strerror(errno));
4413bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            umount("/mnt/secure/staging");
4423bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            setState(Volume::State_Idle);
4433bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return -1;
4443bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
4453bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
4463bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        /*
4473bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat         * Now that the bindmount trickery is done, atomically move the
4483bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat         * whole subtree to expose it to non priviledged users.
4493bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat         */
4503bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (doMoveMount("/mnt/secure/staging", getMountpoint(), false)) {
45197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Failed to move mount (%s)", strerror(errno));
4523bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            umount("/mnt/secure/staging");
4533bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            setState(Volume::State_Idle);
4543bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return -1;
4553bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
4563bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        setState(Volume::State_Mounted);
4573bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        mCurrentlyMountedKdev = deviceNodes[i];
4583bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        return 0;
459a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
460a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
46197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    SLOGE("Volume %s found no suitable devices for mounting :(\n", getLabel());
46249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    setState(Volume::State_Idle);
463a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
464eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    return -1;
465a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
466a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
4673bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatint Volume::createBindMounts() {
4683bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    unsigned long flags;
4693bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
4703bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
47152c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat     * Rename old /android_secure -> /.android_secure
47252c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat     */
47352c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat    if (!access("/mnt/secure/staging/android_secure", R_OK | X_OK) &&
47452c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat         access(SEC_STG_SECIMGDIR, R_OK | X_OK)) {
47552c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat        if (rename("/mnt/secure/staging/android_secure", SEC_STG_SECIMGDIR)) {
47697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Failed to rename legacy asec dir (%s)", strerror(errno));
47752c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat        }
47852c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat    }
47952c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat
48052c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat    /*
4813bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * Ensure that /android_secure exists and is a directory
4823bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
4833bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (access(SEC_STG_SECIMGDIR, R_OK | X_OK)) {
4843bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (errno == ENOENT) {
4853bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            if (mkdir(SEC_STG_SECIMGDIR, 0777)) {
48697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                SLOGE("Failed to create %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
4873bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat                return -1;
4883bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            }
4893bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        } else {
49097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Failed to access %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
4913bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return -1;
4923bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
4933bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    } else {
4943bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        struct stat sbuf;
495a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
4963bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (stat(SEC_STG_SECIMGDIR, &sbuf)) {
49797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Failed to stat %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
4983bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return -1;
4993bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
5003bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (!S_ISDIR(sbuf.st_mode)) {
50197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("%s is not a directory", SEC_STG_SECIMGDIR);
5023bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            errno = ENOTDIR;
5033bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return -1;
5043bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
5053bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
5063bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
5073bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
5083bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * Bind mount /mnt/secure/staging/android_secure -> /mnt/secure/asec so we'll
5093bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * have a root only accessable mountpoint for it.
5103bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
511344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (mount(SEC_STG_SECIMGDIR, SEC_ASECDIR_EXT, "", MS_BIND, NULL)) {
51297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to bind mount points %s -> %s (%s)",
513344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root                SEC_STG_SECIMGDIR, SEC_ASECDIR_EXT, strerror(errno));
514a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
515a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
516a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
5173bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
5183bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * Mount a read-only, zero-sized tmpfs  on <mountpoint>/android_secure to
5193bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * obscure the underlying directory from everybody - sneaky eh? ;)
5203bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
5213bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (mount("tmpfs", SEC_STG_SECIMGDIR, "tmpfs", MS_RDONLY, "size=0,mode=000,uid=0,gid=0")) {
52297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to obscure %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
5233bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        umount("/mnt/asec_secure");
5243bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        return -1;
5253bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
5263bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
5273bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    return 0;
5283bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat}
5293bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
5303bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatint Volume::doMoveMount(const char *src, const char *dst, bool force) {
5313bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    unsigned int flags = MS_MOVE;
5323bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    int retries = 5;
5333bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
5343bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    while(retries--) {
5353bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (!mount(src, dst, "", flags, NULL)) {
536d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            if (mDebug) {
53797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat                SLOGD("Moved mount %s -> %s sucessfully", src, dst);
538d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat            }
5393bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return 0;
5403bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        } else if (errno != EBUSY) {
54197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGE("Failed to move mount %s -> %s (%s)", src, dst, strerror(errno));
5423bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return -1;
5433bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
5443bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        int action = 0;
5453bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
5463bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (force) {
5473bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            if (retries == 1) {
5483bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat                action = 2; // SIGKILL
5493bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            } else if (retries == 2) {
5503bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat                action = 1; // SIGHUP
5513bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            }
552a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
55397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Failed to move %s -> %s (%s, retries %d, action %d)",
5543bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat                src, dst, strerror(errno), retries, action);
5553bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        Process::killProcessesWithOpenFiles(src, action);
5563bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        usleep(1000*250);
5573bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
558a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
5593bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    errno = EBUSY;
56097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    SLOGE("Giving up on move %s -> %s (%s)", src, dst, strerror(errno));
5613bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    return -1;
5623bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat}
5633bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
5643bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatint Volume::doUnmount(const char *path, bool force) {
5653bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    int retries = 10;
5663bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
567d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    if (mDebug) {
56897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGD("Unmounting {%s}, force = %d", path, force);
569d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat    }
570d9a4e358614a0c5f60cc76c0636ee4bb02004a32San Mehat
5713bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    while (retries--) {
5723bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (!umount(path) || errno == EINVAL || errno == ENOENT) {
57397ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat            SLOGI("%s sucessfully unmounted", path);
5743bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return 0;
5753bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
5768c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
5774ba8948dc16463053e21cda5744f519a555080d0San Mehat        int action = 0;
5788c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
5794ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (force) {
5803bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            if (retries == 1) {
5814ba8948dc16463053e21cda5744f519a555080d0San Mehat                action = 2; // SIGKILL
5823bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            } else if (retries == 2) {
5834ba8948dc16463053e21cda5744f519a555080d0San Mehat                action = 1; // SIGHUP
5844ba8948dc16463053e21cda5744f519a555080d0San Mehat            }
5854ba8948dc16463053e21cda5744f519a555080d0San Mehat        }
5868c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
58797ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGW("Failed to unmount %s (%s, retries %d, action %d)",
5883bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat                path, strerror(errno), retries, action);
5893bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
5903bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        Process::killProcessesWithOpenFiles(path, action);
5914ba8948dc16463053e21cda5744f519a555080d0San Mehat        usleep(1000*1000);
592a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
5933bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    errno = EBUSY;
59497ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    SLOGE("Giving up on unmount %s (%s)", path, strerror(errno));
5953bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    return -1;
5963bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat}
597a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
5980b8b59719357fb80c330442787f7d5b1e332263bKen Sumrallint Volume::unmountVol(bool force, bool revert) {
5993bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    int i, rc;
6003bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
6013bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (getState() != Volume::State_Mounted) {
60297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Volume %s unmount request when not mounted", getLabel());
6033bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        errno = EINVAL;
604319b1043bbbd410aa2d572d88b5936f26072d026Ken Sumrall        return UNMOUNT_NOT_MOUNTED_ERR;
6053bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
6063bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
6073bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    setState(Volume::State_Unmounting);
6083bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    usleep(1000 * 1000); // Give the framework some time to react
6093bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
6103bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
6113bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * First move the mountpoint back to our internal staging point
6123bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * so nobody else can muck with it while we work.
6133bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
6143bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (doMoveMount(getMountpoint(), SEC_STGDIR, force)) {
61597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to move mount %s => %s (%s)", getMountpoint(), SEC_STGDIR, strerror(errno));
6163bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        setState(Volume::State_Mounted);
6173bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        return -1;
6183bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
6193bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
620cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat    protectFromAutorunStupidity();
621cb4dac8a5243f6673b0590019b5b28a01bd3e343San Mehat
6223bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
6233bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * Unmount the tmpfs which was obscuring the asec image directory
6243bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * from non root users
6253bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
6263bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
6273bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (doUnmount(Volume::SEC_STG_SECIMGDIR, force)) {
62897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to unmount tmpfs on %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
6293bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        goto fail_republish;
6303bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
6313bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
6323bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
6333bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * Remove the bindmount we were using to keep a reference to
6343bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * the previously obscured directory.
6353bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
6363bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
637344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (doUnmount(Volume::SEC_ASECDIR_EXT, force)) {
638344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root        SLOGE("Failed to remove bindmount on %s (%s)", SEC_ASECDIR_EXT, strerror(errno));
6393bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        goto fail_remount_tmpfs;
6403bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
6413bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
6423bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
6433bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * Finally, unmount the actual block device from the staging dir
6443bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
6453bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (doUnmount(Volume::SEC_STGDIR, force)) {
64697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to unmount %s (%s)", SEC_STGDIR, strerror(errno));
6473bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        goto fail_recreate_bindmount;
6483bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
6493bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
65097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    SLOGI("%s unmounted sucessfully", getMountpoint());
6513bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
6520b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall    /* If this is an encrypted volume, and we've been asked to undo
6530b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall     * the crypto mapping, then revert the dm-crypt mapping, and revert
6540b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall     * the device info to the original values.
6550b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall     */
6560b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall    if (revert && isDecrypted()) {
6570b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall        cryptfs_revert_volume(getLabel());
6580b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall        revertDeviceInfo();
6590b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall        SLOGI("Encrypted volume %s reverted successfully", getMountpoint());
6600b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall    }
6610b8b59719357fb80c330442787f7d5b1e332263bKen Sumrall
6623bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    setState(Volume::State_Idle);
6633bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    mCurrentlyMountedKdev = -1;
6643bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    return 0;
6653bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
6663bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
6673bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * Failure handling - try to restore everything back the way it was
6683bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
6693bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatfail_recreate_bindmount:
670344ca10856f3d3087a3288ce8f91ad83665d93fbKenny Root    if (mount(SEC_STG_SECIMGDIR, SEC_ASECDIR_EXT, "", MS_BIND, NULL)) {
67197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to restore bindmount after failure! - Storage will appear offline!");
6723bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        goto out_nomedia;
6733bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
6743bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatfail_remount_tmpfs:
6753bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (mount("tmpfs", SEC_STG_SECIMGDIR, "tmpfs", MS_RDONLY, "size=0,mode=0,uid=0,gid=0")) {
67697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to restore tmpfs after failure! - Storage will appear offline!");
6773bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        goto out_nomedia;
6783bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
6793bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatfail_republish:
6803bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (doMoveMount(SEC_STGDIR, getMountpoint(), force)) {
68197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to republish mount after failure! - Storage will appear offline!");
6823bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        goto out_nomedia;
683a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
684a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
685a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    setState(Volume::State_Mounted);
686a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return -1;
6873bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
6883bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatout_nomedia:
6893bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    setState(Volume::State_NoMedia);
6903bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    return -1;
691a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
692a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint Volume::initializeMbr(const char *deviceNode) {
6932a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    struct disk_info dinfo;
694a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
6952a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    memset(&dinfo, 0, sizeof(dinfo));
696a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
6972a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    if (!(dinfo.part_lst = (struct part_info *) malloc(MAX_NUM_PARTS * sizeof(struct part_info)))) {
69897ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to malloc prt_lst");
699a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
700a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
701a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
7022a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    memset(dinfo.part_lst, 0, MAX_NUM_PARTS * sizeof(struct part_info));
7032a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    dinfo.device = strdup(deviceNode);
7042a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    dinfo.scheme = PART_SCHEME_MBR;
7052a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    dinfo.sect_size = 512;
7062a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    dinfo.skip_lba = 2048;
7072a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    dinfo.num_lba = 0;
7082a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    dinfo.num_parts = 1;
709a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
7102a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    struct part_info *pinfo = &dinfo.part_lst[0];
711a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
7122a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    pinfo->name = strdup("android_sdcard");
7132a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    pinfo->flags |= PART_ACTIVE_FLAG;
7142a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    pinfo->type = PC_PART_TYPE_FAT32;
7152a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    pinfo->len_kb = -1;
716a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
7172a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    int rc = apply_disk_config(&dinfo, 0);
718a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
7192a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    if (rc) {
72097ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Failed to apply disk configuration (%d)", rc);
7212a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat        goto out;
722a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
7232a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat
7242a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat out:
7252a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    free(pinfo->name);
7262a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    free(dinfo.device);
7272a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    free(dinfo.part_lst);
7282a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat
7292a5b8ce09b8836a8463ef9beaaff865c36ca5e6aSan Mehat    return rc;
730a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
731