Example #1
0
static void action_rename_kbd_finished(void* data, char* input) {
    rename_data* renameData = (rename_data*) data;

    if(strlen(input) == 0) {
        error_display(NULL, NULL, NULL, "No name specified.");
    }

    file_info* targetInfo = (file_info*) renameData->target->data;

    Result res = 0;

    char parentPath[FILE_PATH_MAX] = {'\0'};
    util_get_parent_path(parentPath, targetInfo->path, FILE_PATH_MAX);

    char dstPath[FILE_PATH_MAX] = {'\0'};
    snprintf(dstPath, FILE_PATH_MAX, "%s%s", parentPath, input);

    FS_Path* srcFsPath = util_make_path_utf8(targetInfo->path);
    if(srcFsPath != NULL) {
        FS_Path* dstFsPath = util_make_path_utf8(dstPath);
        if(dstFsPath != NULL) {
            if(targetInfo->isDirectory) {
                res = FSUSER_RenameDirectory(targetInfo->archive, *srcFsPath, targetInfo->archive, *dstFsPath);
            } else {
                res = FSUSER_RenameFile(targetInfo->archive, *srcFsPath, targetInfo->archive, *dstFsPath);
            }

            util_free_path_utf8(dstFsPath);
        } else {
            res = R_FBI_OUT_OF_MEMORY;
        }

        util_free_path_utf8(srcFsPath);
    } else {
        res = R_FBI_OUT_OF_MEMORY;
    }

    if(R_SUCCEEDED(res)) {
        if(strncmp(renameData->target->name, "<current directory>", LIST_ITEM_NAME_MAX) != 0 && strncmp(renameData->target->name, "<current file>", LIST_ITEM_NAME_MAX) != 0) {
            strncpy(renameData->target->name, input, LIST_ITEM_NAME_MAX);
        }

        strncpy(targetInfo->name, input, FILE_NAME_MAX);
        strncpy(targetInfo->path, dstPath, FILE_PATH_MAX);

        linked_list_sort(renameData->items, util_compare_file_infos);

        prompt_display("Success", "Renamed.", COLOR_TEXT, false, NULL, NULL, NULL);
    } else {
        error_display_res(NULL, NULL, NULL, res, "Failed to perform rename.");
    }

    free(data);
}
Example #2
0
static Result action_paste_files_open_dst(void* data, u32 index, void* initialReadBlock, u64 size, u32* handle) {
    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);

    FS_Path* fsPath = util_make_path_utf8(dstPath);
    if(fsPath != NULL) {
        Handle currHandle;
        pasteData->currExists = R_SUCCEEDED(FSUSER_OpenFile(&currHandle, pasteData->target->archive, *fsPath, FS_OPEN_READ, 0));
        if(pasteData->currExists) {
            FSFILE_Close(currHandle);
        } else {
            res = FSUSER_CreateFile(pasteData->target->archive, *fsPath, 0, size);
        }

        if(R_SUCCEEDED(res)) {
            res = FSUSER_OpenFile(handle, pasteData->target->archive, *fsPath, FS_OPEN_WRITE, 0);
        }

        util_free_path_utf8(fsPath);
    } else {
        res = R_FBI_OUT_OF_MEMORY;
    }

    return res;
}
Example #3
0
static Result action_install_tickets_open_src(void* data, u32 index, u32* handle) {
    install_tickets_data* installData = (install_tickets_data*) data;

    FS_Path* fsPath = util_make_path_utf8(installData->contents[index]);

    Result res = FSUSER_OpenFile(handle, *installData->base->archive, *fsPath, FS_OPEN_READ, 0);

    util_free_path_utf8(fsPath);

    return res;
}
Example #4
0
static Result action_paste_files_open_src(void* data, u32 index, u32* handle) {
    paste_files_data* pasteData = (paste_files_data*) data;

    Result res = 0;

    FS_Path* fsPath = util_make_path_utf8(((file_info*) ((list_item*) linked_list_get(&pasteData->contents, index))->data)->path);
    if(fsPath != NULL) {
        res = FSUSER_OpenFile(handle, clipboard_get_archive(), *fsPath, FS_OPEN_READ, 0);

        util_free_path_utf8(fsPath);
    } else {
        res = R_FBI_OUT_OF_MEMORY;
    }

    return res;
}
Example #5
0
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;
}
Example #6
0
static Result action_import_twl_save_open_src(void* data, u32 index, u32* handle) {
    import_twl_save_data* importData = (import_twl_save_data*) data;

    Result res = 0;

    char path[FILE_PATH_MAX];
    snprintf(path, sizeof(path), "/fbi/save/%s.sav", importData->title->productCode);

    FS_Path* fsPath = util_make_path_utf8(path);
    if(fsPath != NULL) {
        res = FSUSER_OpenFileDirectly(handle, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""), *fsPath, FS_OPEN_READ, 0);

        util_free_path_utf8(fsPath);
    } else {
        res = R_FBI_OUT_OF_MEMORY;
    }

    return res;
}
Example #7
0
static Result action_paste_files_open_dst(void* data, u32 index, void* initialReadBlock, u64 size, u32* handle) {
    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);

    FS_Path* fsPath = util_make_path_utf8(dstPath);
    if(fsPath != NULL) {
        Handle currHandle;
        if(R_SUCCEEDED(FSUSER_OpenFile(&currHandle, pasteData->target->archive, *fsPath, FS_OPEN_READ, 0))) {
            FSFILE_Close(currHandle);
            if(R_SUCCEEDED(res = FSUSER_DeleteFile(pasteData->target->archive, *fsPath))) {
                linked_list_iter iter;
                linked_list_iterate(pasteData->items, &iter);

                while(linked_list_iter_has_next(&iter)) {
                    list_item* item = (list_item*) linked_list_iter_next(&iter);
                    file_info* currInfo = (file_info*) item->data;

                    if(strncmp(currInfo->path, dstPath, FILE_PATH_MAX) == 0) {
                        linked_list_iter_remove(&iter);
                        task_free_file(item);
                    }
                }
            }
        }

        if(R_SUCCEEDED(res) && R_SUCCEEDED(res = FSUSER_CreateFile(pasteData->target->archive, *fsPath, ((file_info*) ((list_item*) linked_list_get(&pasteData->contents, index))->data)->attributes & ~FS_ATTRIBUTE_READ_ONLY, size))) {
            res = FSUSER_OpenFile(handle, pasteData->target->archive, *fsPath, FS_OPEN_WRITE, 0);
        }

        util_free_path_utf8(fsPath);
    } else {
        res = R_FBI_OUT_OF_MEMORY;
    }

    return res;
}
Example #8
0
Result task_create_file_item(list_item** out, FS_Archive archive, const char* path) {
    Result res = 0;

    list_item* item = (list_item*) calloc(1, sizeof(list_item));
    if(item != NULL) {
        file_info* fileInfo = (file_info*) calloc(1, sizeof(file_info));
        if(fileInfo != NULL) {
            fileInfo->archive = archive;
            util_get_path_file(fileInfo->name, path, FILE_NAME_MAX);
            fileInfo->attributes = 0;

            fileInfo->size = 0;
            fileInfo->isCia = false;
            fileInfo->isTicket = false;

            if(util_is_dir(archive, path)) {
                item->color = COLOR_DIRECTORY;

                size_t len = strlen(path);
                if(len > 1 && path[len - 1] != '/') {
                    snprintf(fileInfo->path, FILE_PATH_MAX, "%s/", path);
                } else {
                    strncpy(fileInfo->path, path, FILE_PATH_MAX);
                }

                fileInfo->attributes = FS_ATTRIBUTE_DIRECTORY;
            } else {
                item->color = COLOR_FILE;

                strncpy(fileInfo->path, path, FILE_PATH_MAX);

                FS_Path* fileFsPath = util_make_path_utf8(fileInfo->path);
                if(fileFsPath != NULL) {
                    Handle fileHandle;
                    if(R_SUCCEEDED(FSUSER_OpenFile(&fileHandle, archive, *fileFsPath, FS_OPEN_READ, 0))) {
                        FSFILE_GetAttributes(fileHandle, &fileInfo->attributes);
                        FSFILE_GetSize(fileHandle, &fileInfo->size);

                        size_t len = strlen(fileInfo->path);
                        if(len > 4) {
                            if(strcasecmp(&fileInfo->path[len - 4], ".cia") == 0) {
                                AM_TitleEntry titleEntry;
                                if(R_SUCCEEDED(AM_GetCiaFileInfo(MEDIATYPE_SD, &titleEntry, fileHandle))) {
                                    fileInfo->isCia = true;
                                    fileInfo->ciaInfo.titleId = titleEntry.titleID;
                                    fileInfo->ciaInfo.version = titleEntry.version;
                                    fileInfo->ciaInfo.installedSize = titleEntry.size;
                                    fileInfo->ciaInfo.hasMeta = false;

                                    if((titleEntry.titleID & 0x0000801000000002) != 0 && R_SUCCEEDED(AM_GetCiaFileInfo(MEDIATYPE_NAND, &titleEntry, fileHandle))) {
                                        fileInfo->ciaInfo.installedSize = titleEntry.size;
                                    }

                                    SMDH* smdh = (SMDH*) calloc(1, sizeof(SMDH));
                                    if(smdh != NULL) {
                                        if(R_SUCCEEDED(util_get_cia_file_smdh(smdh, fileHandle))) {
                                            if(smdh->magic[0] == 'S' && smdh->magic[1] == 'M' && smdh->magic[2] == 'D' && smdh->magic[3] == 'H') {
                                                u8 systemLanguage = CFG_LANGUAGE_EN;
                                                CFGU_GetSystemLanguage(&systemLanguage);

                                                fileInfo->ciaInfo.hasMeta = true;
                                                utf16_to_utf8((uint8_t*) fileInfo->ciaInfo.meta.shortDescription, smdh->titles[systemLanguage].shortDescription, sizeof(fileInfo->ciaInfo.meta.shortDescription) - 1);
                                                utf16_to_utf8((uint8_t*) fileInfo->ciaInfo.meta.longDescription, smdh->titles[systemLanguage].longDescription, sizeof(fileInfo->ciaInfo.meta.longDescription) - 1);
                                                utf16_to_utf8((uint8_t*) fileInfo->ciaInfo.meta.publisher, smdh->titles[systemLanguage].publisher, sizeof(fileInfo->ciaInfo.meta.publisher) - 1);
                                                fileInfo->ciaInfo.meta.region = smdh->region;
                                                fileInfo->ciaInfo.meta.texture = screen_load_texture_tiled_auto(smdh->largeIcon, sizeof(smdh->largeIcon), 48, 48, GPU_RGB565, false);
                                            }
                                        }

                                        free(smdh);
                                    }
                                }
                            } else if(strcasecmp(&fileInfo->path[len - 4], ".tik") == 0) {
                                u32 bytesRead = 0;

                                u8 sigType = 0;
                                if(R_SUCCEEDED(FSFILE_Read(fileHandle, &bytesRead, 3, &sigType, sizeof(sigType))) && bytesRead == sizeof(sigType) && sigType <= 5) {
                                    static u32 dataOffsets[6] = {0x240, 0x140, 0x80, 0x240, 0x140, 0x80};
                                    static u32 titleIdOffset = 0x9C;

                                    u64 titleId = 0;
                                    if(R_SUCCEEDED(FSFILE_Read(fileHandle, &bytesRead, dataOffsets[sigType] + titleIdOffset, &titleId, sizeof(titleId))) && bytesRead == sizeof(titleId)) {
                                        fileInfo->isTicket = true;
                                        fileInfo->ticketInfo.titleId = __builtin_bswap64(titleId);
                                    }
                                }
                            }
                        }

                        FSFILE_Close(fileHandle);
                    }

                    util_free_path_utf8(fileFsPath);
                }
            }

            strncpy(item->name, fileInfo->name, LIST_ITEM_NAME_MAX);
            item->data = fileInfo;

            *out = item;
        } else {
            free(item);

            res = R_FBI_OUT_OF_MEMORY;
        }
    } else {
        res = R_FBI_OUT_OF_MEMORY;
    }

    return res;
}
Example #9
0
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;
}