int
install_package(const char *root_path)
{
    ui_set_background(BACKGROUND_ICON_INSTALLING);
    ui_print("Finding update package...\n");
    ui_show_indeterminate_progress();
    LOGI("Update location: %s\n", root_path);

    if (ensure_root_path_mounted(root_path) != 0) {
        LOGE("Can't mount %s\n", root_path);
        return INSTALL_CORRUPT;
    }

    char path[PATH_MAX] = "";
    if (translate_root_path(root_path, path, sizeof(path)) == NULL) {
        LOGE("Bad path %s\n", root_path);
        return INSTALL_CORRUPT;
    }

    ui_print("Opening update package...\n");
    LOGI("Update file path: %s\n", path);

    int numKeys;
    RSAPublicKey* 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);

    // Give verification half the progress bar...
    ui_print("Verifying update package...\n");
    ui_show_progress(
            VERIFICATION_PROGRESS_FRACTION,
            VERIFICATION_PROGRESS_TIME);

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

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

    /* Verify and install the contents of the package.
     */
    int status = handle_update_package(path, &zip);
    mzCloseZipArchive(&zip);
    return status;
}
예제 #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;
}
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;
}
예제 #4
0
int
install_package(const char *path)
{
    ui_set_background(BACKGROUND_ICON_INSTALLING);
    ui_print("Finding update package...\n");
    ui_show_indeterminate_progress();
    LOGI("Update location: %s\n", path);

/*
    if (strcmp(root_path, ":") == 0) {
	    if (ensure_root_path_mounted(root_path) != 0) {
	        LOGE("Can't mount %s\n", root_path);
	        return INSTALL_CORRUPT;
	    }

	    if (translate_root_path(root_path, path, sizeof(path)) == NULL) {
	        LOGE("Bad path %s\n", root_path);
	        return INSTALL_CORRUPT;
	    }
    } else {
	    path = strndup(path, root_path);
    }
*/

    ui_print("Opening update package...\n");
    LOGI("Update file path: %s\n", path);

/*
    int numKeys;
    RSAPublicKey* 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);
*/

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

    /* Verify and install the contents of the package.
     */
    // int status = handle_update_package(path, &zip, loadedKeys, numKeys);
    int status = handle_update_package(path, &zip);
    mzCloseZipArchive(&zip);
    // free(loadedKeys);
    return status;
}
예제 #5
0
int extract_deltaupdate_binary(const char *path)
{
    int err;
    ZipArchive zip;

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

    const ZipEntry* dua_entry =
            mzFindZipEntry(&zip, ASSUMED_DELTAUPDATE_BINARY_NAME);
    if (dua_entry == NULL) {
        mzCloseZipArchive(&zip);
       LOGE("Can't find %s\n", ASSUMED_DELTAUPDATE_BINARY_NAME);
        return INSTALL_ERROR;
    }

    char* deltaupdate_agent = RUN_DELTAUPDATE_AGENT;
    unlink(deltaupdate_agent);
    int fd = creat(deltaupdate_agent, 0755);
    if (fd < 0) {
        mzCloseZipArchive(&zip);
        LOGE("Can't make %s\n", deltaupdate_agent);
        return INSTALL_ERROR;
    }

    bool ok = mzExtractZipEntryToFile(&zip, dua_entry, fd);
    close(fd);
    mzCloseZipArchive(&zip);

    if (!ok) {
        LOGE("Can't copy %s\n", ASSUMED_DELTAUPDATE_BINARY_NAME);
        return INSTALL_ERROR;
    }

    return 0;
}
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;
}
예제 #7
0
int open_ota_package(const char *root_path)
{
	int status = INSTALL_SUCCESS;
	int recovery_status = 0;
	ui_print("Opening OTA upgrade package...\n");

	char *c = root_path;
	const char *p;
	int len = strlen(root_path);
	int i;

	c = c + len-2;

	for(i=1;i<len-1;i++)
	{
		--c;
	}
	c[len-1] = '\0';
	p = c;

    int err;
    ZipArchive zip;
    err = mzOpenZipArchive(p, &zip);
    if (err != 0) {
        ui_print("Can't open '%s'\n(%s)\n", p, err != -1 ? strerror(err) : "bad");
        status = INSTALL_CORRUPT;
		goto exit;
    }
	
	ui_print("start update package file\n");
    status = handle_update_package(p, &zip);
	ui_print("install_success!!!\n");
    mzCloseZipArchive(&zip);

exit:
	if (status != INSTALL_SUCCESS)
		recovery_status = 1;
	else
		recovery_status = 0;

    return status;

}
예제 #8
0
int
install_package(const char *root_path)
{
    ui_set_background(BACKGROUND_ICON_INSTALLING);
    ui_print("Finding update package...\n");
    LOGI("Update location: %s\n", root_path);

    if (ensure_root_path_mounted(root_path) != 0) {
        LOGE("Can't mount %s\n", root_path);
        return INSTALL_CORRUPT;
    }

    char path[PATH_MAX] = "";
    if (translate_root_path(root_path, path, sizeof(path)) == NULL) {
        LOGE("Bad path %s\n", root_path);
        return INSTALL_CORRUPT;
    }

    ui_print("Opening update package...\n");
    LOGI("Update file path: %s\n", path);

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

    /* Verify and install the contents of the package.
     */
    int status = handle_update_package(path, &zip);
    mzCloseZipArchive(&zip);
    return status;
}
예제 #9
0
int
install_package(const char *root_path)
{
    ui_set_background(BACKGROUND_ICON_INSTALLING);
    ui_print("查找升级包中...\n");
    LOGI("升级点: %s\n", root_path);

    if (ensure_root_path_mounted(root_path) != 0) {
        LOGE("无法挂载 %s\n", root_path);
        return INSTALL_CORRUPT;
    }

    char path[PATH_MAX] = "";
    if (translate_root_path(root_path, path, sizeof(path)) == NULL) {
        LOGE("错误路径 %s\n", root_path);
        return INSTALL_CORRUPT;
    }

    ui_print("打开升级包中...\n");
    LOGI("升级文件路径: %s\n", path);

    /* Try to open the package.
     */
    int err;
    ZipArchive zip;
    err = mzOpenZipArchive(path, &zip);
    if (err != 0) {
        LOGE("无法打开%s\n(%s)\n", path, err != -1 ? strerror(err) : "bad");
        return INSTALL_CORRUPT;
    }

    /* Verify and install the contents of the package.
     */
    int status = handle_update_package(path, &zip);
    mzCloseZipArchive(&zip);
    return status;
}
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();
}
// If the package contains an update binary, extract it and run it.
static int
try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) {
    const ZipEntry* binary_entry =
            mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);
    if (binary_entry == NULL) {
        mzCloseZipArchive(zip);
        return INSTALL_CORRUPT;
    }

    const char* binary = "/tmp/update_binary";
    unlink(binary);
    int fd = creat(binary, 0755);
    if (fd < 0) {
        mzCloseZipArchive(zip);
        LOGE("Can't make %s\n", binary);
        return INSTALL_ERROR;
    }
    bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd);
    close(fd);
    mzCloseZipArchive(zip);

    if (!ok) {
        LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME);
        return INSTALL_ERROR;
    }

    int pipefd[2];
    pipe(pipefd);

    // When executing the update binary contained in the package, the
    // arguments passed are:
    //
    //   - the version number for this interface
    //
    //   - an fd to which the program can write in order to update the
    //     progress bar.  The program can write single-line commands:
    //
    //        progress <frac> <secs>
    //            fill up the next <frac> part of of the progress bar
    //            over <secs> seconds.  If <secs> is zero, use
    //            set_progress commands to manually control the
    //            progress of this segment of the bar
    //
    //        set_progress <frac>
    //            <frac> should be between 0.0 and 1.0; sets the
    //            progress bar within the segment defined by the most
    //            recent progress command.
    //
    //        firmware <"hboot"|"radio"> <filename>
    //            arrange to install the contents of <filename> in the
    //            given partition on reboot.
    //
    //            (API v2: <filename> may start with "PACKAGE:" to
    //            indicate taking a file from the OTA package.)
    //
    //            (API v3: this command no longer exists.)
    //
    //        ui_print <string>
    //            display <string> on the screen.
    //
    //   - the name of the package zip file.
    //

    const char** args = (const char**)malloc(sizeof(char*) * 5);
    args[0] = binary;
    args[1] = EXPAND(RECOVERY_API_VERSION);   // defined in Android.mk
    char* temp = (char*)malloc(10);
    sprintf(temp, "%d", pipefd[1]);
    args[2] = temp;
    args[3] = (char*)path;
    args[4] = NULL;

    pid_t pid = fork();
    if (pid == 0) {
        close(pipefd[0]);
        execv(binary, (char* const*)args);
        fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno));
        _exit(-1);
    }
    close(pipefd[1]);

    *wipe_cache = 0;

    char buffer[1024];
    FILE* from_child = fdopen(pipefd[0], "r");
    while (fgets(buffer, sizeof(buffer), from_child) != NULL) {
        char* command = strtok(buffer, " \n");
        if (command == NULL) {
            continue;
        } else if (strcmp(command, "progress") == 0) {
            char* fraction_s = strtok(NULL, " \n");
            char* seconds_s = strtok(NULL, " \n");

            float fraction = strtof(fraction_s, NULL);
            int seconds = strtol(seconds_s, NULL, 10);

            ui->ShowProgress(fraction * (1-VERIFICATION_PROGRESS_FRACTION), seconds);
        } else if (strcmp(command, "set_progress") == 0) {
            char* fraction_s = strtok(NULL, " \n");
            float fraction = strtof(fraction_s, NULL);
            ui->SetProgress(fraction);
        } else if (strcmp(command, "ui_print") == 0) {
            char* str = strtok(NULL, "\n");
            if (str) {
                ui->Print("%s", str);
            } else {
                ui->Print("\n");
            }
	    fflush(stdout);
        } else if (strcmp(command, "wipe_cache") == 0) {
            *wipe_cache = 1;
        } else if (strcmp(command, "clear_display") == 0) {
            ui->SetBackground(RecoveryUI::NONE);
        } else {
            LOGE("unknown command [%s]\n", command);
        }
    }
    fclose(from_child);

    int status;
    waitpid(pid, &status, 0);
    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
        LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status));
        return INSTALL_ERROR;
    }

    return INSTALL_SUCCESS;
}
예제 #12
0
파일: zip.c 프로젝트: sub77-bkp/libaroma
/*
 * Function    : libaroma_zip_release
 * Return Value: void
 * Descriptions: release zip file
 */
