int Resource::ExtractResource(ZipArchive* pZip, 
                              std::string folderName, 
                              std::string fileName, 
                              std::string fileExtn, 
                              std::string destFile)
{
    if (!pZip)  return -1;

    std::string src = folderName + "/" + fileName + fileExtn;

	const ZipEntry* binary = mzFindZipEntry(pZip, src.c_str());
    if (binary == NULL) {
        return -1;
	}

    unlink(destFile.c_str());
    int fd = creat(destFile.c_str(), 0666);
    if (fd < 0)
        return -1;

    int ret = 0;
    if (!mzExtractZipEntryToFile(pZip, binary, fd))
        ret = -1;

    close(fd);
    return ret;
}
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;
}
//-- Extract To File
byte az_extract(const char * zpath, const char * dest) {
  const ZipEntry * zdata = mzFindZipEntry(&zip, zpath);
  
  if (zdata == NULL) {
    return 0;
  }
  
  unlink(dest);
  int fd = creat(dest, 0755);
  
  if (fd < 0) {
    return 0;
  }
  
  byte ok = mzExtractZipEntryToFile(&zip, zdata, fd);
  close(fd);
  return ok;
}
Пример #4
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;
}
Пример #5
0
/*
 * Function    : libaroma_zip_extract
 * Return Value: byte
 * Descriptions: extract zip entry to file
 */
byte libaroma_zip_extract(
    LIBAROMA_ZIP zip,
    const char * zpath,
    const char * dest) {
#ifdef LIBAROMA_SYSCAL_HAVE_FD
  const ZipEntry * zdata = mzFindZipEntry((ZipArchive *) zip, zpath);
  if (zdata == NULL) {
    ALOGW("libaroma_zip_extract zdata=NULL (%s)", zpath);
    return 0;
  }
  libaroma_unlink(dest);
  int fd = creat(dest, 0755);
  if (fd < 0) {
    ALOGW("libaroma_zip_extract creat error (%s)", dest);
    return 0;
  }
  byte ok = mzExtractZipEntryToFile((ZipArchive *) zip, zdata, fd);
  close(fd);
  return ok;
#else
  return 0;
#endif
} /* End of libaroma_zip_extract */
Пример #6
0
static int get_hw_version_zip(ZipArchive *zip, char* item_name, char* zip_hw_version)
{
	int ret;
	int fd;
    char* hw_version = "/tmp/hw_version";
    const ZipEntry* hw_version_entry;

   	hw_version_entry = mzFindZipEntry(zip, HW_VERSION_ENTRY_ZIP);
    if (hw_version_entry == NULL) {
        return 1;
    }

    fd = creat(hw_version, 0755);
    if (fd < 0) {
        LOGE("Can't make %s\n", hw_version);
        return 2;
    }


    if (!mzExtractZipEntryToFile(zip, hw_version_entry, fd)) {
        LOGE("Can't copy %s, error is %s\n", HW_VERSION_ENTRY_ZIP, strerror(errno));
        return 4;
    }
	close(fd);

	fd = open(hw_version, O_RDONLY);
	ret = read(fd, zip_hw_version, 256);
	ui_print("read %d\n", ret);
	if (ret <= 0) {
		LOGE("Can't read from %s\n", hw_version);
		return 3;
	}
    close(fd);

	ui_print("zip_hw_version=%s\n", zip_hw_version);
	return 0;
}
Пример #7
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) {
        return INSTALL_CORRUPT;
    }

    char* binary = "/tmp/update_binary";
    unlink(binary);
    int fd = creat(binary, 0755);
    if (fd < 0) {
        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);
        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.)
    //
    //        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) {
        close(pipefd[0]);
        execv(binary, args);
        fprintf(stderr, "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[81];
    FILE* from_child = fdopen(pipefd[0], "r");
    while (fgets(buffer, sizeof(buffer), from_child) != NULL) {
        LOGI("read: %s", buffer);

        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) {
                printf(str);
            } else {
                printf("\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));
        return INSTALL_ERROR;
    }

    if (firmware_type != NULL) {
        return handle_firmware_update(firmware_type, firmware_filename, zip);
    } else {
        return INSTALL_SUCCESS;
    }
}
Пример #8
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;
}
Пример #9
0
// package_extract_file(package_path, destination_path)
//   or
// package_extract_file(package_path)
//   to return the entire contents of the file as the result of this
//   function (the char* returned is actually a FileContents*).
Value* PackageExtractFileFn(const char* name, State* state,
                           int argc, Expr* argv[]) {
    if (argc != 1 && argc != 2) {
        return ErrorAbort(state, "%s() expects 1 or 2 args, got %d",
                          name, argc);
    }
    bool success = false;
    if (argc == 2) {
        // The two-argument version extracts to a file.

        char* zip_path;
        char* dest_path;
        if (ReadArgs(state, argv, 2, &zip_path, &dest_path) < 0) return NULL;

        ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;
        const ZipEntry* entry = mzFindZipEntry(za, zip_path);
        if (entry == NULL) {
            fprintf(stderr, "%s: no %s in package\n", name, zip_path);
            goto done2;
        }

        FILE* f = fopen(dest_path, "wb");
        if (f == NULL) {
            fprintf(stderr, "%s: can't open %s for write: %s\n",
                    name, dest_path, strerror(errno));
            goto done2;
        }
        success = mzExtractZipEntryToFile(za, entry, fileno(f));
        fclose(f);

      done2:
        free(zip_path);
        free(dest_path);
        return StringValue(strdup(success ? "t" : ""));
    } else {
        // The one-argument version returns the contents of the file
        // as the result.

        char* zip_path;
        Value* v = malloc(sizeof(Value));
        v->type = VAL_BLOB;
        v->size = -1;
        v->data = NULL;

        if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL;

        ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;
        const ZipEntry* entry = mzFindZipEntry(za, zip_path);
        if (entry == NULL) {
            fprintf(stderr, "%s: no %s in package\n", name, zip_path);
            goto done1;
        }

        v->size = mzGetZipEntryUncompLen(entry);
        v->data = malloc(v->size);
        if (v->data == NULL) {
            fprintf(stderr, "%s: failed to allocate %ld bytes for %s\n",
                    name, (long)v->size, zip_path);
            goto done1;
        }

        success = mzExtractZipEntryToBuffer(za, entry,
                                            (unsigned char *)v->data);

      done1:
        free(zip_path);
        if (!success) {
            free(v->data);
            v->data = NULL;
            v->size = -1;
        }
        return v;
    }
}
Пример #10
0
/* run_program <program-file> [<args> ...]
 *
 * Run an external program included in the update package.
 */
