Volume.cpp revision 49e2bce5b74129c26a35e25d4693cbfe98c4688e
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdlib.h> 18#include <string.h> 19#include <dirent.h> 20#include <errno.h> 21#include <fcntl.h> 22 23#include <sys/types.h> 24#include <sys/stat.h> 25#include <sys/types.h> 26#include <sys/mman.h> 27 28#define LOG_TAG "Vold" 29 30#include <cutils/log.h> 31 32#include "Volume.h" 33 34extern "C" int logwrap(int argc, const char **argv, int background); 35 36static char FSCK_MSDOS_PATH[] = "/system/bin/fsck_msdos"; 37 38Volume::Volume(const char *label, const char *mount_point) { 39 mLabel = strdup(label); 40 mMountpoint = strdup(mount_point); 41 mState = Volume::State_Init; 42} 43 44Volume::~Volume() { 45 free(mLabel); 46 free(mMountpoint); 47} 48 49int Volume::handleBlockEvent(NetlinkEvent *evt) { 50 errno = ENOSYS; 51 return -1; 52} 53 54void Volume::setState(int state) { 55 LOGD("Volume %s state changing %d -> %d", mLabel, mState, state); 56 mState = state; 57} 58 59int Volume::mount() { 60 char nodepath[255]; 61 int major = -1, minor = -1; 62 63 if (prepareToMount(&major, &minor)) { 64 LOGE("Volume failed to prepare: %s", strerror(errno)); 65 return -1; 66 } 67 68 /* Create device nodes */ 69 mode_t mode = 0660 | S_IFBLK; 70 dev_t dev = (major << 8) | minor; 71 sprintf(nodepath, "/dev/block/vold/%d:%d", major, minor); 72 if (mknod(nodepath, mode, dev) < 0) { 73 LOGE("Error making device nodes for '%s' (%s)", 74 nodepath, strerror(errno)); 75 return -1; 76 } 77 78 /* Run disk checker */ 79 if (checkFilesystem(nodepath)) { 80 setState(Volume::State_Idle); 81 return -1; 82 } 83 84 setState(Volume::State_Idle); 85 return 0; 86} 87 88int Volume::checkFilesystem(const char *nodepath) { 89 90 bool rw = true; 91 if (access(FSCK_MSDOS_PATH, X_OK)) { 92 LOGW("Skipping fs checks\n"); 93 return 0; 94 } 95 96 setState(Volume::State_Checking); 97 int pass = 1; 98 int rc = 0; 99 do { 100 const char *args[5]; 101 args[0] = FSCK_MSDOS_PATH; 102 args[1] = "-p"; 103 args[2] = "-f"; 104 args[3] = nodepath; 105 args[4] = NULL; 106 107 rc = logwrap(4, args, 1); 108 109 switch(rc) { 110 case 0: 111 LOGI("Filesystem check completed OK"); 112 return 0; 113 114 case 2: 115 LOGE("Filesystem check failed (not a FAT filesystem)"); 116 errno = ENODATA; 117 return -1; 118 119 case 4: 120 if (pass++ <= 3) { 121 LOGW("Filesystem modified - rechecking (pass %d)", 122 pass); 123 continue; 124 } 125 LOGE("Failing check after too many rechecks"); 126 errno = EIO; 127 return -1; 128 129 default: 130 LOGE("Filesystem check failed (unknown exit code %d)", rc); 131 errno = EIO; 132 return -1; 133 } 134 } while (0); 135 136 return 0; 137} 138 139int Volume::unmount() { 140 return 0; 141} 142