static int installCia(Handle ciaFile){ Result failed; Handle outputHandle; u64 fileSize; u64 fileOffset = 0; u32 bytesRead; u32 bytesWritten; u8 transferBuffer[FILE_CHUNK_SIZE]; failed = AM_StartCiaInstall(MEDIATYPE_SD, &outputHandle); if(R_FAILED(failed)) return -1; failed = FSFILE_GetSize(ciaFile, &fileSize); if(R_FAILED(failed)) return -1; while(fileOffset < fileSize){ u64 bytesRemaining = fileSize - fileOffset; failed = FSFILE_Read(ciaFile, &bytesRead, fileOffset, transferBuffer, bytesRemaining < FILE_CHUNK_SIZE ? bytesRemaining : FILE_CHUNK_SIZE); if(R_FAILED(failed)){ AM_CancelCIAInstall(outputHandle); return -1; } failed = FSFILE_Write(outputHandle, &bytesWritten, fileOffset, transferBuffer, bytesRead, 0); if(R_FAILED(failed)){ AM_CancelCIAInstall(outputHandle); if(R_DESCRIPTION(failed) == RD_ALREADY_EXISTS) return 1; return -1; } if(bytesWritten != bytesRead){ AM_CancelCIAInstall(outputHandle); return -1; } fileOffset += bytesWritten; } failed = AM_FinishCiaInstall(outputHandle); if(R_FAILED(failed)) return -1; return 1; }
void installCia(const std::u16string& path, FS_MediaType mediaType, std::function<void (const std::u16string& file, u32 percent)> callback) { fs::File ciaFile(path, FS_OPEN_READ), cia; Buffer<u8> buffer(MAX_BUF_SIZE, false); Handle ciaHandle; u32 blockSize; u64 ciaSize, offset = 0; Result res; ciaSize = ciaFile.size(); if((res = AM_StartCiaInstall(mediaType, &ciaHandle))) throw titleException(_FILE_, __LINE__, res, "Failed to start CIA installation!"); cia.setFileHandle(ciaHandle); // Use the handle returned by AM for(u32 i=0; i<=ciaSize / MAX_BUF_SIZE; i++) { blockSize = ((ciaSize - offset<MAX_BUF_SIZE) ? ciaSize - offset : MAX_BUF_SIZE); if(blockSize>0) { try { ciaFile.read(&buffer, blockSize); cia.write(&buffer, blockSize); } catch(fsException& e) { AM_CancelCIAInstall(&ciaHandle); // Abort installation cia.setFileHandle(0); // Reset the handle so it doesn't get closed twice throw; } offset += blockSize; if(callback) callback(path, offset * 100 / ciaSize); } } if((res = AM_FinishCiaInstall(mediaType, &ciaHandle))) throw titleException(_FILE_, __LINE__, res, "installation successfull :)!"); }
AppResult appInstall(MediaType mediaType, FILE* fd, u64 size, std::function<bool(u64 pos, u64 totalSize)> onProgress) { if(!serviceRequire("am")) { return APP_AM_INIT_FAILED; } if(onProgress != NULL) { onProgress(0, size); } Handle ciaHandle; Result startResult = AM_StartCiaInstall(appMediatypeToByte(mediaType), &ciaHandle); if(startResult != 0) { platformSetError(serviceParseError((u32) startResult)); return APP_BEGIN_INSTALL_FAILED; } u32 bufSize = 1024 * 128; // 128KB void* buf = malloc(bufSize); bool cancelled = false; u64 pos = 0; while(platformIsRunning()) { if(onProgress != NULL && !onProgress(pos, size)) { cancelled = true; break; } size_t bytesRead = fread(buf, 1, bufSize, fd); if(bytesRead > 0) { Result writeResult = FSFILE_Write(ciaHandle, NULL, pos, buf, (u32) bytesRead, FS_WRITE_NOFLUSH); if(writeResult != 0) { AM_CancelCIAInstall(&ciaHandle); platformSetError(serviceParseError((u32) writeResult)); return APP_INSTALL_ERROR; } pos += bytesRead; } if((ferror(fd) && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINPROGRESS) || (size != 0 && pos == size)) { break; } } free(buf); if(cancelled) { AM_CancelCIAInstall(&ciaHandle); return APP_OPERATION_CANCELLED; } if(!platformIsRunning()) { AM_CancelCIAInstall(&ciaHandle); return APP_PROCESS_CLOSING; } if(size != 0 && pos != size) { AM_CancelCIAInstall(&ciaHandle); return APP_IO_ERROR; } if(onProgress != NULL) { onProgress(size, size); } Result finishResult = AM_FinishCiaInstall(appMediatypeToByte(mediaType), &ciaHandle); if(finishResult != 0) { platformSetError(serviceParseError((u32) finishResult)); return APP_FINALIZE_INSTALL_FAILED; } return APP_SUCCESS; }
int installTitleFromCIA(const char *path, PrintConsole *con) { Handle CIAIn, CIAOut; u32 bytesread; u32 byteswritten; u64 totalread; int animpos; LOG_INFO("installTitleFromCIA: Installing CIA from %s.", path); CIAIn = openFileHandle(path, FS_OPEN_READ); if(CIAIn == 0) { LOG_ERROR("installTitleFromCIA: Failed to open %s.", path); printf("Failed to open file %s.\n", path); goto error0; } #ifdef ARMED if(R_FAILED(AM_StartCiaInstall(MEDIATYPE_NAND, &CIAOut))) { LOG_ERROR("installTitleFromCIA: AM_StartCiaInstall failed."); printf("Failed to start CIA install.\n"); goto error1; } #endif bytesread = BUFFERSIZE; totalread = 0; while(bytesread == BUFFERSIZE) { printf("%c", anim[animpos]); stepFrame(); con->cursorX--; animpos = (animpos + 1) % 4; if(R_FAILED(FSFILE_Read(CIAIn, &bytesread, totalread, buffer, BUFFERSIZE))) { printf("\nFailed to read %s around %llu!\n", path, totalread); stepFrame(); goto error2; } #ifdef ARMED if(R_FAILED(FSFILE_Write(CIAOut, &byteswritten, totalread, buffer, bytesread, FS_WRITE_FLUSH))) { printf("\nFailed to write %s around %llu!\n", path, totalread); stepFrame(); goto error2; } if(byteswritten < bytesread) { LOG_ERROR("installTitleFromCIA: Incomplete write around %llu.", totalread); printf("\nIncompelete write around %llu!\n", totalread); stepFrame(); goto error2; } #endif totalread += bytesread; } #ifdef ARMED if(R_FAILED(AM_FinishCiaInstall(MEDIATYPE_NAND, &CIAOut))) { LOG_ERROR("installTitleFromCIA: AM_FinishCiaInstall failed."); printf("Failed to finalize CIA install.\n"); goto error2; } #endif closeFileHandle(CIAIn); LOG_INFO("Successfully installed %s.", path); return(0); error2: #ifdef ARMED if(R_FAILED(AM_CancelCIAInstall(&CIAOut))) { printf("Couldn't cancel unsuccessful CIA install.\n"); } #endif error1: closeFileHandle(CIAIn); error0: LOG_ERROR("Failed installing %s.", path); return(-1); }