static int
cmd_run_program(const char *name, void *cookie, int argc, const char *argv[])
{
    UNUSED(cookie);
    CHECK_WORDS();

    if (argc < 1) {
        LOGE("Command %s requires at least one argument\n", name);
        return 1;
    }

    // Copy the program file to temporary storage.
    if (!is_package_root_path(argv[0])) {
        LOGE("Command %s: non-package program file \"%s\" not supported\n",
                name, argv[0]);
        return 1;
    }

    char path[PATH_MAX];
    const ZipArchive *package;
    if (!translate_package_root_path(argv[0], path, sizeof(path), &package)) {
        LOGE("Command %s: bad source path \"%s\"\n", name, argv[0]);
        return 1;
    }

    const ZipEntry *entry = mzFindZipEntry(package, path);
    if (entry == NULL) {
        LOGE("Can't find %s\n", path);
        return 1;
    }

    static const char *binary = "/tmp/run_program_binary";
    unlink(binary);  // just to be sure
    int fd = creat(binary, 0755);
    if (fd < 0) {
        LOGE("Can't make %s\n", binary);
        return 1;
    }
    bool ok = mzExtractZipEntryToFile(package, entry, fd);
    close(fd);

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

    // Create a copy of argv to NULL-terminate it, as execv requires
    char **args = (char **) malloc(sizeof(char*) * (argc + 1));
    memcpy(args, argv, sizeof(char*) * argc);
    args[argc] = NULL;

    pid_t pid = fork();
    if (pid == 0) {
        execv(binary, args);
        fprintf(stderr, "E:Can't run %s\n(%s)\n", binary, strerror(errno));
        _exit(-1);
    }

    int status;
    waitpid(pid, &status, 0);
    if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
        return 0;
    } else {
        LOGE("Error in %s\n(Status %d)\n", path, status);
        return 1;
    }
}
// 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;
}
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;
}
Пример #13
0
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;
}
Пример #14
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;
}
Пример #15
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;
}
Пример #16
0
// If the package contains an update binary, extract it and run it.
static int
try_update_binary(const char *path, ZipArchive *zip) 
{
	int	custom_binary = 0;

	const ZipEntry* or_script_entry =
		      mzFindZipEntry(zip, ASSUMED_OR_UPDATE_SCRIPT_NAME);
		      
	if (or_script_entry != NULL)
	{
		ui_print("使用shell脚本...\n");
		return handle_or_update(path, zip);
	}

	const ZipEntry* binary_entry =
		      mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);

	if (binary_entry == NULL)
		ui_print("使用默认的updater...\n");
	else
		custom_binary = 1;
  
  char* binary = "/tmp/update_binary";
  unlink(binary);
  
  if (custom_binary)
  {
		int fd = creat(binary, 0755);
		if (fd < 0) 
		{
		  LOGE("无法制作%s\n", binary);
		  return 1;
		}
  
		bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd);
		close(fd);

		if (!ok) 
		{
	    LOGE("无法复制%s\n", ASSUMED_UPDATE_BINARY_NAME);
	    return 1;
		}
	}
	else
		binary = DEFAULT_UPDATE_BINARY_NAME;

	ui_show_indeterminate_progress();
  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.)
  //
  //        ui_print <string>
  //            display <string> on the screen.
  //
  //				stasis
  //						quit the gui
  //   - 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) 
  {
    close(pipefd[0]);
    execv(binary, args);
    fprintf(stderr, "E:无法运行%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");
  
  ui_set_progress(0.0);
  
  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, 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("忽略试图进行多个固件更新");
        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(str);
      else
        ui_print("\n");       
    }
    else 
      LOGE("未知命令[%s]\n", command);   
  }
  
  fclose(from_child);

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

  if (firmware_type != NULL) 
    return handle_firmware_update(firmware_type, firmware_filename, zip);
  else 
    return INSTALL_SUCCESS;
  
}