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 <stdio.h> 18 #include <stdlib.h> 19 #include <errno.h> 20 #include <string.h> 21 #include <sys/stat.h> 22 #include <sys/types.h> 23 24 #include <fcntl.h> 25 #include <dirent.h> 26 #include <fs_mgr.h> 27 28 #define LOG_TAG "Vold" 29 30 #include "cutils/klog.h" 31 #include "cutils/log.h" 32 #include "cutils/properties.h" 33 34 #include "VolumeManager.h" 35 #include "CommandListener.h" 36 #include "NetlinkManager.h" 37 #include "DirectVolume.h" 38 #include "cryptfs.h" 39 40 static int process_config(VolumeManager *vm); 41 static void coldboot(const char *path); 42 43 #define FSTAB_PREFIX "/fstab." 44 struct fstab *fstab; 45 46 int main() { 47 48 VolumeManager *vm; 49 CommandListener *cl; 50 NetlinkManager *nm; 51 52 SLOGI("Vold 2.1 (the revenge) firing up"); 53 54 mkdir("/dev/block/vold", 0755); 55 56 /* For when cryptfs checks and mounts an encrypted filesystem */ 57 klog_set_level(6); 58 59 /* Create our singleton managers */ 60 if (!(vm = VolumeManager::Instance())) { 61 SLOGE("Unable to create VolumeManager"); 62 exit(1); 63 }; 64 65 if (!(nm = NetlinkManager::Instance())) { 66 SLOGE("Unable to create NetlinkManager"); 67 exit(1); 68 }; 69 70 71 cl = new CommandListener(); 72 vm->setBroadcaster((SocketListener *) cl); 73 nm->setBroadcaster((SocketListener *) cl); 74 75 if (vm->start()) { 76 SLOGE("Unable to start VolumeManager (%s)", strerror(errno)); 77 exit(1); 78 } 79 80 if (process_config(vm)) { 81 SLOGE("Error reading configuration (%s)... continuing anyways", strerror(errno)); 82 } 83 84 if (nm->start()) { 85 SLOGE("Unable to start NetlinkManager (%s)", strerror(errno)); 86 exit(1); 87 } 88 89 coldboot("/sys/block"); 90 // coldboot("/sys/class/switch"); 91 92 /* 93 * Now that we're up, we can respond to commands 94 */ 95 if (cl->startListener()) { 96 SLOGE("Unable to start CommandListener (%s)", strerror(errno)); 97 exit(1); 98 } 99 100 // Eventually we'll become the monitoring thread 101 while(1) { 102 sleep(1000); 103 } 104 105 SLOGI("Vold exiting"); 106 exit(0); 107 } 108 109 static void do_coldboot(DIR *d, int lvl) 110 { 111 struct dirent *de; 112 int dfd, fd; 113 114 dfd = dirfd(d); 115 116 fd = openat(dfd, "uevent", O_WRONLY); 117 if(fd >= 0) { 118 write(fd, "add\n", 4); 119 close(fd); 120 } 121 122 while((de = readdir(d))) { 123 DIR *d2; 124 125 if (de->d_name[0] == '.') 126 continue; 127 128 if (de->d_type != DT_DIR && lvl > 0) 129 continue; 130 131 fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY); 132 if(fd < 0) 133 continue; 134 135 d2 = fdopendir(fd); 136 if(d2 == 0) 137 close(fd); 138 else { 139 do_coldboot(d2, lvl + 1); 140 closedir(d2); 141 } 142 } 143 } 144 145 static void coldboot(const char *path) 146 { 147 DIR *d = opendir(path); 148 if(d) { 149 do_coldboot(d, 0); 150 closedir(d); 151 } 152 } 153 154 static int process_config(VolumeManager *vm) 155 { 156 char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; 157 char propbuf[PROPERTY_VALUE_MAX]; 158 int i; 159 int ret = -1; 160 int flags; 161 162 property_get("ro.hardware", propbuf, ""); 163 snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf); 164 165 fstab = fs_mgr_read_fstab(fstab_filename); 166 if (!fstab) { 167 SLOGE("failed to open %s\n", fstab_filename); 168 return -1; 169 } 170 171 /* Loop through entries looking for ones that vold manages */ 172 for (i = 0; i < fstab->num_entries; i++) { 173 if (fs_mgr_is_voldmanaged(&fstab->recs[i])) { 174 DirectVolume *dv = NULL; 175 flags = 0; 176 177 /* Set any flags that might be set for this volume */ 178 if (fs_mgr_is_nonremovable(&fstab->recs[i])) { 179 flags |= VOL_NONREMOVABLE; 180 } 181 if (fs_mgr_is_encryptable(&fstab->recs[i])) { 182 flags |= VOL_ENCRYPTABLE; 183 } 184 /* Only set this flag if there is not an emulated sd card */ 185 if (fs_mgr_is_noemulatedsd(&fstab->recs[i]) && 186 !strcmp(fstab->recs[i].fs_type, "vfat")) { 187 flags |= VOL_PROVIDES_ASEC; 188 } 189 dv = new DirectVolume(vm, &(fstab->recs[i]), flags); 190 191 if (dv->addPath(fstab->recs[i].blk_device)) { 192 SLOGE("Failed to add devpath %s to volume %s", 193 fstab->recs[i].blk_device, fstab->recs[i].label); 194 goto out_fail; 195 } 196 197 vm->addVolume(dv); 198 } 199 } 200 201 ret = 0; 202 203 out_fail: 204 return ret; 205 } 206