Volume.cpp revision dd9b8e92aaf330b48ddb40a7380588ef92b53de6
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> 27f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 28f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#define LOG_TAG "Vold" 29f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 30f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <cutils/log.h> 31f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 32f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "Volume.h" 33f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 3449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatextern "C" int logwrap(int argc, const char **argv, int background); 3549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 3649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatstatic char FSCK_MSDOS_PATH[] = "/system/bin/fsck_msdos"; 3749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 38f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolume::Volume(const char *label, const char *mount_point) { 39f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat mLabel = strdup(label); 40f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat mMountpoint = strdup(mount_point); 41f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat mState = Volume::State_Init; 42f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 43f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 44f1b736bc5605e92e917ab27f5abf3ba839be2270San MehatVolume::~Volume() { 45f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat free(mLabel); 46f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat free(mMountpoint); 47f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 48f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 49fd7f5875129adfe2845f4f3fffb17db3a89eea25San Mehatint Volume::handleBlockEvent(NetlinkEvent *evt) { 50f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat errno = ENOSYS; 51f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat return -1; 52f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 53f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat 54f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatvoid Volume::setState(int state) { 55f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat LOGD("Volume %s state changing %d -> %d", mLabel, mState, state); 56f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat mState = state; 57f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat} 5849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 59dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehatint Volume::createDeviceNode(const char *path, int major, int minor) { 60dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat mode_t mode = 0660 | S_IFBLK; 61dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat dev_t dev = (major << 8) | minor; 62dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat if (mknod(path, mode, dev) < 0) { 63dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat if (errno != EEXIST) { 64dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat return -1; 65dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat } 66dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat } 67dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat return 0; 68dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat} 69dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat 7049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint Volume::mount() { 7149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat char nodepath[255]; 7249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat int major = -1, minor = -1; 7349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 7449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat if (prepareToMount(&major, &minor)) { 7549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat LOGE("Volume failed to prepare: %s", strerror(errno)); 7649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return -1; 7749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 7849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 7949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat sprintf(nodepath, "/dev/block/vold/%d:%d", major, minor); 80dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat 81dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat LOGD("nodepath = %s\n", nodepath); 82dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat 83dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat /* Create device nodes */ 84dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat if (createDeviceNode(nodepath, major, minor)) { 85dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat LOGE("Error making device nodes for '%s' (%s)", nodepath, 86dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat strerror(errno)); 87dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat // XXX: cleanup will be needed eventually 8849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return -1; 8949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 9049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 9149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat /* Run disk checker */ 9249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat if (checkFilesystem(nodepath)) { 93dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat LOGE("Error checking filesystem (%s)", strerror(errno)); 9449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat setState(Volume::State_Idle); 9549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return -1; 9649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 9749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 98dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat 99dd9b8e92aaf330b48ddb40a7380588ef92b53de6San Mehat 10049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat setState(Volume::State_Idle); 10149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return 0; 10249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat} 10349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 10449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint Volume::checkFilesystem(const char *nodepath) { 10549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 10649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat bool rw = true; 10749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat if (access(FSCK_MSDOS_PATH, X_OK)) { 10849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat LOGW("Skipping fs checks\n"); 10949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return 0; 11049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 11149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 11249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat setState(Volume::State_Checking); 11349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat int pass = 1; 11449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat int rc = 0; 11549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat do { 11649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat const char *args[5]; 11749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat args[0] = FSCK_MSDOS_PATH; 11849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat args[1] = "-p"; 11949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat args[2] = "-f"; 12049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat args[3] = nodepath; 12149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat args[4] = NULL; 12249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 12349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat rc = logwrap(4, args, 1); 12449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 12549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat switch(rc) { 12649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat case 0: 12749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat LOGI("Filesystem check completed OK"); 12849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return 0; 12949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 13049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat case 2: 13149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat LOGE("Filesystem check failed (not a FAT filesystem)"); 13249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat errno = ENODATA; 13349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return -1; 13449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 13549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat case 4: 13649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat if (pass++ <= 3) { 13749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat LOGW("Filesystem modified - rechecking (pass %d)", 13849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat pass); 13949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat continue; 14049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 14149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat LOGE("Failing check after too many rechecks"); 14249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat errno = EIO; 14349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return -1; 14449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 14549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat default: 14649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat LOGE("Filesystem check failed (unknown exit code %d)", rc); 14749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat errno = EIO; 14849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return -1; 14949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } 15049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat } while (0); 15149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 15249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return 0; 15349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat} 15449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat 15549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint Volume::unmount() { 15649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat return 0; 15749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat} 158