bool MROMInstaller::hasEntry(const std::string& name)
{
	ZipArchive zip;
#if (ANDROID_VERSION >= 5)
	MemMapping map;
	if (sysMapFile(m_file.c_str(), &map) != 0) {
		LOGERR("Failed to sysMapFile '%s'\n", m_file.c_str());
		return false;
	}

	if (mzOpenZipArchive(map.addr, map.length, &zip) != 0)
#else
	if (mzOpenZipArchive(m_file.c_str(), &zip) != 0)
#endif
	{
		gui_print("Failed to open ZIP file %s\n", m_file.c_str());
#if (ANDROID_VERSION >= 5)
	sysReleaseMap(&map);
#endif
		return false;
	}

	// Check also for entry with / - according to minzip, folders
	// usually (but not always) end with /
	const ZipEntry *entry1 = mzFindZipEntry(&zip, name.c_str());
	const ZipEntry *entry2 = mzFindZipEntry(&zip, (name + "/").c_str());

	mzCloseZipArchive(&zip);
#if (ANDROID_VERSION >= 5)
	sysReleaseMap(&map);
#endif

	return entry1 || entry2;
}
Пример #2
0
bool MROMInstaller::extractDir(const std::string& name, const std::string& dest)
{
	ZipArchive zip;

	MemMapping map;
	if (sysMapFile(m_file.c_str(), &map) != 0) {
		LOGERR("Failed to sysMapFile '%s'\n", m_file.c_str());
		return false;
	}

	if (mzOpenZipArchive(map.addr, map.length, &zip) != 0)
	{
		gui_print("Failed to open ZIP file %s\n", m_file.c_str());
		sysReleaseMap(&map);
		return false;
	}

	// To create a consistent system image, never use the clock for timestamps.
    struct utimbuf timestamp = { 1217592000, 1217592000 };  // 8/1/2008 default
	bool success = mzExtractRecursive(&zip, name.c_str(), dest.c_str(), MZ_EXTRACT_FILES_ONLY, &timestamp, NULL, NULL, NULL);

	mzCloseZipArchive(&zip);
	sysReleaseMap(&map);

	if(!success)
	{
		gui_print("Failed to extract dir %s from zip %s\n", name.c_str(), m_file.c_str());
		return false;
	}
	return true;
}
extern "C" int TWinstall_zip(const char* path, int* wipe_cache) {
	int ret_val, zip_verify = 1, md5_return, key_count;
	twrpDigest md5sum;
	string strpath = path;
	ZipArchive Zip;

	if (strcmp(path, "error") == 0) {
		LOGERR("Failed to get adb sideload file: '%s'\n", path);
		return INSTALL_CORRUPT;
	}

	gui_print("Installing '%s'...\n", path);
	if (strlen(path) < 9 || strncmp(path, "/sideload", 9) != 0) {
		gui_print("Checking for MD5 file...\n");
		md5sum.setfn(strpath);
		md5_return = md5sum.verify_md5digest();
		if (md5_return == -2) { // md5 did not match
			LOGERR("Aborting zip install\n");
			return INSTALL_CORRUPT;
		}
	}

#ifndef TW_OEM_BUILD
	DataManager::GetValue(TW_SIGNED_ZIP_VERIFY_VAR, zip_verify);
#endif
	DataManager::SetProgress(0);

	MemMapping map;
	if (sysMapFile(path, &map) != 0) {
		LOGERR("Failed to sysMapFile '%s'\n", path);
        return -1;
    }

	if (zip_verify) {
		gui_print("Verifying zip signature...\n");
		ret_val = verify_file(map.addr, map.length);
		if (ret_val != VERIFY_SUCCESS) {
			LOGERR("Zip signature verification failed: %i\n", ret_val);
			sysReleaseMap(&map);
			return -1;
		} else {
			gui_print("Zip signature verified successfully.\n");
		}
	}
	ret_val = mzOpenZipArchive(map.addr, map.length, &Zip);
	if (ret_val != 0) {
		LOGERR("Zip file is corrupt!\n", path);
		sysReleaseMap(&map);
		return INSTALL_CORRUPT;
	}
	ret_val = Run_Update_Binary(path, &Zip, wipe_cache);
	sysReleaseMap(&map);
	return ret_val;
}
bool MROMInstaller::extractFile(const std::string& name, const std::string& dest)
{
	ZipArchive zip;
#if (ANDROID_VERSION >= 5)
	MemMapping map;
	if (sysMapFile(m_file.c_str(), &map) != 0) {
		LOGERR("Failed to sysMapFile '%s'\n", m_file.c_str());
		return false;
	}

	if (mzOpenZipArchive(map.addr, map.length, &zip) != 0)
#else
	if (mzOpenZipArchive(m_file.c_str(), &zip) != 0)
#endif
	{
		gui_print("Failed to open ZIP file %s\n", m_file.c_str());
#if (ANDROID_VERSION >= 5)
	sysReleaseMap(&map);
#endif
		return false;
	}

	bool res = false;
	FILE* f = NULL;
	const ZipEntry* entry = mzFindZipEntry(&zip, name.c_str());
	if (entry == NULL)
	{
		gui_print("Could not find file %s in zip %s\n", name.c_str(), m_file.c_str());
		goto exit;
	}

	f = fopen(dest.c_str(), "wb");
	if(!f)
	{
		gui_print("Could not open dest file %s for writing!\n", dest.c_str());
		goto exit;
	}

	res = mzExtractZipEntryToFile(&zip, entry, fileno(f));
	if(!res)
		gui_print("Failed to extract file %s from the ZIP!", name.c_str());

	fclose(f);
exit:
	mzCloseZipArchive(&zip);
#if (ANDROID_VERSION >= 5)
	sysReleaseMap(&map);
#endif
	return res;
}
Пример #5
0
int main(int argc, char** argv) {
    // Various things log information to stdout or stderr more or less
    // at random (though we've tried to standardize on stdout).  The
    // log file makes more sense if buffering is turned off so things
    // appear in the right order.
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);

    if (argc != 4) {
        printf("unexpected number of arguments (%d)\n", argc);
        return 1;
    }

    char* version = argv[1];
    if ((version[0] != '1' && version[0] != '2' && version[0] != '3') ||
        version[1] != '\0') {
        // We support version 1, 2, or 3.
        printf("wrong updater binary API; expected 1, 2, or 3; "
                        "got %s\n",
                argv[1]);
        return 2;
    }

    // Set up the pipe for sending commands back to the parent process.

    int fd = atoi(argv[2]);
    FILE* cmd_pipe = fdopen(fd, "wb");
    setlinebuf(cmd_pipe);

    // Extract the script from the package.

    const char* package_filename = argv[3];
    MemMapping map;
    if (sysMapFile(package_filename, &map) != 0) {
        printf("failed to map package %s\n", argv[3]);
        return 3;
    }
    ZipArchive za;
    int err;
    err = mzOpenZipArchive(map.addr, map.length, &za);
    if (err != 0) {
        printf("failed to open package %s: %s\n",
               argv[3], strerror(err));
        return 3;
    }

    const ZipEntry* script_entry = mzFindZipEntry(&za, SCRIPT_NAME);
    if (script_entry == NULL) {
        printf("failed to find %s in %s\n", SCRIPT_NAME, package_filename);
        return 4;
    }

    char* script = malloc(script_entry->uncompLen+1);
    if (!mzReadZipEntry(&za, script_entry, script, script_entry->uncompLen)) {
        printf("failed to read script from package\n");
        return 5;
    }
    script[script_entry->uncompLen] = '\0';

    const ZipEntry* file_contexts_entry = mzFindZipEntry(&za, SELINUX_CONTEXTS_ZIP);
    if (file_contexts_entry != NULL) {
        int file_contexts_fd = creat(SELINUX_CONTEXTS_TMP, 0644);
		if (file_contexts_fd < 0) {
			fprintf(stderr, "Could not extract %s to '%s'\n", SELINUX_CONTEXTS_ZIP, SELINUX_CONTEXTS_TMP);
			return 3;
		}

		int ret_val = mzExtractZipEntryToFile(&za, file_contexts_entry, file_contexts_fd);
		close(file_contexts_fd);

		if (!ret_val) {
			fprintf(stderr, "Could not extract '%s'\n", SELINUX_CONTEXTS_ZIP);
			return 3;
		}
    }

    // Configure edify's functions.

    RegisterBuiltins();
    RegisterInstallFunctions();
    RegisterBlockImageFunctions();
    RegisterDeviceExtensions();
    FinishRegistration();

    // Parse the script.

    Expr* root;
    int error_count = 0;
    int error = parse_string(script, &root, &error_count);
    if (error != 0 || error_count > 0) {
        printf("%d parse errors\n", error_count);
        return 6;
    }

    if (access(SELINUX_CONTEXTS_TMP, R_OK) == 0) {
        struct selinux_opt seopts[] = {
          { SELABEL_OPT_PATH, SELINUX_CONTEXTS_TMP }
        };

        sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);
    } else {
        struct selinux_opt seopts[] = {
          { SELABEL_OPT_PATH, "/file_contexts" }
        };

        sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);
    }

    if (!sehandle) {
        fprintf(cmd_pipe, "ui_print Warning: No file_contexts\n");
    }

    // Evaluate the parsed script.

    UpdaterInfo updater_info;
    updater_info.cmd_pipe = cmd_pipe;
    updater_info.package_zip = &za;
    updater_info.version = atoi(version);
    updater_info.package_zip_addr = map.addr;
    updater_info.package_zip_len = map.length;

    State state;
    state.cookie = &updater_info;
    state.script = script;
    state.errmsg = NULL;

    char* result = Evaluate(&state, root);
    if (result == NULL) {
        if (state.errmsg == NULL) {
            printf("script aborted (no error message)\n");
            fprintf(cmd_pipe, "ui_print script aborted (no error message)\n");
        } else {
            printf("script aborted: %s\n", state.errmsg);
            char* line = strtok(state.errmsg, "\n");
            while (line) {
                fprintf(cmd_pipe, "ui_print %s\n", line);
                line = strtok(NULL, "\n");
            }
            fprintf(cmd_pipe, "ui_print\n");
        }
        free(state.errmsg);
        return 7;
    } else {
        fprintf(cmd_pipe, "ui_print script succeeded: result was [%s]\n", result);
        free(result);
    }

    if (updater_info.package_zip) {
        mzCloseZipArchive(updater_info.package_zip);
    }
    sysReleaseMap(&map);
    free(script);

    return 0;
}
Пример #6
0
static int
really_install_package(const char *path, bool* wipe_cache, bool needs_mount)
{
    ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
    ui->Print("Finding update package...\n");
    // Give verification half the progress bar...
    ui->SetProgressType(RecoveryUI::DETERMINATE);
    ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME);
    LOGI("Update location: %s\n", path);

    // Map the update package into memory.
    ui->Print("Opening update package...\n");

    if (path && needs_mount) {
        if (path[0] == '@') {
            ensure_path_mounted(path+1);
        } else {
            ensure_path_mounted(path);
        }
    }

    MemMapping map;
    if (sysMapFile(path, &map) != 0) {
        LOGE("failed to map file\n");
        return INSTALL_CORRUPT;
    }

    int numKeys;
    Certificate* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys);
    if (loadedKeys == NULL) {
        LOGE("Failed to load keys\n");
        return INSTALL_CORRUPT;
    }
    LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE);

    ui->Print("Verifying update package...\n");

    int err;
    err = verify_file(map.addr, map.length, loadedKeys, numKeys);
    free(loadedKeys);
    LOGI("verify_file returned %d\n", err);
    if (err != VERIFY_SUCCESS) {
        LOGE("signature verification failed\n");
        sysReleaseMap(&map);
        return INSTALL_CORRUPT;
    }

    /* Try to open the package.
     */
    ZipArchive zip;
    err = mzOpenZipArchive(map.addr, map.length, &zip);
    if (err != 0) {
        LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad");
        sysReleaseMap(&map);
        return INSTALL_CORRUPT;
    }

    /* Verify and install the contents of the package.
     */
    ui->Print("Installing update...\n");
    ui->SetEnableReboot(false);
    int result = try_update_binary(path, &zip, wipe_cache);
    ui->SetEnableReboot(true);
    ui->Print("\n");

    sysReleaseMap(&map);

    return result;
}
std::string MROMInstaller::open(const std::string& file)
{
	char* manifest = NULL;
	const ZipEntry *script_entry;
	ZipArchive zip;

#if (ANDROID_VERSION >= 5)
	MemMapping map;
	if (sysMapFile(file.c_str(), &map) != 0) {
		LOGERR("Failed to sysMapFile '%s'\n", file.c_str());
		return false;
	}

	if (mzOpenZipArchive(map.addr, map.length, &zip) != 0)
#else
	if (mzOpenZipArchive(file.c_str(), &zip) != 0)
#endif
		return "Failed to open installer file!";

	script_entry = mzFindZipEntry(&zip, "manifest.txt");
	if(!script_entry)
	{
		mzCloseZipArchive(&zip);
#if (ANDROID_VERSION >= 5)
		sysReleaseMap(&map);
#endif
		return "Failed to find manifest.txt";
	}

	int res = read_data(&zip, script_entry, &manifest, NULL);

	mzCloseZipArchive(&zip);
#if (ANDROID_VERSION >= 5)
	sysReleaseMap(&map);
#endif

	if(res < 0)
		return "Failed to read manifest.txt!";

	int line_cnt = 1;
	for(char *line = strtok(manifest, "\r\n"); line; line = strtok(NULL, "\r\n"), ++line_cnt)
	{
		if(line[0] == '#')
			continue;

		char *val = strchr(line, '=');
		if(!val)
			continue;

		std::string key = std::string(line, val-line);
		++val; // skip '=' char

		char *start = strchr(val, '"');
		char *end = strrchr(val, '"');

		if(!start || start == end || start+1 == end)
			gui_print("Line %d: failed to parse string\n", line_cnt);
		else
		{
			++start;
			m_vals[key] = std::string(start, end-start);
			LOGI("MROMInstaller: got tag %s=%s\n", key.c_str(), m_vals[key].c_str());
		}
	}

	free(manifest);

	static const char* needed[] = {
		"manifest_ver", "devices", "base_folders"
	};

	for(uint32_t i = 0; i < sizeof(needed)/sizeof(needed[0]); ++i)
	{
		std::map<std::string, std::string>::const_iterator itr = m_vals.find(needed[i]);
		if(itr == m_vals.end())
			return std::string("Required key not found in manifest: ") + needed[i];
	}

	m_file = file;
	return std::string();
}
/**
 * install_package() 的实现主体.
 * @param path
 *      待安装的 ota_pkg 的路径字串. 
 * @param install_file
 *      传入 install 流程的 log file 的路径. 
 * @param is_ru_pkg
 *      当前待安装的 ota_pkg 是否是 ru_pkg.
 */
