Volume.cpp revision 586536c60b773e3517531ad8a6cb0de6722c67fc
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 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 15962e5dd245bd508eabcba56b5680e2b28bfc2caf6San Mehat LOGI("Formatting volume %s (%s)", 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 169bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if (Fat::format(devicePath)) { 170a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGE("Failed to format (%s)", strerror(errno)); 171a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat goto err; 172a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 173a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 174a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return 0; 175a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehaterr: 176a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 177a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 178a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 179a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatbool Volume::isMountpointMounted(const char *path) { 180a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char device[256]; 181a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char mount_path[256]; 182a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char rest[256]; 183a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat FILE *fp; 184a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char line[1024]; 185a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 186a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (!(fp = fopen("/proc/mounts", "r"))) { 187a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGE("Error opening /proc/mounts (%s)", strerror(errno)); 188a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return false; 18949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 19049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 191a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat while(fgets(line, sizeof(line), fp)) { 192a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat line[strlen(line)-1] = '\0'; 193a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat sscanf(line, "%255s %255s %255s\n", device, mount_path, rest); 194a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (!strcmp(mount_path, path)) { 195a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat fclose(fp); 196a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return true; 197a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 198dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat 199a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 200dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat 201a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat fclose(fp); 202a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return false; 203a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 204a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 205a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint Volume::mountVol() { 206a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat dev_t deviceNodes[4]; 207a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat int n, i, rc = 0; 208a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char errmsg[255]; 209a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 210a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (getState() == Volume::State_NoMedia) { 211a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat snprintf(errmsg, sizeof(errmsg), 212a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat "Volume %s %s mount failed - no media", 213a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat getLabel(), getMountpoint()); 214a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat mVm->getBroadcaster()->sendBroadcast( 215a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat ResponseCode::VolumeMountFailedNoMedia, 216a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errmsg, false); 217a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = ENODEV; 218a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 219a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } else if (getState() != Volume::State_Idle) { 220a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = EBUSY; 22149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return -1; 22249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 22349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 224a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (isMountpointMounted(getMountpoint())) { 225a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGW("Volume is idle but appears to be mounted - fixing"); 226a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat setState(Volume::State_Mounted); 227a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat // mCurrentlyMountedKdev = XXX 228a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return 0; 229a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 230a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 231a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat n = getDeviceNodes((dev_t *) &deviceNodes, 4); 232a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (!n) { 233a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGE("Failed to get device nodes (%s)\n", strerror(errno)); 23449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return -1; 23549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 23649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 237a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat for (i = 0; i < n; i++) { 238a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat char devicePath[255]; 239dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat 240a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]), 241a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat MINOR(deviceNodes[i])); 242a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 243a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGI("%s being considered for volume %s\n", devicePath, getLabel()); 244a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 245a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = 0; 246bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat setState(Volume::State_Checking); 247bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat 248bf04185c88161f13118b9975cdff7967d49a4fa0San Mehat if ((rc = Fat::check(devicePath))) { 249a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (errno == ENODATA) { 250a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGW("%s does not contain a FAT filesystem\n", devicePath); 251a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat continue; 252a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 253eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat errno = EIO; 254eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat /* Badness - abort the mount */ 255eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat LOGE("%s failed FS checks (%s)", devicePath, strerror(errno)); 256eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat setState(Volume::State_Idle); 257eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat return -1; 258a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 259a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 260a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = 0; 261fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat if (!(rc = Fat::doMount(devicePath, getMountpoint(), false, false, 262fff0b47998a722d57eea6a07350bbd7a6032b3ccSan Mehat 1000, 1015, 0702, true))) { 263eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat LOGI("%s sucessfully mounted for volume %s\n", devicePath, getLabel()); 264a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat setState(Volume::State_Mounted); 265a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat mCurrentlyMountedKdev = deviceNodes[i]; 266eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat return 0; 267a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 268a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 269a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGW("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno)); 270a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 271a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 272a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGE("Volume %s found no suitable devices for mounting :(\n", getLabel()); 27349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat setState(Volume::State_Idle); 274a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 275eba65e9d438a05f1c5dfd0f8d31bc463a5d08eeeSan Mehat return -1; 276a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 277a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 278a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint Volume::unmountVol() { 279a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat int i, rc; 280a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 281a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (getState() != Volume::State_Mounted) { 282a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGE("Volume %s unmount request when not mounted", getLabel()); 283a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat errno = EINVAL; 284a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 285a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 286a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 287a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat setState(Volume::State_Unmounting); 28862e5dd245bd508eabcba56b5680e2b28bfc2caf6San Mehat usleep(1000 * 200); // Give the framework some time to react 2898c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat for (i = 1; i <= 10; i++) { 290a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat rc = umount(getMountpoint()); 291a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (!rc) 292a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat break; 293a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 294a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (rc && (errno == EINVAL || errno == ENOENT)) { 295a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat rc = 0; 296a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat break; 297a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 298a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 299a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGW("Volume %s unmount attempt %d failed (%s)", 3008c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat getLabel(), i, strerror(errno)); 3018c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat 3028c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat int action; 3038c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat 3048c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat if (i > 8) { 3058c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat action = 2; // SIGKILL 3068c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat } else if (i > 7) { 3078c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat action = 1; // SIGHUP 3088c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat } else 3098c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat action = 0; // just complain 3108c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat 311586536c60b773e3517531ad8a6cb0de6722c67fcSan Mehat Process::killProcessesWithOpenFiles(getMountpoint(), action); 3128c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat usleep(1000*250); 313a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 314a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 315a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (!rc) { 316a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGI("Volume %s unmounted sucessfully", getLabel()); 317a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat setState(Volume::State_Idle); 318a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat mCurrentlyMountedKdev = -1; 319a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return 0; 320a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 321a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 322a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGE("Volume %s failed to unmount (%s)\n", getLabel(), strerror(errno)); 323a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat setState(Volume::State_Mounted); 324a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 325a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 326a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 327a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehatint Volume::initializeMbr(const char *deviceNode) { 328a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat int fd, rc; 329a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat unsigned char block[512]; 330a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat struct dos_partition part; 331a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat unsigned int nr_sec; 332a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 333a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if ((fd = open(deviceNode, O_RDWR)) < 0) { 334a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGE("Error opening disk file (%s)", strerror(errno)); 335a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 336a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 337a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 338a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (ioctl(fd, BLKGETSIZE, &nr_sec)) { 339a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGE("Unable to get device size (%s)", strerror(errno)); 340a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat close(fd); 341a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 342a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 343a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 344a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat memset(&part, 0, sizeof(part)); 345a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat part.dp_flag = 0x80; 346a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat part.dp_typ = 0xc; 347a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat part.dp_start = ((1024 * 64) / 512) + 1; 348a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat part.dp_size = nr_sec - part.dp_start; 349a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 350a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat memset(block, 0, sizeof(block)); 351a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat block[0x1fe] = 0x55; 352a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat block[0x1ff] = 0xaa; 353a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 354a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat dos_partition_enc(block + DOSPARTOFF, &part); 355a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 356a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (write(fd, block, sizeof(block)) < 0) { 357a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGE("Error writing MBR (%s)", strerror(errno)); 358a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat close(fd); 359a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 360a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 361a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat 362a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat if (ioctl(fd, BLKRRPART, NULL) < 0) { 363a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat LOGE("Error re-reading partition table (%s)", strerror(errno)); 364a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat close(fd); 365a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return -1; 366a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat } 367a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat close(fd); 368a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat return 0; 369a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat} 370