Volume.cpp revision dd9b8e92aaf330b48ddb40a7380588ef92b53de6
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::createDeviceNode(const char *path, int major, int minor) { 60 mode_t mode = 0660 | S_IFBLK; 61 dev_t dev = (major << 8) | minor; 62 if (mknod(path, mode, dev) < 0) { 63 if (errno != EEXIST) { 64 return -1; 65 } 66 } 67 return 0; 68} 69 70int Volume::mount() { 71 char nodepath[255]; 72 int major = -1, minor = -1; 73 74 if (prepareToMount(&major, &minor)) { 75 LOGE("Volume failed to prepare: %s", strerror(errno)); 76 return -1; 77 } 78 79 sprintf(nodepath, "/dev/block/vold/%d:%d", major, minor); 80 81 LOGD("nodepath = %s\n", nodepath); 82 83 /* Create device nodes */ 84 if (createDeviceNode(nodepath, major, minor)) { 85 LOGE("Error making device nodes for '%s' (%s)", nodepath, 86 strerror(errno)); 87 // XXX: cleanup will be needed eventually 88 return -1; 89 } 90 91 /* Run disk checker */ 92 if (checkFilesystem(nodepath)) { 93 LOGE("Error checking filesystem (%s)", strerror(errno)); 94 setState(Volume::State_Idle); 95 return -1; 96 } 97 98 99 100 setState(Volume::State_Idle); 101 return 0; 102} 103 104int Volume::checkFilesystem(const char *nodepath) { 105 106 bool rw = true; 107 if (access(FSCK_MSDOS_PATH, X_OK)) { 108 LOGW("Skipping fs checks\n"); 109 return 0; 110 } 111 112 setState(Volume::State_Checking); 113 int pass = 1; 114 int rc = 0; 115 do { 116 const char *args[5]; 117 args[0] = FSCK_MSDOS_PATH; 118 args[1] = "-p"; 119 args[2] = "-f"; 120 args[3] = nodepath; 121 args[4] = NULL; 122 123 rc = logwrap(4, args, 1); 124 125 switch(rc) { 126 case 0: 127 LOGI("Filesystem check completed OK"); 128 return 0; 129 130 case 2: 131 LOGE("Filesystem check failed (not a FAT filesystem)"); 132 errno = ENODATA; 133 return -1; 134 135 case 4: 136 if (pass++ <= 3) { 137 LOGW("Filesystem modified - rechecking (pass %d)", 138 pass); 139 continue; 140 } 141 LOGE("Failing check after too many rechecks"); 142 errno = EIO; 143 return -1; 144 145 default: 146 LOGE("Filesystem check failed (unknown exit code %d)", rc); 147 errno = EIO; 148 return -1; 149 } 150 } while (0); 151 152 return 0; 153} 154 155int Volume::unmount() { 156 return 0; 157} 158