main.cpp 6.41 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
21 22
#include <sys/stat.h>
#include <sys/types.h>
23
#include <getopt.h>
24 25 26

#include <fcntl.h>
#include <dirent.h>
Ken Sumrall's avatar
Ken Sumrall committed
27
#include <fs_mgr.h>
28 29 30

#define LOG_TAG "Vold"

31 32
#include <base/logging.h>
#include <base/stringprintf.h>
33
#include "cutils/klog.h"
34
#include "cutils/log.h"
Ken Sumrall's avatar
Ken Sumrall committed
35
#include "cutils/properties.h"
Jeff Sharkey's avatar
Jeff Sharkey committed
36
#include "cutils/sockets.h"
37

38
#include "Disk.h"
39 40 41
#include "VolumeManager.h"
#include "CommandListener.h"
#include "NetlinkManager.h"
42
#include "DirectVolume.h"
43
#include "cryptfs.h"
44
#include "sehandle.h"
45 46

static int process_config(VolumeManager *vm);
47
static void coldboot(const char *path);
48
static void parse_args(int argc, char** argv);
49

50 51
//#define DEBUG_FSTAB "/data/local/tmp/fstab.debug"

Ken Sumrall's avatar
Ken Sumrall committed
52 53
struct fstab *fstab;

54 55
struct selabel_handle *sehandle;

56 57
using android::base::StringPrintf;

58 59 60
int main(int argc, char** argv) {
    SLOGI("Vold 2.1 (the revenge) firing up");

61 62
    setenv("ANDROID_LOG_TAGS", "*:v", 1);
    android::base::InitLogging(argv);
63 64 65 66 67

    VolumeManager *vm;
    CommandListener *cl;
    NetlinkManager *nm;

68
    parse_args(argc, argv);
69

70
    sehandle = selinux_android_file_context_handle();
71
    if (sehandle) {
72
        selinux_android_set_sehandle(sehandle);
73
    }
74

Jeff Sharkey's avatar
Jeff Sharkey committed
75 76 77
    // Quickly throw a CLOEXEC on the socket we just inherited from init
    fcntl(android_get_control_socket("vold"), F_SETFD, FD_CLOEXEC);

78
    mkdir("/dev/block/vold", 0755);
79

80 81 82
    /* For when cryptfs checks and mounts an encrypted filesystem */
    klog_set_level(6);

83 84
    /* Create our singleton managers */
    if (!(vm = VolumeManager::Instance())) {
San Mehat's avatar
San Mehat committed
85
        SLOGE("Unable to create VolumeManager");
86
        exit(1);
87
    }
88 89

    if (!(nm = NetlinkManager::Instance())) {
San Mehat's avatar
San Mehat committed
90
        SLOGE("Unable to create NetlinkManager");
91
        exit(1);
92
    }
93

94 95 96 97 98
    cl = new CommandListener();
    vm->setBroadcaster((SocketListener *) cl);
    nm->setBroadcaster((SocketListener *) cl);

    if (vm->start()) {
San Mehat's avatar
San Mehat committed
99
        SLOGE("Unable to start VolumeManager (%s)", strerror(errno));
100 101 102 103
        exit(1);
    }

    if (process_config(vm)) {
San Mehat's avatar
San Mehat committed
104
        SLOGE("Error reading configuration (%s)... continuing anyways", strerror(errno));
105 106 107
    }

    if (nm->start()) {
San Mehat's avatar
San Mehat committed
108
        SLOGE("Unable to start NetlinkManager (%s)", strerror(errno));
109 110 111
        exit(1);
    }

112
    coldboot("/sys/block");
113
//    coldboot("/sys/class/switch");
114

115 116 117 118
    /*
     * Now that we're up, we can respond to commands
     */
    if (cl->startListener()) {
San Mehat's avatar
San Mehat committed
119
        SLOGE("Unable to start CommandListener (%s)", strerror(errno));
120 121 122 123 124 125 126 127
        exit(1);
    }

    // Eventually we'll become the monitoring thread
    while(1) {
        sleep(1000);
    }

San Mehat's avatar
San Mehat committed
128
    SLOGI("Vold exiting");
129 130 131
    exit(0);
}

