Volume.cpp revision bf04185c88161f13118b9975cdff7967d49a4fa0
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"
43f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
44a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatextern "C" void KillProcessesWithOpenFiles(const char *, int, int, int);
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
48a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatstatic const char *stateToStr(int state) {
49a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (state == Volume::State_Init)
50a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Initializing";
51a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_NoMedia)
52a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "No-Media";
53a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Idle)
54a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Idle-Unmounted";
55a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Pending)
56a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Pending";
57a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Mounted)
58a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Mounted";
59a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Unmounting)
60a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Unmounting";
61a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Checking)
62a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Checking";
63a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Formatting)
64a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Formatting";
65a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_Shared)
66a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Shared-Unmounted";
67a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else if (state == Volume::State_SharedMnt)
68a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Shared-Mounted";
69a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    else
70a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return "Unknown-Error";
71a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
7249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
73a2677e4ad01f250b0765f04adf0acfa6627efc98San MehatVolume::Volume(VolumeManager *vm, const char *label, const char *mount_point) {
74a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mVm = vm;
75f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mLabel = strdup(label);
76f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mMountpoint = strdup(mount_point);
77f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mState = Volume::State_Init;
78a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mCurrentlyMountedKdev = -1;
79f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
80f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
81f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolume::~Volume() {
82f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    free(mLabel);
83f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    free(mMountpoint);
84f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
85f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
86a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatdev_t Volume::getDiskDevice() {
87a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return MKDEV(0, 0);
88a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat};
89a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
90a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid Volume::handleVolumeShared() {
91a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
92a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
93a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatvoid Volume::handleVolumeUnshared() {
94a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
95a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
96fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehatint Volume::handleBlockEvent(NetlinkEvent *evt) {
97f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    errno = ENOSYS;
98f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    return -1;
99f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
100f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
101f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatvoid Volume::setState(int state) {
102a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char msg[255];
103a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int oldState = mState;
104a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
105a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (oldState == state) {
106a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Duplicate state (%d)\n", state);
107a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return;
108a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
109a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
110f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    mState = state;
111a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
112a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    LOGD("Volume %s state changing %d (%s) -> %d (%s)", mLabel,
113a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat         oldState, stateToStr(oldState), mState, stateToStr(mState));
114a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    snprintf(msg, sizeof(msg),
115a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             "Volume %s %s state changed from %d (%s) to %d (%s)", getLabel(),
116a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             getMountpoint(), oldState, stateToStr(oldState), mState,
117a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             stateToStr(mState));
118a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
119a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeStateChange,
120a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                         msg, false);
121f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
12249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
123dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehatint Volume::createDeviceNode(const char *path, int major, int minor) {
124dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    mode_t mode = 0660 | S_IFBLK;
125dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    dev_t dev = (major << 8) | minor;
126dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    if (mknod(path, mode, dev) < 0) {
127dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat        if (errno != EEXIST) {
128dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat            return -1;
129dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat        }
130dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    }
131dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat    return 0;
132dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat}
133dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat
134a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint Volume::formatVol() {
13549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
136a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (getState() == Volume::State_NoMedia) {
137a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
13849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
139a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else if (getState() != Volume::State_Idle) {
140a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EBUSY;
141a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
142a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
143a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
144a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (isMountpointMounted(getMountpoint())) {
145a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Volume is idle but appears to be mounted - fixing");
146a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        setState(Volume::State_Mounted);
147a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // mCurrentlyMountedKdev = XXX
148a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EBUSY;
149a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
150a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
151a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
152a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char devicePath[255];
153a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t diskNode = getDiskDevice();
154a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t partNode = MKDEV(MAJOR(diskNode), 1); // XXX: Hmmm
155a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
156a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    sprintf(devicePath, "/dev/block/vold/%d:%d",
157a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            MAJOR(diskNode), MINOR(diskNode));
158a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
159a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    LOGI("Volume %s (%s) MBR being initialized", getLabel(), devicePath);
160a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
161a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (initializeMbr(devicePath)) {
162a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Failed to initialize MBR (%s)", strerror(errno));
163a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        goto err;
164a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
165a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
166a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    sprintf(devicePath, "/dev/block/vold/%d:%d",
167a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            MAJOR(partNode), MINOR(partNode));
168a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
169a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    LOGI("Volume %s (%s) being formatted", getLabel(), devicePath);
170a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
171bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat    if (Fat::format(devicePath)) {
172a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Failed to format (%s)", strerror(errno));
173a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        goto err;
174a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
175a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
176a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    LOGI("Volume %s (%s) formatted sucessfully", getLabel(), devicePath);
177a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
178a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehaterr:
179a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return -1;
180a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
181a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
182a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatbool Volume::isMountpointMounted(const char *path) {
183a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char device[256];
184a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char mount_path[256];
185a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char rest[256];
186a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    FILE *fp;
187a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char line[1024];
188a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
189a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!(fp = fopen("/proc/mounts", "r"))) {
190a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Error opening /proc/mounts (%s)", strerror(errno));
191a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return false;
19249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
19349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
194a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    while(fgets(line, sizeof(line), fp)) {
195a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        line[strlen(line)-1] = '\0';
196a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
197a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!strcmp(mount_path, path)) {
198a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            fclose(fp);
199a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            return true;
200a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
201dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat
202a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
203dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat
204a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    fclose(fp);
205a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return false;
206a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
207a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
208a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint Volume::mountVol() {
209a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dev_t deviceNodes[4];
210a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int n, i, rc = 0;
211a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    char errmsg[255];
212a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
213a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (getState() == Volume::State_NoMedia) {
214a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        snprintf(errmsg, sizeof(errmsg),
215a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                 "Volume %s %s mount failed - no media",
216a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                 getLabel(), getMountpoint());
217a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mVm->getBroadcaster()->sendBroadcast(
218a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                         ResponseCode::VolumeMountFailedNoMedia,
219a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                         errmsg, false);
220a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = ENODEV;
221a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
222a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    } else if (getState() != Volume::State_Idle) {
223a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EBUSY;
22449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
22549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
22649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
227a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (isMountpointMounted(getMountpoint())) {
228a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Volume is idle but appears to be mounted - fixing");
229a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        setState(Volume::State_Mounted);
230a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        // mCurrentlyMountedKdev = XXX
231a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return 0;
232a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
233a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
234a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    n = getDeviceNodes((dev_t *) &deviceNodes, 4);
235a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!n) {
236a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Failed to get device nodes (%s)\n", strerror(errno));
23749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -1;
23849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
23949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
240a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    for (i = 0; i < n; i++) {
241a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        char devicePath[255];
242dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat
243a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]),
244a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                MINOR(deviceNodes[i]));
245a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
246a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGI("%s being considered for volume %s\n", devicePath, getLabel());
247a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
248a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = 0;
249bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat        setState(Volume::State_Checking);
250bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat
251bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat        if ((rc = Fat::check(devicePath))) {
252a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            if (errno == ENODATA) {
253a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                LOGW("%s does not contain a FAT filesystem\n", devicePath);
254a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                continue;
255a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            } else {
256a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                /* Badness - abort the mount */
257a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                LOGE("%s failed FS checks (%s)", devicePath, strerror(errno));
258a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                snprintf(errmsg, sizeof(errmsg),
259a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                         "Volume %s %s mount failed - filesystem check failed",
260a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                         getLabel(), getMountpoint());
261a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                mVm->getBroadcaster()->sendBroadcast(
262a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                         ResponseCode::VolumeMountFailedDamaged,
263a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                         errmsg, false);
264a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                setState(Volume::State_Idle);
265a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                goto out;
266a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            }
267a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
268a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
269a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGI("%s checks out - attempting to mount\n", devicePath);
270a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = 0;
271bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat        if (!(rc = Fat::doMount(devicePath, getMountpoint()))) {
272a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            LOGI("%s sucessfully mounted for volume %s\n", devicePath,
273a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                 getLabel());
274a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            setState(Volume::State_Mounted);
275a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            mCurrentlyMountedKdev = deviceNodes[i];
276a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            goto out;
277a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
278a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
279a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno));
280a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
281a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
282a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    // XXX: Doesn't handle multiple partitions properly
283a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (errno == ENODATA) {
284a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        snprintf(errmsg, sizeof(errmsg),
285a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                 "Volume %s %s mount failed - no supported file-systems",
286a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                 getLabel(), getMountpoint());
287a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mVm->getBroadcaster()->sendBroadcast(
288a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                 ResponseCode::VolumeMountFailedBlank,
289a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                 errmsg, false);
290a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
291a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
292a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
293a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    LOGE("Volume %s found no suitable devices for mounting :(\n", getLabel());
29449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    setState(Volume::State_Idle);
295a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
296a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatout:
297a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return rc;
298a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
299a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
300a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint Volume::unmountVol() {
301a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int i, rc;
302a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
303a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (getState() != Volume::State_Mounted) {
304a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Volume %s unmount request when not mounted", getLabel());
305a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        errno = EINVAL;
306a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
307a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
308a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
309a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    setState(Volume::State_Unmounting);
310a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    for (i = 0; i < 10; i++) {
311a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        rc = umount(getMountpoint());
312a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (!rc)
313a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            break;
314a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
315a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (rc && (errno == EINVAL || errno == ENOENT)) {
316a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            rc = 0;
317a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            break;
318a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
319a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
320a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGW("Volume %s unmount attempt %d failed (%s)",
321a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat             getLabel(), i + 1, strerror(errno));
322a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
323a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        if (i < 5) {
324a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            usleep(1000 * 250);
325a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        } else {
326a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            KillProcessesWithOpenFiles(getMountpoint(),
327a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                       (i < 7 ? 0 : 1),
328a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat                                       NULL, 0);
329a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat            usleep(1000 * 250);
330a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        }
331a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
332a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
333a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (!rc) {
334a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGI("Volume %s unmounted sucessfully", getLabel());
335a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        setState(Volume::State_Idle);
336a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        mCurrentlyMountedKdev = -1;
337a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return 0;
338a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
339a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
340a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    LOGE("Volume %s failed to unmount (%s)\n", getLabel(), strerror(errno));
341a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    setState(Volume::State_Mounted);
342a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return -1;
343a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
344a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
345a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint Volume::initializeMbr(const char *deviceNode) {
346a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    int fd, rc;
347a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    unsigned char block[512];
348a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    struct dos_partition part;
349a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    unsigned int nr_sec;
350a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
351a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if ((fd = open(deviceNode, O_RDWR)) < 0) {
352a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Error opening disk file (%s)", strerror(errno));
353a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
354a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
355a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
356a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
357a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Unable to get device size (%s)", strerror(errno));
358a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
359a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
360a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
361a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
362a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    memset(&part, 0, sizeof(part));
363a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    part.dp_flag = 0x80;
364a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    part.dp_typ = 0xc;
365a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    part.dp_start = ((1024 * 64) / 512) + 1;
366a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    part.dp_size = nr_sec - part.dp_start;
367a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
368a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    memset(block, 0, sizeof(block));
369a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    block[0x1fe] = 0x55;
370a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    block[0x1ff] = 0xaa;
371a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
372a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    dos_partition_enc(block + DOSPARTOFF, &part);
373a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
374a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (write(fd, block, sizeof(block)) < 0) {
375a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Error writing MBR (%s)", strerror(errno));
376a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
377a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
378a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
379a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
380a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    if (ioctl(fd, BLKRRPART, NULL) < 0) {
381a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        LOGE("Error re-reading partition table (%s)", strerror(errno));
382a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        close(fd);
383a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat        return -1;
384a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    }
385a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    close(fd);
386a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    return 0;
387a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat}
388