static int
really_install_package(const char *path, int* wipe_cache, bool needs_mount, int is_ru_pkg)
{
    int ret = INSTALL_SUCCESS;
	//by [email protected]
	//if update loader, we hope not clear misc command.
	//default not clear misc command, let the update-script of update.zip to clear misc when no update loader.
	bNeedClearMisc = false;
    ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
    ui->Print("Finding update package...\n");
    // Give verification half the progress bar...
    ui->SetProgressType(RecoveryUI::DETERMINATE);
    ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME);
    LOGI("Update location: %s\n", path);

    // Map the update package into memory.
    ui->Print("Opening update package...\n");

	needs_mount = true;
    if (path && needs_mount) {
        if (path[0] == '@') {
            ensure_path_mounted(path+1);
        } else {
            ensure_path_mounted(path);
        }
    }

    MemMapping map;
    if (sysMapFile(path, &map) != 0) {
        LOGE("failed to map file\n");
        return INSTALL_CORRUPT;
    }

    int numKeys;
    Certificate* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys);
    if (loadedKeys == NULL) {
        LOGE("Failed to load keys\n");
        return INSTALL_CORRUPT;
    }
    LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE);

    ui->Print("Verifying update package...\n");

    int err;
    err = verify_file(map.addr, map.length, loadedKeys, numKeys);
    free(loadedKeys);
    LOGI("verify_file returned %d\n", err);
    if (err != VERIFY_SUCCESS) {
        LOGE("signature verification failed\n");
        sysReleaseMap(&map);
        return INSTALL_CORRUPT;
    }

    /* Try to open the package.
     */
    ZipArchive zip;
    err = mzOpenZipArchive(map.addr, map.length, &zip);
    if (err != 0) {
        LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad");
        sysReleaseMap(&map);
        return INSTALL_CORRUPT;
    }