void libaroma_zip_release(
    LIBAROMA_ZIP zip) {
  mzCloseZipArchive((ZipArchive *) zip);
  free(zip);
} /* End of libaroma_zip_release */
예제 #13
0
파일: action.cpp 프로젝트: Borkata/linux
int GUIAction::flash_zip(std::string filename, std::string pageName, const int simulate)
{
    int ret_val = 0;

	DataManager::SetValue("ui_progress", 0);

    if (filename.empty())
    {
        LOGE("No file specified.\n");
        return -1;
    }

    // We're going to jump to this page first, like a loading page
    gui_changePage(pageName);

    int fd = -1;
    ZipArchive zip;

    if (mzOpenZipArchive(filename.c_str(), &zip))
    {
        LOGE("Unable to open zip file.\n");
        return -1;
    }

    // Check the zip to see if it has a custom installer theme
	const ZipEntry* twrp = mzFindZipEntry(&zip, "META-INF/teamwin/twrp.zip");
    if (twrp != NULL)
    {
        unlink("/tmp/twrp.zip");
        fd = creat("/tmp/twrp.zip", 0666);
    }
    if (fd >= 0 && twrp != NULL && 
        mzExtractZipEntryToFile(&zip, twrp, fd) && 
        !PageManager::LoadPackage("install", "/tmp/twrp.zip"))
    {
        mzCloseZipArchive(&zip);
        PageManager::SelectPackage("install");
        gui_changePage("main");
    }
    else
    {
        // In this case, we just use the default page
        mzCloseZipArchive(&zip);
        gui_changePage(pageName);
    }
    if (fd >= 0)
        close(fd);

	if (simulate) {
		simulate_progress_bar();
	} else {
		ret_val = install_zip_package(filename.c_str());

		// Now, check if we need to ensure TWRP remains installed...
		struct stat st;
		if (stat("/sbin/installTwrp", &st) == 0)
		{
			DataManager::SetValue("tw_operation", "Configuring TWRP");
			DataManager::SetValue("tw_partition", "");
			ui_print("Configuring TWRP...\n");
			if (__system("/sbin/installTwrp reinstall") < 0)
			{
				ui_print("Unable to configure TWRP with this kernel.\n");
			}
		}
	}

    // Done
    DataManager::SetValue("ui_progress", 100);
    DataManager::SetValue("ui_progress", 0);
    return ret_val;
}
static int Run_Update_Binary(const char *path, ZipArchive *Zip, int* wipe_cache) {
	const ZipEntry* binary_location = mzFindZipEntry(Zip, ASSUMED_UPDATE_BINARY_NAME);
	string Temp_Binary = "/tmp/updater";
	int binary_fd, ret_val, pipe_fd[2], status, zip_verify;
	char buffer[1024];
	const char** args = (const char**)malloc(sizeof(char*) * 5);
	FILE* child_data;

	if (binary_location == NULL) {
		mzCloseZipArchive(Zip);
		return INSTALL_CORRUPT;
	}

	// Delete any existing updater
	if (TWFunc::Path_Exists(Temp_Binary) && unlink(Temp_Binary.c_str()) != 0) {
		LOGINFO("Unable to unlink '%s'\n", Temp_Binary.c_str());
	}

	binary_fd = creat(Temp_Binary.c_str(), 0755);
	if (binary_fd < 0) {
		mzCloseZipArchive(Zip);
		LOGERR("Could not create file for updater extract in '%s'\n", Temp_Binary.c_str());
		return INSTALL_ERROR;
	}

	ret_val = mzExtractZipEntryToFile(Zip, binary_location, binary_fd);
	close(binary_fd);

	if (!ret_val) {
		mzCloseZipArchive(Zip);
		LOGERR("Could not extract '%s'\n", ASSUMED_UPDATE_BINARY_NAME);
		return INSTALL_ERROR;
	}

	// If exists, extract file_contexts from the zip file
	const ZipEntry* selinx_contexts = mzFindZipEntry(Zip, "file_contexts");
	if (selinx_contexts == NULL) {
		mzCloseZipArchive(Zip);
		LOGINFO("Zip does not contain SELinux file_contexts file in its root.\n");
	} else {
		string output_filename = "/file_contexts";
		LOGINFO("Zip contains SELinux file_contexts file in its root. Extracting to %s\n", output_filename.c_str());
		// Delete any file_contexts
		if (TWFunc::Path_Exists(output_filename) && unlink(output_filename.c_str()) != 0) {
			LOGINFO("Unable to unlink '%s'\n", output_filename.c_str());
		}

		int file_contexts_fd = creat(output_filename.c_str(), 0644);
		if (file_contexts_fd < 0) {
			mzCloseZipArchive(Zip);
			LOGERR("Could not extract file_contexts to '%s'\n", output_filename.c_str());
			return INSTALL_ERROR;
		}

		ret_val = mzExtractZipEntryToFile(Zip, selinx_contexts, file_contexts_fd);
		close(file_contexts_fd);

		if (!ret_val) {
			mzCloseZipArchive(Zip);
			LOGERR("Could not extract '%s'\n", ASSUMED_UPDATE_BINARY_NAME);
			return INSTALL_ERROR;
		}
	}
	mzCloseZipArchive(Zip);

	pipe(pipe_fd);

	args[0] = Temp_Binary.c_str();
	args[1] = EXPAND(RECOVERY_API_VERSION);
	char* temp = (char*)malloc(10);
	sprintf(temp, "%d", pipe_fd[1]);
	args[2] = temp;
	args[3] = (char*)path;
	args[4] = NULL;

	pid_t pid = fork();
	if (pid == 0) {
		close(pipe_fd[0]);
		execv(Temp_Binary.c_str(), (char* const*)args);
		printf("E:Can't execute '%s'\n", Temp_Binary.c_str());
		_exit(-1);
	}
	close(pipe_fd[1]);

	*wipe_cache = 0;

	DataManager::GetValue(TW_SIGNED_ZIP_VERIFY_VAR, zip_verify);
	child_data = fdopen(pipe_fd[0], "r");
	while (fgets(buffer, sizeof(buffer), child_data) != NULL) {
		char* command = strtok(buffer, " \n");
		if (command == NULL) {
			continue;
		} else if (strcmp(command, "progress") == 0) {
			char* fraction_char = strtok(NULL, " \n");
			char* seconds_char = strtok(NULL, " \n");

			float fraction_float = strtof(fraction_char, NULL);
			int seconds_float = strtol(seconds_char, NULL, 10);

			if (zip_verify)
				DataManager::ShowProgress(fraction_float * (1 - VERIFICATION_PROGRESS_FRACTION), seconds_float);
			else
				DataManager::ShowProgress(fraction_float, seconds_float);
		} else if (strcmp(command, "set_progress") == 0) {
			char* fraction_char = strtok(NULL, " \n");
			float fraction_float = strtof(fraction_char, NULL);
			DataManager::SetProgress(fraction_float);
		} else if (strcmp(command, "ui_print") == 0) {
			char* display_value = strtok(NULL, "\n");
			if (display_value) {
				gui_print("%s", display_value);
			} else {
				gui_print("\n");
			}
		} else if (strcmp(command, "wipe_cache") == 0) {
			*wipe_cache = 1;
		} else if (strcmp(command, "clear_display") == 0) {
			// Do nothing, not supported by TWRP
		} else {
			LOGERR("unknown command [%s]\n", command);
		}
	}
	fclose(child_data);

	waitpid(pid, &status, 0);
	if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
		LOGERR("Error executing updater binary in zip '%s'\n", path);
		return INSTALL_ERROR;
	}

	return INSTALL_SUCCESS;
}
예제 #15
0
// If the package contains an update binary, extract it and run it.
static int
try_update_binary(const char *path, ZipArchive *zip, int* wipe_cache) {
    const ZipEntry* binary_entry =
            mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);
    if (binary_entry == NULL) {
        mzCloseZipArchive(zip);
        return INSTALL_CORRUPT;
    }

    const char* binary = "/tmp/update_binary";
    unlink(binary);
    int fd = creat(binary, 0755);
    if (fd < 0) {
        mzCloseZipArchive(zip);
        LOGE("Can't make %s\n", binary);
        return INSTALL_ERROR;
    }
    bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd);
    close(fd);
    mzCloseZipArchive(zip);

    if (!ok) {
        LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME);
        return INSTALL_ERROR;
    }

    /* Make sure the update binary is compatible with this recovery
     *
     * We're building this against 4.4's (or above) bionic, which
     * has a different property namespace structure. If "set_perm_"
     * is found, it's probably a regular updater instead of a custom
     * one. If "set_metadata_" isn't there, it's pre-4.4, which
     * makes it incompatible.
     *
     * Also, I hate matching strings in binary blobs */

    FILE *updaterfile = fopen(binary, "rb");
    char tmpbuf;
    char setpermmatch[9] = { 's','e','t','_','p','e','r','m','_' };
    char setmetamatch[13] = { 's','e','t','_','m','e','t','a','d','a','t','a','_' };
    size_t pos = 0;
    bool foundsetperm = false;
    bool foundsetmeta = false;

    if (updaterfile == NULL) {
        LOGE("Can't find %s for validation\n", ASSUMED_UPDATE_BINARY_NAME);
        return INSTALL_ERROR;
    }
    fseek(updaterfile, 0, SEEK_SET);
    while (!feof(updaterfile)) {
        fread(&tmpbuf, 1, 1, updaterfile);
        if (!foundsetperm && pos < sizeof(setpermmatch) && tmpbuf == setpermmatch[pos]) {
            pos++;
            if (pos == sizeof(setpermmatch)) {
                foundsetperm = true;
                pos = 0;
            }
            continue;
        }
        if (!foundsetmeta && tmpbuf == setmetamatch[pos]) {
            pos++;
            if (pos == sizeof(setmetamatch)) {
                foundsetmeta = true;
                pos = 0;
            }
            continue;
        }
        /* None of the match loops got a continuation, reset the counter */
        pos = 0;
    }
    fclose(updaterfile);

    /* Set legacy properties */
    if (foundsetperm && !foundsetmeta) {
        ui_print("Using legacy property environment for update-binary...\n");
        ui_print("Please upgrade to latest binary...\n");
        if (set_legacy_props() != 0) {
            LOGE("Legacy property environment did not init successfully. Properties may not be detected.\n");
        } else {
            LOGI("Legacy property environment initialized.\n");
        }
    }

    int pipefd[2];
    pipe(pipefd);

    // When executing the update binary contained in the package, the
    // arguments passed are:
    //
    //   - the version number for this interface
    //
    //   - an fd to which the program can write in order to update the
    //     progress bar.  The program can write single-line commands:
    //
    //        progress <frac> <secs>
    //            fill up the next <frac> part of of the progress bar
    //            over <secs> seconds.  If <secs> is zero, use
    //            set_progress commands to manually control the
    //            progress of this segment of the bar
    //
    //        set_progress <frac>
    //            <frac> should be between 0.0 and 1.0; sets the
    //            progress bar within the segment defined by the most
    //            recent progress command.
    //
    //        firmware <"hboot"|"radio"> <filename>
    //            arrange to install the contents of <filename> in the
    //            given partition on reboot.
    //
    //            (API v2: <filename> may start with "PACKAGE:" to
    //            indicate taking a file from the OTA package.)
    //
    //            (API v3: this command no longer exists.)
    //
    //        ui_print <string>
    //            display <string> on the screen.
    //
    //   - the name of the package zip file.
    //

    const char** args = (const char**)malloc(sizeof(char*) * 5);
    args[0] = binary;
    args[1] = EXPAND(RECOVERY_API_VERSION);   // defined in Android.mk
    char* temp = (char*)malloc(10);
    sprintf(temp, "%d", pipefd[1]);
    args[2] = temp;
    args[3] = (char*)path;
    args[4] = NULL;

    pid_t pid = fork();
    if (pid == 0) {
        // set the env for UPDATE_PACKAGE (the source zip) for update-binary. This allows shell scripts to use the source zip.
		// https://github.com/CyanogenMod/android_bootable_recovery/commit/20b516a408adebcad06e03f12516e70b8998c38f
        setenv("UPDATE_PACKAGE", path, 1);
        close(pipefd[0]);
        execve(binary, (char* const*)args, environ);
        fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno));
        _exit(-1);
    }
    close(pipefd[1]);

    *wipe_cache = 0;

    char buffer[1024];
    FILE* from_child = fdopen(pipefd[0], "r");
    while (fgets(buffer, sizeof(buffer), from_child) != NULL) {
        char* command = strtok(buffer, " \n");
        if (command == NULL) {
            continue;
        } else if (strcmp(command, "progress") == 0) {
            char* fraction_s = strtok(NULL, " \n");
            char* seconds_s = strtok(NULL, " \n");

            float fraction = strtof(fraction_s, NULL);
            int seconds = strtol(seconds_s, NULL, 10);

            ui_show_progress(fraction * (1-VERIFICATION_PROGRESS_FRACTION), seconds);
        } else if (strcmp(command, "set_progress") == 0) {
            char* fraction_s = strtok(NULL, " \n");
            float fraction = strtof(fraction_s, NULL);
            ui_set_progress(fraction);
        } else if (strcmp(command, "ui_print") == 0) {
            char* str = strtok(NULL, "\n");
            if (str) {
                ui_print("%s", str);
            } else {
                ui_print("\n");
            }
            fflush(stdout);
        } else if (strcmp(command, "wipe_cache") == 0) {
            *wipe_cache = 1;
        } else if (strcmp(command, "clear_display") == 0) {
            // not needed in PhilZ Touch;
        } else {
            LOGE("unknown command [%s]\n", command);
        }
    }
    fclose(from_child);

    int status;
    waitpid(pid, &status, 0);

    /* Unset legacy properties */
    if (legacy_props_path_modified) {
        if (unset_legacy_props() != 0) {
            LOGE("Legacy property environment did not disable successfully. Legacy properties may still be in use.\n");
        } else {
            LOGI("Legacy property environment disabled.\n");
        }
    }

    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
        LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status));
        return INSTALL_ERROR;
    }

    return INSTALL_SUCCESS;
}
예제 #16
0
Value *FlashIfwiFn(const char *name, State * state, int argc, Expr * argv[])
{
	Value *ret = NULL;
	char *filename = NULL;
	int err, ifwi_bin_fd, dnx_bin_fd, i, num;
	char ifwi_name[128], dnx_name[128];
	ZipArchive ifwi_za;
	const ZipEntry *dnx_entry, *ifwi_entry;
	unsigned char *file_buf = NULL;
	size_t file_size;

	if (ReadArgs(state, argv, 1, &filename) < 0) {
		return NULL;
	}

	if (filename == NULL || strlen(filename) == 0) {
		ErrorAbort(state, "filename argument to %s can't be empty", name);
		goto done;
	}

	err = file_read(filename, (void **)&file_buf, &file_size);
	if (err) {
		ErrorAbort(state, "Failed to open zip archive file %s\n", filename);
		goto done;
	}

	err = mzOpenZipArchive(file_buf, file_size, &ifwi_za);
	if (err) {
		ErrorAbort(state, "Failed to open zip archive\n");
		goto done;
	}

	num = mzZipEntryCount(&ifwi_za);
	for (i = 0; i < num; i++) {
		ifwi_entry = mzGetZipEntryAt(&ifwi_za, i);
		if ((ifwi_entry->fileNameLen + 1) < sizeof(ifwi_name)) {
			strncpy(ifwi_name, ifwi_entry->fileName, ifwi_entry->fileNameLen);
			ifwi_name[ifwi_entry->fileNameLen] = '\0';
		} else {
			ErrorAbort(state, "ifwi file name is too big. Size max is:%d.\n", sizeof(ifwi_name));
			goto error;
		}
		if (strncmp(ifwi_name, IFWI_NAME, strlen(IFWI_NAME)))
			continue;

		if ((ifwi_bin_fd = open(IFWI_BIN_PATH, O_RDWR | O_TRUNC | O_CREAT, FILEMODE)) < 0) {
			ErrorAbort(state, "unable to create Extracted file:%s.\n", IFWI_BIN_PATH);
			goto error;
		}
		if ((dnx_bin_fd = open(DNX_BIN_PATH, O_RDWR | O_TRUNC | O_CREAT, FILEMODE)) < 0) {
			ErrorAbort(state, "unable to create Extracted file:%s.\n", IFWI_BIN_PATH);
			close(ifwi_bin_fd);
			goto error;
		}
		strcpy(dnx_name, "dnx_fwr");
		strncat(dnx_name, &(ifwi_name[strlen(IFWI_NAME)]), sizeof(dnx_name) - strlen("dnx_fwr") - 1);
		dnx_entry = mzFindZipEntry(&ifwi_za, dnx_name);

		if (dnx_entry == NULL) {
			ErrorAbort(state, "Could not find DNX entry");
			close(ifwi_bin_fd);
			close(dnx_bin_fd);
			goto error;
		}

		err = mzExtractZipEntryToFile(&ifwi_za, dnx_entry, dnx_bin_fd);
		if (!err) {
			ErrorAbort(state, "Failed to unzip %s\n", DNX_BIN_PATH);
			close(ifwi_bin_fd);
			close(dnx_bin_fd);
			goto error;
		}
		close(dnx_bin_fd);
		err = mzExtractZipEntryToFile(&ifwi_za, ifwi_entry, ifwi_bin_fd);
		if (!err) {
			ErrorAbort(state, "Failed to unzip %s\n", DNX_BIN_PATH);
			close(ifwi_bin_fd);
			goto error;
		}
		close(ifwi_bin_fd);
		int update_ifwi_file_scu_ipc(const char *dnx, const char *ifwi);
		update_ifwi_file_scu_ipc(DNX_BIN_PATH, IFWI_BIN_PATH);
	}

	ret = StringValue(strdup("t"));

error:
	mzCloseZipArchive(&ifwi_za);

done:
	free(file_buf);
	if (filename)
		free(filename);

	return ret;
}
예제 #17
0
int
install_package(const char *root_path)
{
	recovery_status = 0;
	int status = INSTALL_SUCCESS;
    ui_set_background(BACKGROUND_ICON_INSTALLING);
    ui_print("Finding update package...\n");
    ui_show_indeterminate_progress();

    if (ensure_root_path_mounted(root_path) != 0) {
        ui_print("Can't mount %s\n", root_path);
        status = INSTALL_CORRUPT;
		goto exit;
    }

    char path[PATH_MAX] = "";
    if (translate_root_path(root_path, path, sizeof(path)) == NULL) {
        ui_print("Bad path %s\n", root_path);
        status = INSTALL_CORRUPT;
		goto exit;
    }
	printf("package name = '%s'\t path_len= %d\n",path,strlen(path));
    ui_print("Opening update package...\n");
#if 0
    int numKeys;
    RSAPublicKey* 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);

    // Give verification half the progress bar...
    ui_print("Verifying update package...\n");
    ui_show_progress(
            VERIFICATION_PROGRESS_FRACTION,
            VERIFICATION_PROGRESS_TIME);

    int err;
    err = verify_file(path, loadedKeys, numKeys);
    free(loadedKeys);
    LOGI("verify_file returned %d\n", err);
    if (err != VERIFY_SUCCESS) {
        LOGE("signature verification failed\n");
        return INSTALL_CORRUPT;
    }
