static Result action_paste_files_close_dst(void* data, u32 index, bool succeeded, u32 handle) { paste_files_data* pasteData = (paste_files_data*) data; Result res = 0; if(R_SUCCEEDED(res = FSFILE_Close(handle))) { char dstPath[FILE_PATH_MAX]; action_paste_files_get_dst_path(pasteData, index, dstPath); char parentPath[FILE_PATH_MAX]; util_get_parent_path(parentPath, dstPath, FILE_PATH_MAX); char baseDstPath[FILE_PATH_MAX]; if(pasteData->target->attributes & FS_ATTRIBUTE_DIRECTORY) { strncpy(baseDstPath, pasteData->target->path, FILE_PATH_MAX); } else { util_get_parent_path(baseDstPath, pasteData->target->path, FILE_PATH_MAX); } if(strncmp(parentPath, baseDstPath, FILE_PATH_MAX) == 0) { list_item* dstItem = NULL; if(R_SUCCEEDED(task_create_file_item(&dstItem, pasteData->target->archive, dstPath, ((file_info*) ((list_item*) linked_list_get(&pasteData->contents, index))->data)->attributes & ~FS_ATTRIBUTE_READ_ONLY))) { linked_list_add(pasteData->items, dstItem); } } } return res; }
static void files_repopulate(files_data* listData, linked_list* items) { if(!listData->populateData.finished) { svcSignalEvent(listData->populateData.cancelEvent); while(!listData->populateData.finished) { svcSleepThread(1000000); } } if(listData->dirItem != NULL) { task_free_file(listData->dirItem); listData->dirItem = NULL; } Result res = 0; if(R_SUCCEEDED(res = task_create_file_item(&listData->dirItem, listData->archive, listData->currDir))) { listData->populateData.items = items; listData->populateData.base = (file_info*) listData->dirItem->data; res = task_populate_files(&listData->populateData); } if(R_FAILED(res)) { error_display_res(NULL, NULL, NULL, res, "Failed to initiate file list population."); } listData->populated = true; }
static Result action_paste_files_make_dst_directory(void* data, u32 index) { paste_files_data* pasteData = (paste_files_data*) data; Result res = 0; char dstPath[FILE_PATH_MAX]; action_paste_files_get_dst_path(pasteData, index, dstPath); if(R_SUCCEEDED(res = util_ensure_dir(pasteData->target->archive, dstPath))) { char parentPath[FILE_PATH_MAX]; util_get_parent_path(parentPath, dstPath, FILE_PATH_MAX); char baseDstPath[FILE_PATH_MAX]; if(pasteData->target->attributes & FS_ATTRIBUTE_DIRECTORY) { strncpy(baseDstPath, pasteData->target->path, FILE_PATH_MAX); } else { util_get_parent_path(baseDstPath, pasteData->target->path, FILE_PATH_MAX); } if(strncmp(parentPath, baseDstPath, FILE_PATH_MAX) == 0) { list_item* dstItem = NULL; if(R_SUCCEEDED(res) && R_SUCCEEDED(task_create_file_item(&dstItem, pasteData->target->archive, dstPath))) { linked_list_add(pasteData->items, dstItem); } } } return res; }
static Result action_paste_files_make_dst_directory(void* data, u32 index) { paste_files_data* pasteData = (paste_files_data*) data; Result res = 0; u32 attributes = ((file_info*) ((list_item*) linked_list_get(&pasteData->contents, index))->data)->attributes; char dstPath[FILE_PATH_MAX]; action_paste_files_get_dst_path(pasteData, index, dstPath); FS_Path* fsPath = util_make_path_utf8(dstPath); if(fsPath != NULL) { Handle dirHandle = 0; if(R_SUCCEEDED(FSUSER_OpenDirectory(&dirHandle, pasteData->target->archive, *fsPath))) { FSDIR_Close(dirHandle); } else { res = FSUSER_CreateDirectory(pasteData->target->archive, *fsPath, attributes); } util_free_path_utf8(fsPath); } else { res = R_FBI_OUT_OF_MEMORY; } if(R_SUCCEEDED(res)) { char parentPath[FILE_PATH_MAX]; util_get_parent_path(parentPath, dstPath, FILE_PATH_MAX); char baseDstPath[FILE_PATH_MAX]; if(pasteData->target->attributes & FS_ATTRIBUTE_DIRECTORY) { strncpy(baseDstPath, pasteData->target->path, FILE_PATH_MAX); } else { util_get_parent_path(baseDstPath, pasteData->target->path, FILE_PATH_MAX); } if(strncmp(parentPath, baseDstPath, FILE_PATH_MAX) == 0) { list_item* dstItem = NULL; if(R_SUCCEEDED(res) && R_SUCCEEDED(task_create_file_item(&dstItem, pasteData->target->archive, dstPath, attributes))) { linked_list_add(pasteData->items, dstItem); } } } return res; }
static void task_populate_files_thread(void* arg) { populate_files_data* data = (populate_files_data*) arg; Result res = 0; list_item* baseItem = NULL; if(R_SUCCEEDED(res = task_create_file_item(&baseItem, data->archive, data->path))) { file_info* baseInfo = (file_info*) baseItem->data; if(baseInfo->attributes & FS_ATTRIBUTE_DIRECTORY) { strncpy(baseItem->name, "<current directory>", LIST_ITEM_NAME_MAX); } else { strncpy(baseItem->name, "<current file>", LIST_ITEM_NAME_MAX); } linked_list queue; linked_list_init(&queue); linked_list_add(&queue, baseItem); bool quit = false; while(!quit && R_SUCCEEDED(res) && linked_list_size(&queue) > 0) { u32 tail = linked_list_size(&queue) - 1; list_item* currItem = (list_item*) linked_list_get(&queue, tail); file_info* curr = (file_info*) currItem->data; linked_list_remove_at(&queue, tail); if(data->includeBase || currItem != baseItem) { linked_list_add(data->items, currItem); } if(curr->attributes & FS_ATTRIBUTE_DIRECTORY) { FS_Path* fsPath = util_make_path_utf8(curr->path); if(fsPath != NULL) { Handle dirHandle = 0; if(R_SUCCEEDED(res = FSUSER_OpenDirectory(&dirHandle, curr->archive, *fsPath))) { u32 entryCount = 0; FS_DirectoryEntry* entries = (FS_DirectoryEntry*) calloc(MAX_FILES, sizeof(FS_DirectoryEntry)); if(entries != NULL) { if(R_SUCCEEDED(res = FSDIR_Read(dirHandle, &entryCount, MAX_FILES, entries)) && entryCount > 0) { qsort(entries, entryCount, sizeof(FS_DirectoryEntry), task_populate_files_compare_directory_entries); for(u32 i = 0; i < entryCount && R_SUCCEEDED(res); i++) { svcWaitSynchronization(task_get_pause_event(), U64_MAX); if(task_is_quit_all() || svcWaitSynchronization(data->cancelEvent, 0) == 0) { quit = true; break; } char name[FILE_NAME_MAX] = {'\0'}; utf16_to_utf8((uint8_t*) name, entries[i].name, FILE_NAME_MAX - 1); if(data->filter == NULL || data->filter(data->filterData, name, entries[i].attributes)) { char path[FILE_PATH_MAX] = {'\0'}; snprintf(path, FILE_PATH_MAX, "%s%s", curr->path, name); list_item* item = NULL; if(R_SUCCEEDED(res = task_create_file_item(&item, curr->archive, path))) { if(data->recursive && (((file_info*) item->data)->attributes & FS_ATTRIBUTE_DIRECTORY)) { linked_list_add(&queue, item); } else { linked_list_add(data->items, item); } } } } } free(entries); } else { res = R_FBI_OUT_OF_MEMORY; } FSDIR_Close(dirHandle); } util_free_path_utf8(fsPath); } else { res = R_FBI_OUT_OF_MEMORY; } } } if(!data->includeBase) { task_free_file(baseItem); } } svcCloseHandle(data->cancelEvent); data->result = res; data->finished = true; }