132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
static void parse_args(int argc, char** argv) {
    static struct option opts[] = {
        {"blkid_context", required_argument, 0, 'b' },
        {"blkid_untrusted_context", required_argument, 0, 'B' },
        {"fsck_context", required_argument, 0, 'f' },
        {"fsck_untrusted_context", required_argument, 0, 'F' },
    };

    int c;
    while ((c = getopt_long(argc, argv, "", opts, nullptr)) != -1) {
        switch (c) {
        case 'b': android::vold::sBlkidContext = optarg; break;
        case 'B': android::vold::sBlkidUntrustedContext = optarg; break;
        case 'f': android::vold::sFsckContext = optarg; break;
        case 'F': android::vold::sFsckUntrustedContext = optarg; break;
        }
    }

    CHECK(android::vold::sBlkidContext != nullptr);
    CHECK(android::vold::sBlkidUntrustedContext != nullptr);
    CHECK(android::vold::sFsckContext != nullptr);
    CHECK(android::vold::sFsckUntrustedContext != nullptr);
}

static void do_coldboot(DIR *d, int lvl) {
157 158 159 160 161
    struct dirent *de;
    int dfd, fd;

    dfd = dirfd(d);

Jeff Sharkey's avatar
Jeff Sharkey committed
162
    fd = openat(dfd, "uevent", O_WRONLY | O_CLOEXEC);
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
    if(fd >= 0) {
        write(fd, "add\n", 4);
        close(fd);
    }

    while((de = readdir(d))) {
        DIR *d2;

        if (de->d_name[0] == '.')
            continue;

        if (de->d_type != DT_DIR && lvl > 0)
            continue;

        fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
        if(fd < 0)
            continue;

        d2 = fdopendir(fd);
        if(d2 == 0)
            close(fd);
        else {
            do_coldboot(d2, lvl + 1);
            closedir(d2);
        }
    }
}

191
static void coldboot(const char *path) {
192 193 194 195 196 197 198
    DIR *d = opendir(path);
    if(d) {
        do_coldboot(d, 0);
        closedir(d);
    }
}

199
static int process_config(VolumeManager *vm) {
200 201 202 203 204 205 206 207 208 209
    char hardware[PROPERTY_VALUE_MAX];
    property_get("ro.hardware", hardware, "");
    std::string fstab_filename(StringPrintf("/fstab.%s", hardware));

#ifdef DEBUG_FSTAB
    if (access(DEBUG_FSTAB, R_OK) == 0) {
        LOG(DEBUG) << "Found debug fstab; switching!";
        fstab_filename = DEBUG_FSTAB;
    }
#endif
Ken Sumrall's avatar
Ken Sumrall committed
210

211
    fstab = fs_mgr_read_fstab(fstab_filename.c_str());
Ken Sumrall's avatar
Ken Sumrall committed
212
    if (!fstab) {
213
        PLOG(ERROR) << "Failed to open " << fstab_filename;
214 215 216
        return -1;
    }

Ken Sumrall's avatar
Ken Sumrall committed
217
    /* Loop through entries looking for ones that vold manages */
218
    for (int i = 0; i < fstab->num_entries; i++) {
Ken Sumrall's avatar
Ken Sumrall committed
219 220
        if (fs_mgr_is_voldmanaged(&fstab->recs[i])) {
            if (fs_mgr_is_nonremovable(&fstab->recs[i])) {
221 222
                LOG(WARNING) << "nonremovable no longer supported; ignoring volume";
                continue;
Ken Sumrall's avatar
Ken Sumrall committed
223
            }
224 225 226 227 228

            std::string sysPattern(fstab->recs[i].blk_device);
            std::string nickname(fstab->recs[i].label);
            int flags = 0;

Ken Sumrall's avatar
Ken Sumrall committed
229
            if (fs_mgr_is_encryptable(&fstab->recs[i])) {
230
                flags |= android::vold::Disk::Flags::kAdoptable;
231
            }
232 233
            if (fs_mgr_is_noemulatedsd(&fstab->recs[i])) {
                flags |= android::vold::Disk::Flags::kDefaultPrimary;
234 235
            }

236 237
            vm->addDiskSource(std::shared_ptr<VolumeManager::DiskSource>(
                    new VolumeManager::DiskSource(sysPattern, nickname, flags)));
238 239 240
        }
    }

241
    return 0;
242
}