bool arnMigrate() { const static FS_Path aurei = fsMakePath(PATH_ASCII, "/aurei"); const static FS_Path luma = fsMakePath(PATH_ASCII, "/luma"); FS_Archive sdmcArchive = { 0x00000009,{ PATH_EMPTY, 1, (u8*) "" } }; if (FSUSER_OpenArchive(&sdmcArchive) != 0) { std::printf("\nCould not access SD Card (?)\n\n"); return false; } // Check if /luma already existsHandle directory = { 0 }; if (FSUSER_OpenDirectory(NULL, sdmcArchive, luma) == 0) { std::printf("Luma directory already exists, skipping migration..\n"); return true; } if (!renameRecursive(sdmcArchive, "/aurei", "/luma")) { FSUSER_CloseArchive(&sdmcArchive); return false; } // Delete the source directory and check if it succeeds Result res = FSUSER_DeleteDirectoryRecursively(sdmcArchive, aurei); if (res != 0) { std::printf("\nWARN: Could not delete original /aurei (%ld)!\n\n", res); } FSUSER_CloseArchive(&sdmcArchive); return true; }
// ================================================== Result FS_filesysExit(Handle* sdHandle, Handle* saveHandle, FS_archive* sdArchive, FS_archive* saveArchive) // -------------------------------------------------- { FSUSER_CloseArchive(saveHandle, saveArchive); FSUSER_CloseArchive(sdHandle, sdArchive); svcCloseHandle(*saveHandle); svcCloseHandle(*sdHandle); return 0; }
Result filesystemExit() { Result ret; ret = FSUSER_CloseArchive(&saveGameFsHandle, &saveGameArchive); ret = FSUSER_CloseArchive(&sdmcFsHandle, &sdmcArchive); ret = svcCloseHandle(saveGameFsHandle); ret = svcCloseHandle(sdmcFsHandle); return ret; }
Result filesystemExit() { Result ret; ret = FSUSER_CloseArchive(&saveGameArchive); ret |= FSUSER_CloseArchive(&sdmcArchive); fsEndUseSession(); fsExit(); return ret; }
void autoRestore(menu m) { //This still needs user input. for(unsigned i = 0; i < m.getSize(); i++) { FS_Archive saveArch; if(m.optSelected(i) && openSaveArch(&saveArch, sdTitle[i], false)) restoreData(sdTitle[i], saveArch, MODE_SAVE); FSUSER_CloseArchive(&saveArch); FS_Archive extArch; if(m.optSelected(i) && openExtdata(&extArch, sdTitle[i], false)) restoreData(sdTitle[i], extArch, MODE_EXTDATA); FSUSER_CloseArchive(&extArch); } }
Result backupByConfig(u8 *filebuffer, size_t bufsize) { memset(filebuffer, 0, bufsize); FILE *configfile = fopen("config.txt", "r"); if (configfile==NULL) return errno; char source_path[1000], sd_destination[1000]; u32 source_archive; mediatypes_enum mtype; FS_archiveIds atype; int buf2size = 0x10000; u8 *buf2 = malloc(buf2size); if (buf2==NULL) { printf("malloc failed\n"); gfxFlushBuffers(); gfxSwapBuffers(); return -1; } memset(buf2, 0, buf2size); while (fgets((char*) buf2, buf2size, configfile) != NULL) { if (sscanf((const char*) buf2, "DUMP \"%x:%999[^\"]\" \"%999[^\"]\"", (unsigned int*) &source_archive, source_path, sd_destination) == 3) { if (source_archive >= 0x80000000) { mtype = mediatype_NAND; atype = ARCH_SHARED_EXTDATA; } else { mtype = mediatype_SDMC; atype = ARCH_EXTDATA; } u32 extdata_archive_lowpathdata[3] = {mtype, source_archive, 0}; extdata_archive = (FS_archive){atype, (FS_path){PATH_BINARY, 0xC, (u8*)extdata_archive_lowpathdata}}; Result ret = FSUSER_OpenArchive(NULL, &extdata_archive); if(ret!=0) { printf("could not open archive\n"); gfxFlushBuffers(); gfxSwapBuffers(); continue; } printf("Dumping from %s\n", source_path); gfxFlushBuffers(); gfxSwapBuffers(); ret = archive_copyfile(Extdata_Archive, SDArchive, source_path, sd_destination, filebuffer, 0, bufsize, source_path); if (ret) { printf("Copying failed!\n"); } else { printf("Success.\n"); } gfxFlushBuffers(); gfxSwapBuffers(); FSUSER_CloseArchive(NULL, &extdata_archive); } } free(buf2); fclose(configfile); return 0; }
static void files_free_data(files_data* data) { if(!data->populateData.finished) { svcSignalEvent(data->populateData.cancelEvent); while(!data->populateData.finished) { svcSleepThread(1000000); } } if(data->dirItem != NULL) { task_free_file(data->dirItem); data->dirItem = NULL; } if(data->archive != 0) { FSUSER_CloseArchive(data->archive); data->archive = 0; } if(data->archivePath.data != NULL) { free((void*) data->archivePath.data); data->archivePath.data = NULL; } free(data); }
static void files_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { files_data* listData = (files_data*) data; if(hidKeysDown() & KEY_B) { if(strcmp(listData->currDir.path, "/") == 0) { if(listData->archive.handle != 0) { FSUSER_CloseArchive(&listData->archive); listData->archive.handle = 0; } if(listData->archivePath != NULL) { free(listData->archivePath); listData->archivePath = NULL; } if(listData->cancelEvent != 0) { svcSignalEvent(listData->cancelEvent); while(svcWaitSynchronization(listData->cancelEvent, 0) == 0) { svcSleepThread(1000000); } listData->cancelEvent = 0; } ui_pop(); list_destroy(view); free(listData); return; } else { files_navigate(listData, listData->parentDir.path); } } if(hidKeysDown() & KEY_Y) { files_action_open(&listData->currDir, &listData->populated); return; } if(selected != NULL && selected->data != NULL && (selectedTouched || (hidKeysDown() & KEY_A))) { file_info* fileInfo = (file_info*) selected->data; if(util_is_dir(&listData->archive, fileInfo->path)) { files_navigate(listData, fileInfo->path); } else { files_action_open(fileInfo, &listData->populated); return; } } if(!listData->populated || (hidKeysDown() & KEY_X)) { files_repopulate(listData); } if(*itemCount != &listData->count || *items != listData->items) { *itemCount = &listData->count; *items = listData->items; } }
Result restoreFromSd(u8 *buf, size_t bufsize) { memset(buf, 0, bufsize); FILE *configfile = fopen("config.txt", "r"); if (configfile==NULL) return errno; char sd_source[1000], destination_path[1000]; u32 destination_archive; mediatypes_enum mtype; FS_archiveIds atype; u8 *filebuffer2 = malloc(bufsize); memset(filebuffer2, 0, bufsize); while (fgets((char*) buf, bufsize, configfile) != NULL) { if (sscanf((const char*) buf, "RESTORE \"%999[^\"]\" \"%x:%999[^\"]\"", sd_source, (unsigned int*) &destination_archive, destination_path) == 3) { if (destination_archive >= 0x80000000) { mtype = mediatype_NAND; atype = ARCH_SHARED_EXTDATA; } else { mtype = mediatype_SDMC; atype = ARCH_EXTDATA; } u32 extdata_archive_lowpathdata[3] = {mtype, destination_archive, 0}; extdata_archive = (FS_archive) { atype, (FS_path) { PATH_BINARY, 0xC, (u8*)extdata_archive_lowpathdata } }; Result ret = FSUSER_OpenArchive(NULL, &extdata_archive); if(ret!=0) { printf("could not open archive\n"); gfxFlushBuffers(); gfxSwapBuffers(); continue; } printf("Restoring to %s\n", destination_path); gfxFlushBuffers(); gfxSwapBuffers(); ret = archive_copyfile(SDArchive, Extdata_Archive, sd_source, destination_path, filebuffer2, 0, bufsize, destination_path); if (ret) { printf("Copying failed!\n"); } else { printf("Success.\n"); } gfxFlushBuffers(); gfxSwapBuffers(); FSUSER_CloseArchive(NULL, &extdata_archive); } } free(filebuffer2); fclose(configfile); return 0; }
/*! Clean up SDMC device */ Result sdmcExit(void) { Result rc; rc = FSUSER_CloseArchive(NULL, &sdmcArchive); if(rc == 0) RemoveDevice("sdmc"); return rc; }
void autoBackup(menu m) { showMessage("This can take a few minutes depending on how many titles are selected."); progressBar autoDump((float)m.getSelectCount(), "Copying saves..."); //Keep track of what's done float dumpCount = 0; for(unsigned i = 0; i < m.getSize(); i++) { //This is for titles with no save archive ex. Fantasy Life bool dumped = false; FS_Archive saveArch; if(m.optSelected(i) && openSaveArch(&saveArch, sdTitle[i], false))//if it's selected and we can open save archive { createTitleDir(sdTitle[i], MODE_SAVE); backupData(sdTitle[i], saveArch, MODE_SAVE, true); dumpCount++; dumped = true; } FSUSER_CloseArchive(&saveArch); FS_Archive extArch; if(m.optSelected(i) && openExtdata(&extArch, sdTitle[i], false)) { createTitleDir(sdTitle[i], MODE_EXTDATA); backupData(sdTitle[i], extArch, MODE_EXTDATA, true); //check first to make sure we don't count it twice because no save arch if(!dumped) dumpCount++; } FSUSER_CloseArchive(&extArch); sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); autoDump.draw(i); sf2d_end_frame(); sf2d_swapbuffers(); } showMessage("Complete!"); }
void clipboard_clear() { clipboard_has = false; clipboard_contents_only = false; memset(clipboard_path, '\0', FILE_PATH_MAX); if(clipboard_archive != 0) { FSUSER_CloseArchive(clipboard_archive); clipboard_archive = 0; } }
Result write_savedata(const char* path, const void* data, size_t size) { if(!path || !data || size == 0) return -1; Result ret = -1; int fail = 0; fsUseSession(save_session); ret = FSUSER_OpenArchive(&save_archive, ARCHIVE_SAVEDATA, (FS_Path){PATH_EMPTY, 1, (u8*)""}); if(R_FAILED(ret)) { fail = -1; goto writeFail; } // delete file FSUSER_DeleteFile(save_archive, fsMakePath(PATH_ASCII, path)); FSUSER_ControlArchive(save_archive, ARCHIVE_ACTION_COMMIT_SAVE_DATA, NULL, 0, NULL, 0); Handle file = 0; ret = FSUSER_OpenFile(&file, save_archive, fsMakePath(PATH_ASCII, path), FS_OPEN_CREATE | FS_OPEN_WRITE, 0); if(R_FAILED(ret)) { fail = -2; goto writeFail; } u32 bytes_written = 0; ret = FSFILE_Write(file, &bytes_written, 0, data, size, FS_WRITE_FLUSH | FS_WRITE_UPDATE_TIME); if(R_FAILED(ret)) { fail = -3; goto writeFail; } ret = FSFILE_Close(file); if(R_FAILED(ret)) { fail = -4; goto writeFail; } ret = FSUSER_ControlArchive(save_archive, ARCHIVE_ACTION_COMMIT_SAVE_DATA, NULL, 0, NULL, 0); if(R_FAILED(ret)) fail = -5; writeFail: FSUSER_CloseArchive(save_archive); fsEndUseSession(); if(fail) sprintf(status, "Failed to write to file: %d\n %08lX %08lX", fail, ret, bytes_written); else sprintf(status, "Successfully wrote to file!\n %08lX ", bytes_written); return ret; }
void dumpTicket(void) { Result res = 0; Handle nandDir; u32 entryCount; FS_dirent dirent; printf("Opening NAND...\n"); res = FSUSER_OpenArchive(NULL, &nandArchive); if(res != 0) { printf("%sError opening NAND!\n%.8lX%s\n", TEXT_RED, res, TEXT_RESET); return; } printf("Opening /...\n"); nandPath.data = (u8 *)nandPathString; nandPath.size = (wcslen(nandPathString) + 1) * 2; res = FSUSER_OpenDirectory(NULL, &nandDir, nandArchive, nandPath); if(res != 0) { printf("%sError opening /!\n%.8lX%s\n", TEXT_RED, res, TEXT_RESET); return; } printf("Reading...\n"); for(;;) { res = FSDIR_Read(nandDir, &entryCount, 1, &dirent); if(res != 0) { printf("%sError reading dir!\n%.8lX%s\n", TEXT_RED, res, TEXT_RESET); return; } if(entryCount == 0) { break; } utf16_to_utf8(utf8, dirent.name, 0x106); printf("/%s\n", utf8); } printf("Closing /...\n"); res = FSDIR_Close(nandDir); if(res != 0) { printf("%sError closing /!\n%.8lX%s\n", TEXT_RED, res, TEXT_RESET); return; } printf("Closing NAND...\n"); res = FSUSER_CloseArchive(NULL, &nandArchive); if(res != 0) { printf("%sError closing NAND!\n%.8lX%s\n", TEXT_RED, res, TEXT_RESET); return; } }
std::vector<std::string> listPayloads() { std::vector<std::string> files = {}; FS_Archive sdmcArchive; // Open SD card if (FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, NULL)) != 0) { logPrintf("\nCould not access SD Card (?)\n\n"); return files; } // Open source directory Handle directory = 0; if (FSUSER_OpenDirectory(&directory, sdmcArchive, fsMakePath(PATH_ASCII, "/luma/payloads")) != 0) { logPrintf("\nCould not open /luma/payloads\n\n"); FSUSER_CloseArchive(sdmcArchive); return files; } u32 fileRead = 0; while (true) { FS_DirectoryEntry entry = {}; FSDIR_Read(directory, &fileRead, 1, &entry); if (!fileRead) { break; } // Convert name to ASCII (just cut the other bytes) and compare with prefix char name8[262] = { 0 }; for (size_t i = 0; i < 262; i++) { name8[i] = entry.name[i] % 0xff; } files.push_back(std::string(name8)); } FSUSER_CloseArchive(sdmcArchive); return files; }
/*! Clean up SDMC device */ Result sdmcExit(void) { Result rc = 0; if(!sdmcInitialised) return rc; rc = FSUSER_CloseArchive(sdmcArchive); if(R_SUCCEEDED(rc)) { fsUnexemptFromSession(sdmcArchive); RemoveDevice("sdmc:"); sdmcInitialised = false; } return rc; }
void dumpArchive(mediatypes_enum mediatype, int i, FS_archiveIds archivetype, char *dirpath, u8 *filebuffer, size_t bufsize) { u32 extdata_archive_lowpathdata[3] = {mediatype, i, 0}; extdata_archive = (FS_archive){archivetype, (FS_path){PATH_BINARY, 0xC, (u8*)extdata_archive_lowpathdata}}; Result ret = FSUSER_OpenArchive(NULL, &extdata_archive); if(ret!=0) { return; } printf("Archive 0x%08x opened.\n", (unsigned int) i); gfxFlushBuffers(); gfxSwapBuffers(); mkdir(dirpath, 0777); dumpFolder("/", i, dirpath, filebuffer, bufsize); FSUSER_CloseArchive(NULL, &extdata_archive); }
void DumpSharedRomFS(u8* archive_binary_lowpath) { std::string output_file = BuildSharedRomFSFilename(archive_binary_lowpath); // Read RomFS bin from SaveDataCheck... Handle romfs_handle; u64 romfs_size = 0; u32 romfs_bytes_read = 0; FS_archive savedatacheck_archive = { 0x2345678a, { PATH_BINARY, 16, archive_binary_lowpath } }; u8 file_binary_lowpath[20] = {}; FS_path romfs_path = { PATH_BINARY, 20, file_binary_lowpath }; print(GFX_TOP, "Dumping SaveDataCheck RomFS (%s)... ", output_file.c_str()); FSUSER_OpenFileDirectly(NULL, &romfs_handle, savedatacheck_archive, romfs_path, FS_OPEN_READ, FS_ATTRIBUTE_NONE); FSFILE_GetSize(romfs_handle, &romfs_size); std::unique_ptr<u8> romfs_data_buffer(new u8[romfs_size]); FSFILE_Read(romfs_handle, &romfs_bytes_read, 0, romfs_data_buffer.get(), romfs_size); FSFILE_Close(romfs_handle); // Dump RomFS bin to SDMC... Handle file_handle; u32 bytes_written = 0; FS_path fs_path = FS_makePath(PATH_CHAR, output_file.c_str()); FS_archive sdmc_archive = (FS_archive) { 0x00000009, { PATH_EMPTY, 1, (u8*) "" } }; FSUSER_OpenArchive(NULL, &sdmc_archive); FSUSER_OpenFile(NULL, &file_handle, sdmc_archive, fs_path, FS_OPEN_CREATE | FS_OPEN_WRITE, FS_ATTRIBUTE_NONE); Result res = FSFILE_Write(file_handle, &bytes_written, 0x0, romfs_data_buffer.get(), romfs_size, FS_WRITE_FLUSH); FSFILE_Close(file_handle); FSUSER_CloseArchive(NULL, &sdmc_archive); // Check result... if (res == 0 && bytes_written == romfs_size) print(GFX_TOP, "Done!\n"); else print(GFX_TOP, "Failed!\n"); }
App appGetCiaInfo(const std::string file, MediaType mediaType) { if(!serviceRequire("am")) { return {}; } FS_archive archive = (FS_archive) {ARCH_SDMC, (FS_path) {PATH_EMPTY, 1, (u8*) ""}}; Result archiveResult = FSUSER_OpenArchive(NULL, &archive); if(archiveResult != 0) { platformSetError(serviceParseError((u32) archiveResult)); return {}; } Handle handle = 0; Result openResult = FSUSER_OpenFile(NULL, &handle, archive, FS_makePath(PATH_CHAR, file.c_str()), FS_OPEN_READ, FS_ATTRIBUTE_NONE); if(openResult != 0) { platformSetError(serviceParseError((u32) openResult)); return {}; } TitleList titleInfo; Result infoResult = AM_GetCiaFileInfo(appMediatypeToByte(mediaType), &titleInfo, handle); if(infoResult != 0) { platformSetError(serviceParseError((u32) infoResult)); return {}; } FSFILE_Close(handle); FSUSER_CloseArchive(NULL, &archive); App app; app.titleId = titleInfo.titleID; app.uniqueId = ((u32*) &titleInfo.titleID)[0]; strcpy(app.productCode, "<N/A>"); app.mediaType = mediaType; app.platform = appPlatformFromId(((u16*) &titleInfo.titleID)[3]); app.category = appCategoryFromId(((u16*) &titleInfo.titleID)[2]); app.version = titleInfo.titleVersion; app.size = titleInfo.size; return app; }
Result read_savedata(const char* path, void** data, size_t* size) { if(!path || !data || !size) return -1; Result ret = -1; int fail = 0; void* buffer = NULL; fsUseSession(save_session); ret = FSUSER_OpenArchive(&save_archive, ARCHIVE_SAVEDATA, (FS_Path){PATH_EMPTY, 1, (u8*)""}); if(R_FAILED(ret)) { fail = -1; goto readFail; } Handle file = 0; ret = FSUSER_OpenFile(&file, save_archive, fsMakePath(PATH_ASCII, path), FS_OPEN_READ, 0); if(R_FAILED(ret)) { fail = -2; goto readFail; } u64 file_size = 0; ret = FSFILE_GetSize(file, &file_size); buffer = malloc(file_size); if(!buffer) { fail = -3; goto readFail; } u32 bytes_read = 0; ret = FSFILE_Read(file, &bytes_read, 0, buffer, file_size); if(R_FAILED(ret)) { fail = -4; goto readFail; } ret = FSFILE_Close(file); if(R_FAILED(ret)) { fail = -5; goto readFail; } readFail: FSUSER_CloseArchive(save_archive); fsEndUseSession(); if(fail) { sprintf(status, "Failed to read file: %d\n %08lX %08lX", fail, ret, bytes_read); if(buffer) free(buffer); } else { sprintf(status, "Successfully read file.\n %08lX ", bytes_read); *data = buffer; *size = bytes_read; } return ret; }
void sdmcArchiveExit() { FSUSER_CloseArchive(&sdmcArchive); }
int exec_cia(const char* path, const char** args){ struct stat sBuff; bool fileExists; bool inited; if(path == NULL || path[0] == '\0'){ errno = EINVAL; return -1; } fileExists = stat(path, &sBuff) == 0; if(!fileExists){ errno = ENOENT; return -1; } else if(S_ISDIR(sBuff.st_mode)){ errno = EINVAL;; return -1; } inited = R_SUCCEEDED(amInit()) && R_SUCCEEDED(fsInit()); if(inited){ Result res; AM_TitleEntry ciaInfo; FS_Archive ciaArchive; Handle ciaFile; int ciaInstalled; ciaParam param; int argsLength; //open cia file res = FSUSER_OpenArchive(&ciaArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, "")); if(R_FAILED(res)) errorAndQuit("Cant open SD FS archive."); res = FSUSER_OpenFile(&ciaFile, ciaArchive, fsMakePath(PATH_ASCII, path + 5/*skip "sdmc:"*/), FS_OPEN_READ, 0); if(R_FAILED(res)) errorAndQuit("Cant open CIA file."); res = AM_GetCiaFileInfo(MEDIATYPE_SD, &ciaInfo, ciaFile); if(R_FAILED(res)) errorAndQuit("Cant get CIA file info."); ciaInstalled = isCiaInstalled(ciaInfo.titleID, ciaInfo.version); if(ciaInstalled == -1){ //error errorAndQuit("Could not read title id list."); } else if(ciaInstalled == 0){ //not installed int error = installCia(ciaFile); if(error == -1) errorAndQuit("Cant install CIA."); } FSFILE_Close(ciaFile); FSUSER_CloseArchive(ciaArchive); param.argc = 0; argsLength = 0; char* argLocation = param.args; while(args[param.argc] != NULL){ strcpy(argLocation, args[param.argc]); argLocation += strlen(args[param.argc]) + 1; argsLength += strlen(args[param.argc]) + 1; param.argc++; } res = APT_PrepareToDoApplicationJump(0, ciaInfo.titleID, 0x1); if(R_FAILED(res)) errorAndQuit("CIA cant run, cant prepare."); res = APT_DoApplicationJump(¶m, sizeof(param.argc) + argsLength, argvHmac); if(R_FAILED(res)) errorAndQuit("CIA cant run, cant jump."); //wait for application jump, for some reason its not instant while(1); } //should never be reached amExit(); fsExit(); errno = ENOTSUP; return -1; }
bool installTTP(char* path, u8 mediatype) { // Install a TTP file. (needs libzip and installCIA) Result res; FS_Archive archive = {ARCHIVE_SDMC, {PATH_EMPTY, 0, 0}}; FSUSER_OpenArchive(&archive); FSUSER_DeleteDirectoryRecursively(archive, fsMakePath(PATH_ASCII, "/tmp/cias")); FSUSER_CreateDirectory(archive, fsMakePath(PATH_ASCII, "/tmp/cias"), 0); FILE* ttp = fopen(path, "rb"); FILE* tmp = fopen("/tmp/cias/ttp.tmp", "wb"); u32 titlesAmount; AM_GetTitleCount(mediatype, &titlesAmount); u64* titleIDs = malloc(sizeof(u64) * titlesAmount); AM_GetTitleIdList(mediatype, titlesAmount, titleIDs); u32 size; fseek(ttp, 0x19, SEEK_SET); fread(&size, 0x4, 1, ttp); fseek(ttp, 0x1D, SEEK_SET); u32 blockAmount = size / 0x160000; // Finds how many blocks of 4MB you have in the file u32 i; char* block = malloc(0x160000); for (i = 0; i < blockAmount; i++) { fread(block, 1, 0x160000, ttp); fwrite(block, 1, 0x160000, tmp); } if (size % 0x160000 != 0) { fread(block, 1, size-0x160000*blockAmount, ttp); fwrite(block, 1, size-0x160000*blockAmount, tmp); } free(block); fclose(ttp); fclose(tmp); FSUSER_DeleteDirectoryRecursively(archive, fsMakePath(PATH_ASCII, "/tmp/cias")); FSUSER_CreateDirectory(archive, fsMakePath(PATH_ASCII, "/tmp/cias"), 0); Zip *zipHandle = ZipOpen("/tmp/cias/ttp.tmp"); ZipExtract(zipHandle, NULL); ZipClose(zipHandle); Handle ciaDir; FS_Archive fsarchive; u32 actualAmount; FS_DirectoryEntry* entries; FSUSER_DeleteFile(archive, fsMakePath(PATH_ASCII, "/tmp/cias/ttp.tmp")); res = FSUSER_OpenDirectory(&ciaDir, fsarchive, fsMakePath(PATH_ASCII, "/tmp/cias")); if (res != 0) { free(titleIDs); return false; } entries = malloc(256 * sizeof(FS_DirectoryEntry)); res = FSDIR_Read(ciaDir, &actualAmount, 256, entries); if (res != 0) { free(titleIDs); return false; } char* ciaPath; Handle ciaFileHandle; AM_TitleEntry ciaInfo; for (i = 0; i < actualAmount; i++) { ciaPath = malloc(14 + strlen(entries[i].shortName)); strcpy(ciaPath, "/tmp/cias/"); strcat(ciaPath, entries[i].shortName); strcat(ciaPath, ".cia"); FSUSER_OpenFile(&ciaFileHandle, archive, fsMakePath(PATH_ASCII, ciaPath), FS_OPEN_READ, 0); AM_GetCiaFileInfo(mediatype, &ciaInfo, ciaFileHandle); FSFILE_Close(ciaFileHandle); if (ciaInfo.titleID == 0x0004013800000002LL || ciaInfo.titleID == 0x0004013820000002LL) { if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) // Tries to install the CIA 3 times then give up. If it has to give up, that probably means brick. if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) return false; break; } free(ciaPath); } for (i = 0; i < actualAmount; i++) { ciaPath = malloc(14 + strlen(entries[i].shortName)); strcpy(ciaPath, "/tmp/cias/"); strcat(ciaPath, entries[i].shortName); strcat(ciaPath, ".cia"); if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) // Tries to install the CIA 3 times then give up. If it has to give up, that probably means brick. installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName); free(ciaPath); } FSUSER_DeleteDirectoryRecursively(archive, fsMakePath(PATH_ASCII, "/tmp/cias")); FSUSER_CloseArchive(&archive); free(titleIDs); return true; }
void sharedExtManager() { menu sharedMenu(128, 72, false); sharedMenu.addItem("E0000000"); sharedMenu.addItem("F0000001"); sharedMenu.addItem("F0000002"); sharedMenu.addItem("F0000009"); sharedMenu.addItem("F000000B"); sharedMenu.addItem("F000000C"); sharedMenu.addItem("F000000D"); sharedMenu.addItem("F000000E"); sharedMenu.addItem("Back"); std::u32string info = U"Shared ExtData"; bool loop = true; while(loop) { hidScanInput(); u32 up = hidKeysUp(); sharedMenu.handleInput(up); if(up & KEY_A) { FS_Archive shared; titleData sharedDat; bool opened = false; switch(sharedMenu.getSelected()) { case e0: opened = openSharedExt(&shared, 0xE0000000); sharedDat.nameSafe = tou16("E0000000"); break; case f1: opened = openSharedExt(&shared, 0xF0000001); sharedDat.nameSafe = tou16("F0000001"); break; case f2: opened = openSharedExt(&shared, 0xF0000002); sharedDat.nameSafe = tou16("F0000002"); break; case f9: opened = openSharedExt(&shared, 0xF0000009); sharedDat.nameSafe = tou16("F0000009"); break; case fb: opened = openSharedExt(&shared, 0xF000000B); sharedDat.nameSafe = tou16("F000000B"); break; case fc: opened = openSharedExt(&shared, 0xF000000C); sharedDat.nameSafe = tou16("F000000C"); break; case fd: opened = openSharedExt(&shared, 0xF000000D); sharedDat.nameSafe = tou16("F000000D"); break; case fe: opened = openSharedExt(&shared, 0xF000000E); sharedDat.nameSafe = tou16("F0000000E"); break; case back: loop = false; break; } if(opened) { sharedBackupMenu(sharedDat, shared); } FSUSER_CloseArchive(&shared); } else if(up & KEY_B) break; sf2d_start_frame(GFX_TOP, GFX_LEFT); drawTopBar(info); sharedMenu.draw(); sf2d_end_frame(); sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); sftd_draw_text_wrap(yashi, 0, 0, RGBA8(255, 255, 255, 255), 12, 320, descs[sharedMenu.getSelected()].c_str()); sf2d_end_frame(); sf2d_swapbuffers(); } }
void closeSDArchive() { FSUSER_CloseArchive(NULL, &sdmcArchive); }
bool checkTTP(char region, bool isNew, char* path) { // Verifies the integrity of a TTP file and if it corresponds to the console. (needs sha1.c) mbedtls_sha1_context context; // Just figured out there's a cleaner syntax to perform sdmc reads. Note to future. Handle file; FS_Archive archive = {ARCHIVE_SDMC, {PATH_EMPTY, 0, 0}}; FSUSER_OpenArchive(&archive); Result res = FSUSER_OpenFile(&file, archive, fsMakePath(PATH_ASCII, path), FS_OPEN_READ, 0); FSUSER_CloseArchive(&archive); u32 bytesRead = 0; char* buf = malloc(0x3); FSFILE_Read(file, &bytesRead, 0x0, buf, 0x3); if ((u8)buf[0] != 116 || (u8)buf[1] != 116 || (u8)buf[2] != 112) { free(buf); return false; } // if (buf != "ttp") free(buf); // not sure if freeing all the time is needed, maybe allocating 0x14 since the beginning should be enough buf = malloc(0x1); FSFILE_Read(file, &bytesRead, 0x3, buf, 0x1); if (*buf != region && buf != 0xFF) { free(buf); return false; } //free(buf); //buf = malloc(0x1); FSFILE_Read(file, &bytesRead, 0x4, buf, 0x1); if (*buf != (char)isNew && buf != 0xFF) { free(buf); return false; } free(buf); // SHA-1 check buf = malloc(0x14); FSFILE_Read(file, &bytesRead, 0x5, buf, 0x14); mbedtls_sha1_init(&context); mbedtls_sha1_starts(&context); char t[4]; FSFILE_Read(file, &bytesRead, 0x19, t, 4); // t is an array, so it's a pointer here u32 ulSize = ( ((u32)t[0]) << (8*3) ) | // t[0] stores MSB of UInt32 ( ((u32)t[1]) << (8*2) ) | // .. ( ((u32)t[2]) << (8*1) ) | // .. ( ((u32)t[3]) << (8*0) ) ; // t[3] stores LSB of UInt32 u32 blockAmount = ulSize / 0x160000; u32 i; char* block = malloc(0x160000); for (i = 0; i < blockAmount; i++) { FSFILE_Read(file, &bytesRead, 0x1D+0x160000*i, block, 0x160000); mbedtls_sha1_update(&context, block, 0x160000); } if (ulSize % 0x160000 != 0) { FSFILE_Read(file, &bytesRead, 0x1D+0x160000*blockAmount, block, ulSize-0x160000*blockAmount); mbedtls_sha1_update(&context, block, bytesRead); } free(block); FSFILE_Close(file); //FSUSER_CloseArchive(&archive); char hash[20]; mbedtls_sha1_finish(&context, hash); //shaBytes.c = buf; for (i = 0; i < 20; i++) { if (hash[i] != buf[i]) { free(buf); return false; } } free(buf); return true; }