1f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat/*
2f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Copyright (C) 2008 The Android Open Source Project
3f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
4f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Licensed under the Apache License, Version 2.0 (the "License");
5f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * you may not use this file except in compliance with the License.
6f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * You may obtain a copy of the License at
7f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
8f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *      http://www.apache.org/licenses/LICENSE-2.0
9f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat *
10f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * Unless required by applicable law or agreed to in writing, software
11f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * distributed under the License is distributed on an "AS IS" BASIS,
12f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * See the License for the specific language governing permissions and
14f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat * limitations under the License.
15f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat */
16f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
17f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <stdio.h>
18f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <stdlib.h>
19f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <errno.h>
20f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include <string.h>
213578c41ef138cb3edf38bb488cb9864921f55c79San Mehat#include <sys/stat.h>
223578c41ef138cb3edf38bb488cb9864921f55c79San Mehat#include <sys/types.h>
233578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
243578c41ef138cb3edf38bb488cb9864921f55c79San Mehat#include <fcntl.h>
253578c41ef138cb3edf38bb488cb9864921f55c79San Mehat#include <dirent.h>
2656ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall#include <fs_mgr.h>
27f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
28f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#define LOG_TAG "Vold"
29f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
30b9738ea9692f887cf2e2fef132519f4e71cc2905Ken Sumrall#include "cutils/klog.h"
31f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "cutils/log.h"
3256ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall#include "cutils/properties.h"
33f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
34f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "VolumeManager.h"
35f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "CommandListener.h"
36f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat#include "NetlinkManager.h"
37ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehat#include "DirectVolume.h"
3829d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall#include "cryptfs.h"
39f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
40f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatstatic int process_config(VolumeManager *vm);
413578c41ef138cb3edf38bb488cb9864921f55c79San Mehatstatic void coldboot(const char *path);
42f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
4356ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall#define FSTAB_PREFIX "/fstab."
4456ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrallstruct fstab *fstab;
4556ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall
46f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatint main() {
47f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
48f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    VolumeManager *vm;
49f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    CommandListener *cl;
50f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    NetlinkManager *nm;
51f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
5297ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    SLOGI("Vold 2.1 (the revenge) firing up");
53a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
54a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat    mkdir("/dev/block/vold", 0755);
55f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
56b9738ea9692f887cf2e2fef132519f4e71cc2905Ken Sumrall    /* For when cryptfs checks and mounts an encrypted filesystem */
57b9738ea9692f887cf2e2fef132519f4e71cc2905Ken Sumrall    klog_set_level(6);
58b9738ea9692f887cf2e2fef132519f4e71cc2905Ken Sumrall
59f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    /* Create our singleton managers */
60f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!(vm = VolumeManager::Instance())) {
6197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to create VolumeManager");
62f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        exit(1);
63f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    };
64f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
65f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (!(nm = NetlinkManager::Instance())) {
6697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to create NetlinkManager");
67f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        exit(1);
68f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    };
69f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
70a2677e4ad01f250b0765f04adf0acfa6627efc98San Mehat
71f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    cl = new CommandListener();
72f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    vm->setBroadcaster((SocketListener *) cl);
73f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    nm->setBroadcaster((SocketListener *) cl);
74f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
75f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (vm->start()) {
7697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to start VolumeManager (%s)", strerror(errno));
77f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        exit(1);
78f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
79f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
80f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (process_config(vm)) {
8197ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Error reading configuration (%s)... continuing anyways", strerror(errno));
82f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
83f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
84f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (nm->start()) {
8597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to start NetlinkManager (%s)", strerror(errno));
86f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        exit(1);
87f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
88f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
893578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    coldboot("/sys/block");
900cde53ce7b44ce189d0bc6fa81c0036e096deb51San Mehat//    coldboot("/sys/class/switch");
913578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
92f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    /*
93f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat     * Now that we're up, we can respond to commands
94f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat     */
95f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    if (cl->startListener()) {
9697ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat        SLOGE("Unable to start CommandListener (%s)", strerror(errno));
97f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        exit(1);
98f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
99f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
100f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    // Eventually we'll become the monitoring thread
101f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    while(1) {
102f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        sleep(1000);
103f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
104f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
10597ac40e4e6f3ed0bd5d6878d7d8d4a54fcaecb76San Mehat    SLOGI("Vold exiting");
106f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    exit(0);
107f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
108f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
1093578c41ef138cb3edf38bb488cb9864921f55c79San Mehatstatic void do_coldboot(DIR *d, int lvl)
1103578c41ef138cb3edf38bb488cb9864921f55c79San Mehat{
1113578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    struct dirent *de;
1123578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    int dfd, fd;
1133578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1143578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    dfd = dirfd(d);
1153578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1163578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    fd = openat(dfd, "uevent", O_WRONLY);
1173578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    if(fd >= 0) {
1183578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        write(fd, "add\n", 4);
1193578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        close(fd);
1203578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    }
1213578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1223578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    while((de = readdir(d))) {
1233578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        DIR *d2;
1243578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1253578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        if (de->d_name[0] == '.')
1263578c41ef138cb3edf38bb488cb9864921f55c79San Mehat            continue;
1273578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1283578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        if (de->d_type != DT_DIR && lvl > 0)
1293578c41ef138cb3edf38bb488cb9864921f55c79San Mehat            continue;
1303578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1313578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
1323578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        if(fd < 0)
1333578c41ef138cb3edf38bb488cb9864921f55c79San Mehat            continue;
1343578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1353578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        d2 = fdopendir(fd);
1363578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        if(d2 == 0)
1373578c41ef138cb3edf38bb488cb9864921f55c79San Mehat            close(fd);
1383578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        else {
1393578c41ef138cb3edf38bb488cb9864921f55c79San Mehat            do_coldboot(d2, lvl + 1);
1403578c41ef138cb3edf38bb488cb9864921f55c79San Mehat            closedir(d2);
1413578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        }
1423578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    }
1433578c41ef138cb3edf38bb488cb9864921f55c79San Mehat}
1443578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
1453578c41ef138cb3edf38bb488cb9864921f55c79San Mehatstatic void coldboot(const char *path)
1463578c41ef138cb3edf38bb488cb9864921f55c79San Mehat{
1473578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    DIR *d = opendir(path);
1483578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    if(d) {
1493578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        do_coldboot(d, 0);
1503578c41ef138cb3edf38bb488cb9864921f55c79San Mehat        closedir(d);
1513578c41ef138cb3edf38bb488cb9864921f55c79San Mehat    }
1523578c41ef138cb3edf38bb488cb9864921f55c79San Mehat}
1533578c41ef138cb3edf38bb488cb9864921f55c79San Mehat
15456ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrallstatic int process_config(VolumeManager *vm)
15529d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall{
15656ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall    char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
15756ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall    char propbuf[PROPERTY_VALUE_MAX];
15856ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall    int i;
15956ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall    int ret = -1;
16056ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall    int flags;
16156ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall
16256ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall    property_get("ro.hardware", propbuf, "");
16356ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall    snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf);
16456ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall
16556ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall    fstab = fs_mgr_read_fstab(fstab_filename);
16656ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall    if (!fstab) {
16756ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall        SLOGE("failed to open %s\n", fstab_filename);
168f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        return -1;
169f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
170f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
17156ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall    /* Loop through entries looking for ones that vold manages */
17256ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall    for (i = 0; i < fstab->num_entries; i++) {
17356ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall        if (fs_mgr_is_voldmanaged(&fstab->recs[i])) {
174ae10b91044bf76b40b77d81c169e48e0bbdf6d75San Mehat            DirectVolume *dv = NULL;
17556ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall            flags = 0;
176f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
17756ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall            /* Set any flags that might be set for this volume */
17856ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall            if (fs_mgr_is_nonremovable(&fstab->recs[i])) {
17956ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall                flags |= VOL_NONREMOVABLE;
18056ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall            }
18156ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall            if (fs_mgr_is_encryptable(&fstab->recs[i])) {
18256ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall                flags |= VOL_ENCRYPTABLE;
183f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            }
184ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey            /* Only set this flag if there is not an emulated sd card */
185ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey            if (fs_mgr_is_noemulatedsd(&fstab->recs[i]) &&
186ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey                !strcmp(fstab->recs[i].fs_type, "vfat")) {
187ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey                flags |= VOL_PROVIDES_ASEC;
188ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey            }
189ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey            dv = new DirectVolume(vm, &(fstab->recs[i]), flags);
190ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey
191ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey            if (dv->addPath(fstab->recs[i].blk_device)) {
192ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey                SLOGE("Failed to add devpath %s to volume %s",
193ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey                      fstab->recs[i].blk_device, fstab->recs[i].label);
194ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey                goto out_fail;
195ba6ae8db137d012c9b8e11f9f8321c7771698e92Jeff Sharkey            }
19629d8da8cefa99e436c13295d4c9bad060ca18a6dKen Sumrall
197f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat            vm->addVolume(dv);
198f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat        }
199f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat    }
200f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
20156ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall    ret = 0;
202f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat
203f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehatout_fail:
20456ad03cae13524b32898dc4ccf01040ced5a53b4Ken Sumrall    return ret;
205f1b736bc5605e92e917ab27f5abf3ba839be2270San Mehat}
206