#endif

    /* Try to open the package.
     */
    int err;
    ZipArchive zip;
    err = mzOpenZipArchive(path, &zip);
    if (err != 0) {
        ui_print("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad");
        status = INSTALL_CORRUPT;
		goto exit;
    }

	/*
	 * Verify hw version 
	 */
	/*
	if (check_hw_version(&zip)) {
		ui_print("HW version doesn't match!!!");
		status = INSTALL_CORRUPT;
    	mzCloseZipArchive(&zip);
		goto exit;
	}
*/
    /* Verify and install the contents of the package.
     */
	ui_print("start update package file\n");
    status = handle_update_package(path, &zip);
	ui_print("install_success!!!\n");
    mzCloseZipArchive(&zip);

exit:
	ensure_root_path_unmounted(root_path);
	if (status != INSTALL_SUCCESS)
		recovery_status = 1;
	else
		recovery_status = 0;

    return status;
}
예제 #18
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;
}
예제 #19
0
int main(int argc, char** argv) {
    // Various things log information to stdout or stderr more or less
    // at random.  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) {
        fprintf(stderr, "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.
        fprintf(stderr, "wrong updater binary API; expected 1, 2, or 3; "
                        "got %s\n",
                argv[1]);
	//printf("Wrong updater binary API; expected 1, 2, or 3; we just 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.

    char* package_data = argv[3];
    ZipArchive za;
    int err;
    err = mzOpenZipArchive(package_data, &za);
    if (err != 0) {
        fprintf(stderr, "failed to open package %s: %s\n",
                package_data, strerror(err));
        return 3;
    }

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

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

    // Configure edify's functions.

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

    // Parse the script.

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

    struct selinux_opt seopts[] = {
      { SELABEL_OPT_PATH, "/file_contexts" }
    };

    sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1);

    if (!sehandle) {
        fprintf(stderr, "Warning:  No file_contexts\n");
        // 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);

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

    char* result = Evaluate(&state, root);
    if (result == NULL) {
        if (state.errmsg == NULL) {
            fprintf(stderr, "script aborted (no error message)\n");
            fprintf(cmd_pipe, "ui_print script aborted (no error message)\n");
        } else {
            fprintf(stderr, "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(stderr, "script result was [%s]\n", result);
        free(result);
    }

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

    return 0;
}
예제 #20
0
//-- AROMA ZIP Close
void az_close() {
  mzCloseZipArchive(&zip);
}
예제 #21
0
Value *FlashIfwiOrBomFn(enum flash_option_type flash_option, const char *name, State * state, int argc,
			Expr * argv[])
{
	Value *ret = NULL;
	char *filename = NULL;
	int err, i, num, buffsize;
	char ifwi_name[128];
	ZipArchive ifwi_za;
	const ZipEntry *ifwi_entry;
	unsigned char *buffer;
	unsigned char *file_buf = NULL;
	size_t file_size;
#ifdef TEE_FRAMEWORK
	char bom_token_name[128];
	const ZipEntry *bom_token_entry;
	int bom_token_buffsize;
	unsigned char *bom_token_buffer;
#endif

	if (ReadArgs(state, argv, 1, &filename) < 0) {
		return NULL;
	}

	if (filename == NULL || strlen(filename) == 0) {
		ErrorAbort(state, "filename argument to %s can't be empty", name);
		goto done;
	}

	err = file_read(filename, (void **)&file_buf, &file_size);
	if (err) {
		ErrorAbort(state, "Failed to open zip archive file %s\n", filename);
		goto done;
	}

	err = mzOpenZipArchive(file_buf, file_size, &ifwi_za);
	if (err) {
		ErrorAbort(state, "Failed to open zip archive\n");
		goto done;
	}

	num = mzZipEntryCount(&ifwi_za);
	for (i = 0; i < num; i++) {
		ifwi_entry = mzGetZipEntryAt(&ifwi_za, i);
		if ((ifwi_entry->fileNameLen + 1) < sizeof(ifwi_name)) {
			strncpy(ifwi_name, ifwi_entry->fileName, ifwi_entry->fileNameLen);
			ifwi_name[ifwi_entry->fileNameLen] = '\0';
		} else {
			ErrorAbort(state, "ifwi file name is too big. Size max is:%zd.\n", sizeof(ifwi_name));
			goto error;
		}
		if (strncmp(ifwi_name, IFWI_NAME, strlen(IFWI_NAME)))
			continue;
		buffsize = mzGetZipEntryUncompLen(ifwi_entry);
		if (buffsize <= 0) {
			ErrorAbort(state, "Bad ifwi_entry size : %d.\n", buffsize);
			goto error;
		}
		buffer = (unsigned char *)malloc(sizeof(unsigned char) * buffsize);
		if (buffer == NULL) {
			ErrorAbort(state, "Unable to alloc ifwi buffer of %d bytes.\n", buffsize);
			goto error;
		}
		err = mzExtractZipEntryToBuffer(&ifwi_za, ifwi_entry, buffer);
		if (!err) {
			ErrorAbort(state, "Failed to unzip %s\n", IFWI_BIN_PATH);
			free(buffer);
			goto error;
		}

		if (check_ifwi_file(buffer, buffsize) < 1) {
			free(buffer);
			continue;
		}

		if (flash_option == FLASH_BOM_TOKEN_BINARY) {
#ifdef TEE_FRAMEWORK
			strcpy(bom_token_name, BOM_TOKEN_NAME);
			strncat(bom_token_name, &(ifwi_name[strlen(IFWI_NAME)]),
				sizeof(bom_token_name) - strlen(BOM_TOKEN_NAME) - 1);
			bom_token_entry = mzFindZipEntry(&ifwi_za, bom_token_name);

			if (bom_token_entry != NULL) {
				bom_token_buffsize = mzGetZipEntryUncompLen(bom_token_entry);
				if (bom_token_buffsize <= 0) {
					ErrorAbort(state, "Bad bom_token_entry size : %d.\n",
						   bom_token_buffsize);
					free(buffer);
					goto error;
				}
				bom_token_buffer =
				    (unsigned char *)malloc(sizeof(unsigned char) * bom_token_buffsize);
				if (bom_token_buffer == NULL) {
					ErrorAbort(state, "Unable to alloc bom token buffer of %d bytes.\n",
						   bom_token_buffsize);
					free(buffer);
					goto error;
				}
				err = mzExtractZipEntryToBuffer(&ifwi_za, bom_token_entry, bom_token_buffer);
				if (!err) {
					ErrorAbort(state, "Failed to unzip %s.\n", IFWI_BIN_PATH);
					free(bom_token_buffer);
					free(buffer);
					goto error;
				}
				if (write_token(bom_token_buffer, bom_token_buffsize) == 0) {
					printf("BOM token written\n");
				} else {
					printf("Unable to write BOM token.\n");
					cancel_update(0, NULL);
					free(bom_token_buffer);
					free(buffer);
					ret = StringValue(strdup("fail"));
					goto error;
				}
				free(bom_token_buffer);
			}
#else
			printf("BOM token flashing not supported\n");
#endif
		} else if (flash_option == FLASH_IFWI_BINARY) {
			printf("Flashing IFWI\n");
			update_ifwi_file(buffer, buffsize);
		} else {
			ErrorAbort(state, "Don't know what to do with option %d\n", flash_option);
			free(buffer);
			goto error;
		}
		free(buffer);
	}

	ret = StringValue(strdup("t"));

error:
	mzCloseZipArchive(&ifwi_za);

done:
	free(file_buf);
	if (filename)
		free(filename);

	return ret;
}
예제 #22
0
// If the package contains an update binary, extract it and run it.
static int
try_update_binary(const char *path, ZipArchive *zip) {
    const ZipEntry* binary_entry =
            mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);
    if (binary_entry == NULL) {
        const ZipEntry* update_script_entry =
                mzFindZipEntry(zip, ASSUMED_UPDATE_SCRIPT_NAME);
        if (update_script_entry != NULL) {
            ui_print("Amend 脚本 (update-script) 已不支持.\n");
            ui_print("Amend 脚本在 Android 1.5 后不再支持.\n");
            ui_print("请将升级包脚本升级到Edify脚本(updater-script 和 update-binary).\n");
            ui_print("安装已取消.\n");
            return INSTALL_UPDATE_BINARY_MISSING;
        }

        mzCloseZipArchive(zip);
        return INSTALL_UPDATE_BINARY_MISSING;
    }

    char* binary = "/tmp/update_binary";
    unlink(binary);
    int fd = creat(binary, 0755);
    if (fd < 0) {
        mzCloseZipArchive(zip);
        LOGE("Can't make %s\n", binary);
        return 1;
    }
    bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd);
    close(fd);

    if (!ok) {
        LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME);
        mzCloseZipArchive(zip);
        return 1;
    }

    int pipefd[2];
    pipe(pipefd);

    // When executing the update binary contained in the package, the
    // arguments passed are:
    //
    //   - the version number for this interface
    //
    //   - an fd to which the program can write in order to update the
    //     progress bar.  The program can write single-line commands:
    //
    //        progress <frac> <secs>
    //            fill up the next <frac> part of of the progress bar
    //            over <secs> seconds.  If <secs> is zero, use
    //            set_progress commands to manually control the
    //            progress of this segment of the bar
    //
    //        set_progress <frac>
    //            <frac> should be between 0.0 and 1.0; sets the
    //            progress bar within the segment defined by the most
    //            recent progress command.
    //
    //        firmware <"hboot"|"radio"> <filename>
    //            arrange to install the contents of <filename> in the
    //            given partition on reboot.
    //
    //            (API v2: <filename> may start with "PACKAGE:" to
    //            indicate taking a file from the OTA package.)
    //
    //            (API v3: this command no longer exists.)
    //
    //        ui_print <string>
    //            display <string> on the screen.
    //
    //   - the name of the package zip file.
    //

    char** args = malloc(sizeof(char*) * 5);
    args[0] = binary;
    args[1] = EXPAND(RECOVERY_API_VERSION);   // defined in Android.mk
    args[2] = malloc(10);
    sprintf(args[2], "%d", pipefd[1]);
    args[3] = (char*)path;
    args[4] = NULL;

    pid_t pid = fork();
    if (pid == 0) {
        setenv("UPDATE_PACKAGE", path, 1);
        close(pipefd[0]);
        execv(binary, args);
        fprintf(stdout, "E:Can't run %s (%s)\n", binary, strerror(errno));
        _exit(-1);
    }
    close(pipefd[1]);

    char* firmware_type = NULL;
    char* firmware_filename = NULL;

    char buffer[1024];
    FILE* from_child = fdopen(pipefd[0], "r");
    while (fgets(buffer, sizeof(buffer), from_child) != NULL) {
        char* command = strtok(buffer, " \n");
        if (command == NULL) {
            continue;
        } else if (strcmp(command, "progress") == 0) {
            char* fraction_s = strtok(NULL, " \n");
            char* seconds_s = strtok(NULL, " \n");

            float fraction = strtof(fraction_s, NULL);
            int seconds = strtol(seconds_s, NULL, 10);

            ui_show_progress(fraction * (1-VERIFICATION_PROGRESS_FRACTION),
                             seconds);
        } else if (strcmp(command, "set_progress") == 0) {
            char* fraction_s = strtok(NULL, " \n");
            float fraction = strtof(fraction_s, NULL);
            ui_set_progress(fraction);
        } else if (strcmp(command, "firmware") == 0) {
            char* type = strtok(NULL, " \n");
            char* filename = strtok(NULL, " \n");

            if (type != NULL && filename != NULL) {
                if (firmware_type != NULL) {
                    LOGE("ignoring attempt to do multiple firmware updates");
                } else {
                    firmware_type = strdup(type);
                    firmware_filename = strdup(filename);
                }
            }
        } else if (strcmp(command, "ui_print") == 0) {
            char* str = strtok(NULL, "\n");
            if (str) {
                ui_print("%s", str);
            } else {
                ui_print("\n");
            }
        } else {
            LOGE("unknown command [%s]\n", command);
        }
    }
    fclose(from_child);

    int status;
    waitpid(pid, &status, 0);
    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
        LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status));
        mzCloseZipArchive(zip);
        return INSTALL_ERROR;
    }

    if (firmware_type != NULL) {
        int ret = handle_firmware_update(firmware_type, firmware_filename, zip);
        mzCloseZipArchive(zip);
        return ret;
    }
    return INSTALL_SUCCESS;
}
Value* UpdateFn(const char* name, State* state, int argc, Expr* argv[]) {
    if (argc != 7) {
        return ErrorAbort(state, "%s() expects 7 args, got %d", name, argc);
    }

    char* type = strrchr(name, '_');
    if (type == NULL || *(type+1) == '\0') {
        return ErrorAbort(state, "%s() couldn't get type from function name",
                          name);
    }
    ++type;

    Value* image;
    Value* width_string;
    Value* height_string;
    Value* bpp_string;
    Value* busy;
    Value* fail;
    Value* expected_sha1_string;
    if (ReadValueArgs(state, argv, 7, &image,
                      &width_string, &height_string, &bpp_string,
                      &busy, &fail, &expected_sha1_string) < 0) {
        return NULL;
    }

    // close the package
    ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;
    mzCloseZipArchive(za);
    ((UpdaterInfo*)(state->cookie))->package_zip = NULL;

    // Try to unmount /cache.  If we fail (because we're running in an
    // older recovery that still has the package file open), try to
    // remount it read-only.  If that fails, abort.
    sync();
    scan_mounted_volumes();
    MountedVolume* vol = find_mounted_volume_by_mount_point("/cache");
    int result = unmount_mounted_volume(vol);
    if (result != 0) {
        printf("%s(): failed to unmount cache (%d: %s)\n",
               name, result, strerror(errno));

        result = remount_read_only(vol);
        if (result != 0) {
            printf("%s(): failed to remount cache (%d: %s)\n",
                   name, result, strerror(errno));
            return StringValue(strdup(""));
        } else {
            printf("%s(): remounted cache\n", name);
        }
        sync();
    } else {
        printf("%s(): unmounted cache\n", name);
    }

    int width = 0, height = 0, bpp = 0;

    if (width_string->type != VAL_STRING ||
        (width = strtol(width_string->data, NULL, 10)) == 0) {
        printf("%s(): bad width argument", name);
    }
    if (height_string->type != VAL_STRING ||
        (height = strtol(height_string->data, NULL, 10)) == 0) {
        printf("%s(): bad height argument", name);
    }
    if (bpp_string->type != VAL_STRING ||
        (bpp = strtol(bpp_string->data, NULL, 10)) == 0) {
        printf("%s(): bad bpp argument", name);
    }

    if (image->type != VAL_BLOB) {
        printf("image argument is not blob (is type %d)\n", image->type);
        goto done;
    }

    uint8_t expected_sha1[SHA_DIGEST_SIZE];
    char* data = expected_sha1_string->data;
    if (expected_sha1_string->type != VAL_STRING ||
        strlen(data) != SHA_DIGEST_SIZE*2) {
        printf("%s(): bad expected_sha1 argument", name);
        goto done;
    }
    printf("expected sha1 is: ");
    int i;
    for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
        char temp = data[i*2+2];
        data[i*2+2] = '\0';
        expected_sha1[i] = strtol(data+i*2, NULL, 16);
        data[i*2+2] = temp;
        printf("%02x", expected_sha1[i]);
    }
    printf("\n");

    install_firmware_update(
        type,
        image->data,
        image->size,
        width, height, bpp,
        busy->size > 0 ? busy->data : NULL,
        fail->size > 0 ? fail->data : NULL,
        "/tmp/recovery.log",
        expected_sha1);
    printf("%s: install_firmware_update returned!\n", name);

  done:
    FreeValue(image);
    FreeValue(width_string);
    FreeValue(height_string);
    FreeValue(bpp_string);
    FreeValue(busy);
    FreeValue(fail);
    // install_firmware_update should reboot.  If it returns, it failed.
    return StringValue(strdup(""));
}