Home | History | Annotate | Download | only in vold
      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             dv = new DirectVolume(vm, fstab->recs[i].label,
    178                                   fstab->recs[i].mount_point,
    179                                   fstab->recs[i].partnum);
    180 
    181             if (dv->addPath(fstab->recs[i].blk_device)) {
    182                 SLOGE("Failed to add devpath %s to volume %s",
    183                       fstab->recs[i].blk_device, fstab->recs[i].label);
    184                 goto out_fail;
    185             }
    186 
    187             /* Set any flags that might be set for this volume */
    188             if (fs_mgr_is_nonremovable(&fstab->recs[i])) {
    189                 flags |= VOL_NONREMOVABLE;
    190             }
    191             if (fs_mgr_is_encryptable(&fstab->recs[i])) {
    192                 flags |= VOL_ENCRYPTABLE;
    193             }
    194             dv->setFlags(flags);
    195 
    196             vm->addVolume(dv);
    197         }
    198     }
    199 
    200     ret = 0;
    201 
    202 out_fail:
    203     return ret;
    204 }
    205