int extractArchivePath(char *src, char *dst, FileProcessParam *param) { if (!uf) return -1; SceIoStat stat; memset(&stat, 0, sizeof(SceIoStat)); if (archiveFileGetstat(src, &stat) < 0) { FileList list; memset(&list, 0, sizeof(FileList)); fileListGetArchiveEntries(&list, src, SORT_NONE); int ret = sceIoMkdir(dst, 0777); if (ret < 0 && ret != SCE_ERROR_ERRNO_EEXIST) { fileListEmpty(&list); return ret; } if (param) { if (param->value) (*param->value) += DIRECTORY_SIZE; if (param->SetProgress) param->SetProgress(param->value ? *param->value : 0, param->max); if (param->cancelHandler && param->cancelHandler()) { fileListEmpty(&list); return 0; } } FileListEntry *entry = list.head->next; // Ignore .. int i; for (i = 0; i < list.length - 1; i++) { char *src_path = malloc(strlen(src) + strlen(entry->name) + 2); snprintf(src_path, MAX_PATH_LENGTH, "%s%s", src, entry->name); char *dst_path = malloc(strlen(dst) + strlen(entry->name) + 2); snprintf(dst_path, MAX_PATH_LENGTH, "%s%s", dst, entry->name); int ret = extractArchivePath(src_path, dst_path, param); free(dst_path); free(src_path); if (ret <= 0) { fileListEmpty(&list); return ret; } entry = entry->next; } fileListEmpty(&list); } else { SceUID fdsrc = archiveFileOpen(src, SCE_O_RDONLY, 0); if (fdsrc < 0) return fdsrc; SceUID fddst = sceIoOpen(dst, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777); if (fddst < 0) { archiveFileClose(fdsrc); return fddst; } void *buf = malloc(TRANSFER_SIZE); uint64_t seek = 0; while (1) { int read = archiveFileRead(fdsrc, buf, TRANSFER_SIZE); if (read < 0) { free(buf); sceIoClose(fddst); archiveFileClose(fdsrc); return read; } if (read == 0) break; int written = sceIoWrite(fddst, buf, read); if (written == SCE_ERROR_ERRNO_ENODEV) { fddst = sceIoOpen(dst, SCE_O_WRONLY | SCE_O_CREAT, 0777); if (fddst >= 0) { sceIoLseek(fddst, seek, SCE_SEEK_SET); written = sceIoWrite(fddst, buf, read); } } if (written < 0) { free(buf); sceIoClose(fddst); archiveFileClose(fdsrc); return written; } seek += written; if (param) { if (param->value) (*param->value) += read; if (param->SetProgress) param->SetProgress(param->value ? *param->value : 0, param->max); if (param->cancelHandler && param->cancelHandler()) { free(buf); sceIoClose(fddst); archiveFileClose(fdsrc); return 0; } } } free(buf); sceIoClose(fddst); archiveFileClose(fdsrc); } return 1; }
int copy_thread(SceSize args_size, CopyArguments *args) { SceUID thid = -1; // Set progress to 0% sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 0); sceKernelDelayThread(DIALOG_WAIT); // Needed to see the percentage char src_path[MAX_PATH_LENGTH], dst_path[MAX_PATH_LENGTH]; FileListEntry *copy_entry = NULL; if (args->copy_mode == COPY_MODE_MOVE) { // Move // Update thread thid = createStartUpdateThread(args->copy_list->length); copy_entry = args->copy_list->head; int i; for (i = 0; i < args->copy_list->length; i++) { snprintf(src_path, MAX_PATH_LENGTH, "%s%s", args->copy_list->path, copy_entry->name); snprintf(dst_path, MAX_PATH_LENGTH, "%s%s", args->file_list->path, copy_entry->name); int res = sceIoRename(src_path, dst_path); // TODO: if (res == SCE_ERROR_ERRNO_EEXIST) if folder if (res < 0) { closeWaitDialog(); errorDialog(res); goto EXIT; } SetProgress(i + 1, args->copy_list->length); copy_entry = copy_entry->next; } // Set progress to 100% sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100); sceKernelDelayThread(COUNTUP_WAIT); // Close sceMsgDialogClose(); dialog_step = DIALOG_STEP_MOVED; } else { // Copy if (args->copy_mode == COPY_MODE_EXTRACT) archiveOpen(args->archive_path); // Get src paths info uint32_t size = 0, folders = 0, files = 0; copy_entry = args->copy_list->head; int i; for (i = 0; i < args->copy_list->length; i++) { disableAutoSuspend(); snprintf(src_path, MAX_PATH_LENGTH, "%s%s", args->copy_list->path, copy_entry->name); if (args->copy_mode == COPY_MODE_EXTRACT) { addEndSlash(src_path); getArchivePathInfo(src_path, &size, &folders, &files); } else { removeEndSlash(src_path); getPathInfo(src_path, &size, &folders, &files); } copy_entry = copy_entry->next; } // Update thread thid = createStartUpdateThread(size + folders); // Copy process uint32_t value = 0; copy_entry = args->copy_list->head; for (i = 0; i < args->copy_list->length; i++) { snprintf(src_path, MAX_PATH_LENGTH, "%s%s", args->copy_list->path, copy_entry->name); snprintf(dst_path, MAX_PATH_LENGTH, "%s%s", args->file_list->path, copy_entry->name); if (args->copy_mode == COPY_MODE_EXTRACT) { addEndSlash(src_path); addEndSlash(dst_path); int res = extractArchivePath(src_path, dst_path, &value, size + folders, SetProgress); if (res < 0) { closeWaitDialog(); errorDialog(res); goto EXIT; } } else { removeEndSlash(src_path); removeEndSlash(dst_path); int res = copyPath(src_path, dst_path, &value, size + folders, SetProgress); if (res < 0) { closeWaitDialog(); errorDialog(res); goto EXIT; } } copy_entry = copy_entry->next; } // Set progress to 100% sceMsgDialogProgressBarSetValue(SCE_MSG_DIALOG_PROGRESSBAR_TARGET_BAR_DEFAULT, 100); sceKernelDelayThread(COUNTUP_WAIT); // Close sceMsgDialogClose(); dialog_step = DIALOG_STEP_COPIED; } EXIT: if (thid >= 0) sceKernelWaitThreadEnd(thid, NULL, NULL); return sceKernelExitDeleteThread(0); }