Volume.cpp revision 52c2ccb6d25b94b96685efd4803226727710fbae
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>
28a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
29a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include <linux/kdev_t.h>
30a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
31a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include <cutils/properties.h>
32a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
33a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "diskmbr.h"
34f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
35f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#define LOG_TAG "Vold"
36f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
37f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <cutils/log.h>
38f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
39f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "Volume.h"
40a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "VolumeManager.h"
41a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat#include "ResponseCode.h"
42bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat#include "Fat.h"
43586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat#include "Process.h"
44f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
45a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatextern "C" void dos_partition_dec(void const *pp, struct dos_partition *d);
46a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatextern "C" void dos_partition_enc(void *pp, struct dos_partition *d);
4749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
483bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
493bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat/*
503bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat * Secure directory - stuff that only root can see
513bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat */
523bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatconst char *Volume::SECDIR            = "/mnt/secure";
533bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
543bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat/*
553bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat * Secure staging directory - where media is mounted for preparation
563bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat */
573bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatconst char *Volume::SEC_STGDIR        = "/mnt/secure/staging";
583bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
593bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat/*
603bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat * Path to the directory on the media which contains publicly accessable
613bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat * asec imagefiles. This path will be obscured before the mount is
623bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat * exposed to non priviledged users.
633bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat */
6452c2ccb6d25b94b96685efd4803226727710fbaeSan Mehatconst char *Volume::SEC_STG_SECIMGDIR = "/mnt/secure/staging/.android_secure";
653bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
663bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat/*
673bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat * Path to where *only* root can access asec imagefiles
683bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat */
693bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatconst char *Volume::SEC_ASECDIR       = "/mnt/secure/asec";
703bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
713bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat/*
723bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat * Path to where secure containers are mounted
733bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat */
743bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatconst char *Volume::ASECDIR           = "/mnt/asec";
753bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
76a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatstatic const char *stateToStr(int state) {
77a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (state == Volume::State_Init)
78a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Initializing";
79a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_NoMedia)
80a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "No-Media";
81a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Idle)
82a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Idle-Unmounted";
83a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Pending)
84a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Pending";
85a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Mounted)
86a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Mounted";
87a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Unmounting)
88a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Unmounting";
89a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Checking)
90a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Checking";
91a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Formatting)
92a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Formatting";
93a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Shared)
94a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Shared-Unmounted";
95a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_SharedMnt)
96a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Shared-Mounted";
97a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else
98a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Unknown-Error";
99a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
10049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
101a2677e4ad01f250b0765f04adf0acfa6627efc98San MehatVolume::Volume(VolumeManager *vm, const char *label, const char *mount_point) {
102a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mVm = vm;
103f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mLabel = strdup(label);
104f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mMountpoint = strdup(mount_point);
105f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mState = Volume::State_Init;
106a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mCurrentlyMountedKdev = -1;
107f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
108f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
109f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolume::~Volume() {
110f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    free(mLabel);
111f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    free(mMountpoint);
112f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
113f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
114a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatdev_t Volume::getDiskDevice() {
115a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return MKDEV(0, 0);
116a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat};
117a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
118a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid Volume::handleVolumeShared() {
119a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
120a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
121a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid Volume::handleVolumeUnshared() {
122a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
123a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
124fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehatint Volume::handleBlockEvent(NetlinkEvent *evt) {
125f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    errno = ENOSYS;
126f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return -1;
127f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
128f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
129f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatvoid Volume::setState(int state) {
130a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char msg[255];
131a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int oldState = mState;
132a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
133a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (oldState == state) {
134a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Duplicate state (%d)\n", state);
135a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return;
136a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
137a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
138f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mState = state;
139a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
140a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    LOGD("Volume %s state changing %d (%s) -> %d (%s)", mLabel,
141a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat         oldState, stateToStr(oldState), mState, stateToStr(mState));
142a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(msg, sizeof(msg),
143a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             "Volume %s %s state changed from %d (%s) to %d (%s)", getLabel(),
144a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             getMountpoint(), oldState, stateToStr(oldState), mState,
145a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             stateToStr(mState));
146a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
147a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,
148a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                         msg, false);
149f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
15049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
151dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehatint Volume::createDeviceNode(const char *path, int major, int minor) {
152dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    mode_t mode = 0660 | S_IFBLK;
153dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    dev_t dev = (major << 8) | minor;
154dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    if (mknod(path, mode, dev) < 0) {
155dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat        if (errno != EEXIST) {
156dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat            return -1;
157dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat        }
158dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    }
159dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    return 0;
160dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat}
161dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat
162a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint Volume::formatVol() {
16349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
164a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (getState() == Volume::State_NoMedia) {
165a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
16649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
167a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else if (getState() != Volume::State_Idle) {
168a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EBUSY;
169a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
170a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
171a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
172a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (isMountpointMounted(getMountpoint())) {
173a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Volume is idle but appears to be mounted - fixing");
174a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        setState(Volume::State_Mounted);
175a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // mCurrentlyMountedKdev = XXX
176a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EBUSY;
177a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
178a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
179a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
180a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char devicePath[255];
181a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t diskNode = getDiskDevice();
182a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t partNode = MKDEV(MAJOR(diskNode), 1); // XXX: Hmmm
183a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
184a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    sprintf(devicePath, "/dev/block/vold/%d:%d",
185a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            MAJOR(diskNode), MINOR(diskNode));
186a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
18762e5dd245bd508eabcba56b5680e2b28bfc2caf6San Mehat    LOGI("Formatting volume %s (%s)", getLabel(), devicePath);
188a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
189a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (initializeMbr(devicePath)) {
190a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Failed to initialize MBR (%s)", strerror(errno));
191a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        goto err;
192a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
193a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
194a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    sprintf(devicePath, "/dev/block/vold/%d:%d",
195a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            MAJOR(partNode), MINOR(partNode));
196a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
197bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat    if (Fat::format(devicePath)) {
198a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Failed to format (%s)", strerror(errno));
199a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        goto err;
200a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
201a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
202a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
203a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehaterr:
204a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return -1;
205a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
206a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
207a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatbool Volume::isMountpointMounted(const char *path) {
208a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char device[256];
209a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char mount_path[256];
210a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char rest[256];
211a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    FILE *fp;
212a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char line[1024];
213a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
214a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!(fp = fopen("/proc/mounts", "r"))) {
215a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Error opening /proc/mounts (%s)", strerror(errno));
216a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return false;
21749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
21849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
219a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    while(fgets(line, sizeof(line), fp)) {
220a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        line[strlen(line)-1] = '\0';
221a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
222a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(mount_path, path)) {
223a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            fclose(fp);
224a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            return true;
225a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
226dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat
227a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
228dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat
229a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    fclose(fp);
230a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return false;
231a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
232a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
233a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint Volume::mountVol() {
234a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t deviceNodes[4];
235a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int n, i, rc = 0;
236a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char errmsg[255];
237a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
238a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (getState() == Volume::State_NoMedia) {
239a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        snprintf(errmsg, sizeof(errmsg),
240a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                 "Volume %s %s mount failed - no media",
241a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                 getLabel(), getMountpoint());
242a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mVm->getBroadcaster()->sendBroadcast(
243a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                         ResponseCode::VolumeMountFailedNoMedia,
244a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                         errmsg, false);
245a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
246a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
247a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else if (getState() != Volume::State_Idle) {
248a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EBUSY;
24949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
25049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
25149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
252a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (isMountpointMounted(getMountpoint())) {
253a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Volume is idle but appears to be mounted - fixing");
254a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        setState(Volume::State_Mounted);
255a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // mCurrentlyMountedKdev = XXX
256a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return 0;
257a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
258a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
259a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    n = getDeviceNodes((dev_t *) &deviceNodes, 4);
260a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!n) {
261a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Failed to get device nodes (%s)\n", strerror(errno));
26249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
26349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
26449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
265a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    for (i = 0; i < n; i++) {
266a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        char devicePath[255];
267dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat
268a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]),
269a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                MINOR(deviceNodes[i]));
270a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
271a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGI("%s being considered for volume %s\n", devicePath, getLabel());
272a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
273a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = 0;
274bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat        setState(Volume::State_Checking);
275bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat
2763bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (Fat::check(devicePath)) {
277a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (errno == ENODATA) {
278a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                LOGW("%s does not contain a FAT filesystem\n", devicePath);
279a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                continue;
280a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            }
281eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            errno = EIO;
282eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            /* Badness - abort the mount */
283eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            LOGE("%s failed FS checks (%s)", devicePath, strerror(errno));
284eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            setState(Volume::State_Idle);
285eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat            return -1;
286a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
287a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
2883bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        /*
2893bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat         * Mount the device on our internal staging mountpoint so we can
2903bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat         * muck with it before exposing it to non priviledged users.
2913bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat         */
292a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = 0;
2933bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (Fat::doMount(devicePath, "/mnt/secure/staging", false, false, 1000, 1015, 0702, true)) {
2943bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            LOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno));
2953bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            continue;
296a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
297a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
2983bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        LOGI("Device %s, target %s mounted @ /mnt/secure/staging", devicePath, getMountpoint());
2993bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
3003bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (createBindMounts()) {
3013bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            LOGE("Failed to create bindmounts (%s)", strerror(errno));
3023bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            umount("/mnt/secure/staging");
3033bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            setState(Volume::State_Idle);
3043bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return -1;
3053bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
3063bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
3073bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        /*
3083bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat         * Now that the bindmount trickery is done, atomically move the
3093bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat         * whole subtree to expose it to non priviledged users.
3103bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat         */
3113bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (doMoveMount("/mnt/secure/staging", getMountpoint(), false)) {
3123bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            LOGE("Failed to move mount (%s)", strerror(errno));
3133bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            umount("/mnt/secure/staging");
3143bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            setState(Volume::State_Idle);
3153bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return -1;
3163bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
3173bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        setState(Volume::State_Mounted);
3183bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        mCurrentlyMountedKdev = deviceNodes[i];
3193bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        return 0;
320a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
321a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
322a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    LOGE("Volume %s found no suitable devices for mounting :(\n", getLabel());
32349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    setState(Volume::State_Idle);
324a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
325eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat    return -1;
326a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
327a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
3283bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatint Volume::createBindMounts() {
3293bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    unsigned long flags;
3303bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
3313bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
33252c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat     * Rename old /android_secure -> /.android_secure
33352c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat     */
33452c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat    if (!access("/mnt/secure/staging/android_secure", R_OK | X_OK) &&
33552c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat         access(SEC_STG_SECIMGDIR, R_OK | X_OK)) {
33652c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat        if (rename("/mnt/secure/staging/android_secure", SEC_STG_SECIMGDIR)) {
33752c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat            LOGE("Failed to rename legacy asec dir (%s)", strerror(errno));
33852c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat        }
33952c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat    }
34052c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat
34152c2ccb6d25b94b96685efd4803226727710fbaeSan Mehat    /*
3423bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * Ensure that /android_secure exists and is a directory
3433bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
3443bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (access(SEC_STG_SECIMGDIR, R_OK | X_OK)) {
3453bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (errno == ENOENT) {
3463bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            if (mkdir(SEC_STG_SECIMGDIR, 0777)) {
3473bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat                LOGE("Failed to create %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
3483bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat                return -1;
3493bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            }
3503bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        } else {
3513bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            LOGE("Failed to access %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
3523bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return -1;
3533bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
3543bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    } else {
3553bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        struct stat sbuf;
356a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
3573bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (stat(SEC_STG_SECIMGDIR, &sbuf)) {
3583bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            LOGE("Failed to stat %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
3593bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return -1;
3603bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
3613bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (!S_ISDIR(sbuf.st_mode)) {
3623bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            LOGE("%s is not a directory", SEC_STG_SECIMGDIR);
3633bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            errno = ENOTDIR;
3643bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return -1;
3653bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
3663bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
3673bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
3683bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
3693bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * Bind mount /mnt/secure/staging/android_secure -> /mnt/secure/asec so we'll
3703bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * have a root only accessable mountpoint for it.
3713bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
3723bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (mount(SEC_STG_SECIMGDIR, SEC_ASECDIR, "", MS_BIND, NULL)) {
3733bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        LOGE("Failed to bind mount points %s -> %s (%s)",
3743bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat                SEC_STG_SECIMGDIR, SEC_ASECDIR, strerror(errno));
375a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
376a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
377a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
3783bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
3793bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * Mount a read-only, zero-sized tmpfs  on <mountpoint>/android_secure to
3803bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * obscure the underlying directory from everybody - sneaky eh? ;)
3813bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
3823bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (mount("tmpfs", SEC_STG_SECIMGDIR, "tmpfs", MS_RDONLY, "size=0,mode=000,uid=0,gid=0")) {
3833bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        LOGE("Failed to obscure %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
3843bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        umount("/mnt/asec_secure");
3853bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        return -1;
3863bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
3873bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
3883bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    return 0;
3893bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat}
3903bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
3913bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatint Volume::doMoveMount(const char *src, const char *dst, bool force) {
3923bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    unsigned int flags = MS_MOVE;
3933bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    int retries = 5;
3943bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
3953bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    while(retries--) {
3963bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (!mount(src, dst, "", flags, NULL)) {
3973bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            LOGD("Moved mount %s -> %s sucessfully", src, dst);
3983bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return 0;
3993bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        } else if (errno != EBUSY) {
4003bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            LOGE("Failed to move mount %s -> %s (%s)", src, dst, strerror(errno));
4013bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return -1;
4023bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
4033bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        int action = 0;
4043bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
4053bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (force) {
4063bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            if (retries == 1) {
4073bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat                action = 2; // SIGKILL
4083bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            } else if (retries == 2) {
4093bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat                action = 1; // SIGHUP
4103bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            }
411a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
4123bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        LOGW("Failed to move %s -> %s (%s, retries %d, action %d)",
4133bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat                src, dst, strerror(errno), retries, action);
4143bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        Process::killProcessesWithOpenFiles(src, action);
4153bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        usleep(1000*250);
4163bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
417a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
4183bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    errno = EBUSY;
4193bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    LOGE("Giving up on move %s -> %s (%s)", src, dst, strerror(errno));
4203bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    return -1;
4213bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat}
4223bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
4233bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatint Volume::doUnmount(const char *path, bool force) {
4243bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    int retries = 10;
4253bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
4263bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    while (retries--) {
4273bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        if (!umount(path) || errno == EINVAL || errno == ENOENT) {
4283bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            LOGI("%s sucessfully unmounted", path);
4293bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            return 0;
4303bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        }
4318c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
4324ba8948dc16463053e21cda5744f519a555080d0San Mehat        int action = 0;
4338c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
4344ba8948dc16463053e21cda5744f519a555080d0San Mehat        if (force) {
4353bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            if (retries == 1) {
4364ba8948dc16463053e21cda5744f519a555080d0San Mehat                action = 2; // SIGKILL
4373bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat            } else if (retries == 2) {
4384ba8948dc16463053e21cda5744f519a555080d0San Mehat                action = 1; // SIGHUP
4394ba8948dc16463053e21cda5744f519a555080d0San Mehat            }
4404ba8948dc16463053e21cda5744f519a555080d0San Mehat        }
4418c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat
4423bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        LOGW("Failed to unmount %s (%s, retries %d, action %d)",
4433bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat                path, strerror(errno), retries, action);
4443bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
4453bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        Process::killProcessesWithOpenFiles(path, action);
4464ba8948dc16463053e21cda5744f519a555080d0San Mehat        usleep(1000*1000);
447a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
4483bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    errno = EBUSY;
4493bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    LOGE("Giving up on unmount %s (%s)", path, strerror(errno));
4503bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    return -1;
4513bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat}
452a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
4533bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatint Volume::unmountVol(bool force) {
4543bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    int i, rc;
4553bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
4563bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (getState() != Volume::State_Mounted) {
4573bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        LOGE("Volume %s unmount request when not mounted", getLabel());
4583bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        errno = EINVAL;
4593bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        return -1;
4603bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
4613bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
4623bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    setState(Volume::State_Unmounting);
4633bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    usleep(1000 * 1000); // Give the framework some time to react
4643bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
4653bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
4663bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * First move the mountpoint back to our internal staging point
4673bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * so nobody else can muck with it while we work.
4683bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
4693bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (doMoveMount(getMountpoint(), SEC_STGDIR, force)) {
4703bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        LOGE("Failed to move mount %s => %s (%s)", getMountpoint(), SEC_STGDIR, strerror(errno));
4713bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        setState(Volume::State_Mounted);
4723bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        return -1;
4733bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
4743bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
4753bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
4763bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * Unmount the tmpfs which was obscuring the asec image directory
4773bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * from non root users
4783bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
4793bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
4803bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (doUnmount(Volume::SEC_STG_SECIMGDIR, force)) {
4813bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        LOGE("Failed to unmount tmpfs on %s (%s)", SEC_STG_SECIMGDIR, strerror(errno));
4823bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        goto fail_republish;
4833bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
4843bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
4853bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
4863bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * Remove the bindmount we were using to keep a reference to
4873bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * the previously obscured directory.
4883bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
4893bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
4903bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (doUnmount(Volume::SEC_ASECDIR, force)) {
4913bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        LOGE("Failed to remove bindmount on %s (%s)", SEC_ASECDIR, strerror(errno));
4923bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        goto fail_remount_tmpfs;
4933bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
4943bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
4953bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
4963bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * Finally, unmount the actual block device from the staging dir
4973bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
4983bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (doUnmount(Volume::SEC_STGDIR, force)) {
4993bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        LOGE("Failed to unmount %s (%s)", SEC_STGDIR, strerror(errno));
5003bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        goto fail_recreate_bindmount;
5013bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
5023bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
5033bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    LOGI("%s unmounted sucessfully", getMountpoint());
5043bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
5053bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    setState(Volume::State_Idle);
5063bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    mCurrentlyMountedKdev = -1;
5073bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    return 0;
5083bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
5093bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    /*
5103bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     * Failure handling - try to restore everything back the way it was
5113bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat     */
5123bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatfail_recreate_bindmount:
5133bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (mount(SEC_STG_SECIMGDIR, SEC_ASECDIR, "", MS_BIND, NULL)) {
5143bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        LOGE("Failed to restore bindmount after failure! - Storage will appear offline!");
5153bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        goto out_nomedia;
5163bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
5173bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatfail_remount_tmpfs:
5183bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (mount("tmpfs", SEC_STG_SECIMGDIR, "tmpfs", MS_RDONLY, "size=0,mode=0,uid=0,gid=0")) {
5193bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        LOGE("Failed to restore tmpfs after failure! - Storage will appear offline!");
5203bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        goto out_nomedia;
5213bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    }
5223bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatfail_republish:
5233bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    if (doMoveMount(SEC_STGDIR, getMountpoint(), force)) {
5243bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        LOGE("Failed to republish mount after failure! - Storage will appear offline!");
5253bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat        goto out_nomedia;
526a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
527a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
528a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    setState(Volume::State_Mounted);
529a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return -1;
5303bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat
5313bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehatout_nomedia:
5323bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    setState(Volume::State_NoMedia);
5333bb6020e461e8872e8df0775cba6eb32e06b93ecSan Mehat    return -1;
534a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
535a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
536a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint Volume::initializeMbr(const char *deviceNode) {
537a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd, rc;
538a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    unsigned char block[512];
539a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    struct dos_partition part;
540a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    unsigned int nr_sec;
541a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
542a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if ((fd = open(deviceNode, O_RDWR)) < 0) {
543a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Error opening disk file (%s)", strerror(errno));
544a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
545a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
546a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
547a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
548a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to get device size (%s)", strerror(errno));
549a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
550a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
551a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
552a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
553a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    memset(&part, 0, sizeof(part));
554a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    part.dp_flag = 0x80;
555a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    part.dp_typ = 0xc;
556a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    part.dp_start = ((1024 * 64) / 512) + 1;
557a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    part.dp_size = nr_sec - part.dp_start;
558a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
559a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    memset(block, 0, sizeof(block));
560a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    block[0x1fe] = 0x55;
561a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    block[0x1ff] = 0xaa;
562a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
563a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dos_partition_enc(block + DOSPARTOFF, &part);
564a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
565a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, block, sizeof(block)) < 0) {
566a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Error writing MBR (%s)", strerror(errno));
567a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
568a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
569a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
570a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
571a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (ioctl(fd, BLKRRPART, NULL) < 0) {
572a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Error re-reading partition table (%s)", strerror(errno));
573a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
574a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
575a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
576a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
577a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
578a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
579