Пример #1
0
FileContextsResult patch_file_contexts(const char *source_path,
                                       const char *target_path)
{
    ContextsList list;

    autoclose::file fp_old(autoclose::fopen(source_path, "rb"));
    if (!fp_old) {
        return FileContextsResult::ERRNO;
    }

    if (!load_file(fp_old.get(), &list)) {
        return FileContextsResult::PARSE_ERROR;
    }

    fp_old.reset();

    autoclose::file fp_new(autoclose::fopen(target_path, "w"));
    if (!fp_new) {
        return FileContextsResult::ERRNO;
    }

    for (auto const &pair : list) {
        auto const &context = pair.first;
        auto const &regex = pair.second;

        if (fputs(regex.c_str(), fp_new.get()) == EOF
                || fputc(' ', fp_new.get()) == EOF
                || fputs(context.c_str(), fp_new.get()) == EOF
                || fputc('\n', fp_new.get()) == EOF) {
            return FileContextsResult::ERRNO;
        }
    }

    return FileContextsResult::OK;
}
Пример #2
0
static bool fix_file_contexts()
{
    autoclose::file fp_old(autoclose::fopen("/file_contexts", "rb"));
    if (!fp_old) {
        if (errno == ENOENT) {
            return true;
        } else {
            LOGE("Failed to open /file_contexts: %s", strerror(errno));
            return false;
        }
    }

    autoclose::file fp_new(autoclose::fopen("/file_contexts.new", "wb"));
    if (!fp_new) {
        LOGE("Failed to open /file_contexts.new for writing: %s",
             strerror(errno));
        return false;
    }

    char *line = nullptr;
    size_t len = 0;
    ssize_t read = 0;

    auto free_line = util::finally([&] {
        free(line);
    });

    while ((read = getline(&line, &len, fp_old.get())) >= 0) {
        if (util::starts_with(line, "/data/media(")
                && !strstr(line, "<<none>>")) {
            continue;
        }

        if (fwrite(line, 1, read, fp_new.get()) != (std::size_t) read) {
            LOGE("Failed to write to /file_contexts.new: %s", strerror(errno));
            return false;
        }
    }

    static const char *new_contexts =
        "\n"
        "/data/media              <<none>>\n"
        "/data/media/[0-9]+(/.*)? <<none>>\n"
        "/raw(/.*)?               <<none>>\n"
        "/data/multiboot(/.*)?    <<none>>\n"
        "/cache/multiboot(/.*)?   <<none>>\n"
        "/system/multiboot(/.*)?  <<none>>\n";
    fputs(new_contexts, fp_new.get());

    return replace_file("/file_contexts", "/file_contexts.new");
}
Пример #3
0
static bool add_mbtool_services()
{
    autoclose::file fp_old(autoclose::fopen("/init.rc", "rb"));
    if (!fp_old) {
        if (errno == ENOENT) {
            return true;
        } else {
            LOGE("Failed to open /init.rc: %s", strerror(errno));
            return false;
        }
    }

    autoclose::file fp_new(autoclose::fopen("/init.rc.new", "wb"));
    if (!fp_new) {
        LOGE("Failed to open /init.rc.new for writing: %s",
             strerror(errno));
        return false;
    }

    char *line = nullptr;
    size_t len = 0;
    ssize_t read = 0;

    auto free_line = util::finally([&] {
        free(line);
    });

    bool has_init_multiboot_rc = false;
    bool has_disabled_installd = false;
    bool inside_service = false;

    while ((read = getline(&line, &len, fp_old.get())) >= 0) {
        if (strstr(line, "import /init.multiboot.rc")) {
            has_init_multiboot_rc = true;
        }

        if (util::starts_with(line, "service")) {
            inside_service = strstr(line, "installd") != nullptr;
        } else if (inside_service && is_completely_whitespace(line)) {
            inside_service = false;
        }

        if (inside_service && strstr(line, "disabled")) {
            has_disabled_installd = true;
        }
    }

    rewind(fp_old.get());

    while ((read = getline(&line, &len, fp_old.get())) >= 0) {
        // Load /init.multiboot.rc
        if (!has_init_multiboot_rc && line[0] != '#') {
            has_init_multiboot_rc = true;
            fputs("import /init.multiboot.rc\n", fp_new.get());
        }

        if (fwrite(line, 1, read, fp_new.get()) != (std::size_t) read) {
            LOGE("Failed to write to /init.rc.new: %s", strerror(errno));
            return false;
        }

        // Disable installd. mbtool's appsync will spawn it on demand
        if (!has_disabled_installd
                && util::starts_with(line, "service")
                && strstr(line, "installd")) {
            fputs("    disabled\n", fp_new.get());
        }
    }

    if (!replace_file("/init.rc", "/init.rc.new")) {
        return false;
    }

    // Create /init.multiboot.rc
    autoclose::file fp_multiboot(autoclose::fopen("/init.multiboot.rc", "wb"));
    if (!fp_multiboot) {
        LOGE("Failed to open /init.multiboot.rc for writing: %s",
             strerror(errno));
        return false;
    }

    static const char *init_multiboot_rc =
        "service mbtooldaemon /mbtool daemon\n"
        "    class main\n"
        "    user root\n"
        "    oneshot\n"
        "\n"
        "service appsync /mbtool appsync\n"
        "    class main\n"
        "    socket installd stream 600 system system\n";

    fputs(init_multiboot_rc, fp_multiboot.get());

    fchmod(fileno(fp_multiboot.get()), 0750);

    return true;
}