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