#ifdef USE_BOARD_ID
    ensure_path_mounted("/cust");
    ensure_path_mounted("/system");
    D("to restore system_partition.");
    restore();

    gIfBoardIdCustom = true;
#endif

#ifdef USE_RADICAL_UPDATE
    
    // .KP : restore_fw_in_ota_ver : 
    // 无论安装 ru_pkg 还是 original_ota_pkg 之前, 都要 restore 可能的 backup_of_fws_in_ota_ver. 
    // 这样即便连续多次安装 ru_pkg, /radical_update/backup_of_fws_in_ota_ver 中保存的都是 fws_in_ota_ver. 
    // 才能保证, 后续若安装 ota_diff_pkg, 不会失败. 

    if ( 0 != ensure_path_mounted(RU_PARTITION_MOUNT_PATH) )
    {
        SET_ERROR_AND_JUMP("fail to mount ru_partition", ret, INSTALL_ERROR, EXIT);
    }
    if ( 0 != ensure_path_mounted(SYSTEM_PARTITION_MOUNT_PATH) )
    {
        SET_ERROR_AND_JUMP("fail to mount system_partition", ret, INSTALL_ERROR, EXIT);
    }

    if ( RadicalUpdate_isApplied() )
    {
        I("a ru_pkg is applied, to restore backup_of_fws_in_ota_ver to system_partition.");
        CHECK_FUNC_CALL( RadicalUpdate_restoreFirmwaresInOtaVer() , ret, EXIT);
    }
    else 
    {
        D("no ru_pkg is applied.");
    }
    
    if ( 0 != ensure_path_unmounted(RU_PARTITION_MOUNT_PATH) )
    {
        SET_ERROR_AND_JUMP("fail to unmount ru_partition", ret, INSTALL_ERROR, EXIT);
    }
    if ( 0 != ensure_path_unmounted(SYSTEM_PARTITION_MOUNT_PATH) )
    {
        SET_ERROR_AND_JUMP("fail to unmount system_partition", ret, INSTALL_ERROR, EXIT);
    }
#endif

    /* Verify and install the contents of the package.
     */
    ui->Print("Installing update...\n");
    ui->SetEnableReboot(false);
    ret = try_update_binary(path, &zip, wipe_cache);
    ui->SetEnableReboot(true);
    ui->Print("\n");

    sysReleaseMap(&map);

EXIT:
    return ret;
}