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 ®ex = 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; }
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"); }
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; }