void patcher_copy::diff () const { QDir(patched()).removeRecursively(); for(QString modified_file : modified_files()){ QFile original_file(original() + "/" + modified_file); QString patch_path = patched() + "/" + modified_file; QFile patch_file(patch_path); if(patch_file.exists()){ patch_file.remove(); } else{ QDir().mkpath(QFileInfo(patch_path).absolutePath()); } original_file.copy(patch_path); } }
void patcher_copy::patch () const { for(QString patched_file : patched_files()){ QString original_path = original() + "/" + patched_file; QFile original_file(original_path); QFile patch_file(patched() + "/" + patched_file); if(original_file.exists()){ original_file.remove(); } else{ QDir().mkpath(QFileInfo(original_path).absolutePath()); } patch_file.copy(original_path); if(utimes(original_path.toLocal8Bit(), NULL)){ qCritical() << "Could not update patch file time."; } } }
int run_main (int argc, ACE_TCHAR *argv[]) { ACE_START_TEST (ACE_TEXT ("Proactor_Scatter_Gather_Test")); if (::parse_args (argc, argv) == -1) return -1; chunk_size = ACE_OS::getpagesize (); if (client_only) ACE_DEBUG ((LM_INFO, ACE_TEXT ("Running as client only, page size %d\n"), chunk_size)); else if (server_only) ACE_DEBUG ((LM_INFO, ACE_TEXT ("Running as server only, page size %d\n"), chunk_size)); else ACE_DEBUG ((LM_INFO, ACE_TEXT ("Running as server and client, page size %d\n"), chunk_size)); Acceptor acceptor; Connector connector; ACE_INET_Addr addr (port); if (!client_only) { // Simplify, initial read with zero size if (-1 == acceptor.open (addr, 0, 1)) { ACE_TEST_ASSERT (0); return -1; } } if (!server_only) { if (-1 == connector.open (1, ACE_Proactor::instance ())) { ACE_TEST_ASSERT (0); return -1; } // connect to first destination if (addr.set (port, host, 1, addr.get_type ()) == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), host), -1); connector.set_address (addr); if (-1 == connector.connect (addr)) { ACE_TEST_ASSERT (0); return -1; } } ACE_Proactor::instance ()->run_event_loop (); // As Proactor event loop now is inactive it is safe to destroy all // senders connector.stop (); acceptor.stop (); ACE_Proactor::instance()->close_singleton (); // now compare the files - available only when on same machine int success = 0; if (!client_only && !server_only) { ACE_DEBUG ((LM_INFO, ACE_TEXT ("Comparing the input file and the output file...\n"))); success = -1; // map the two files, then perform memcmp { ACE_Mem_Map original_file (input_file); ACE_Mem_Map reconstructed_file (output_file); if (original_file.addr () && original_file.addr () != MAP_FAILED && reconstructed_file.addr () && reconstructed_file.addr () != MAP_FAILED) { // compare lengths if ((original_file.size () == reconstructed_file.size ()) && // and if same size, compare file data (0 == ACE_OS::memcmp (original_file.addr (), reconstructed_file.addr (), original_file.size ()))) success = 0; } } if (0 == success) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("input file and the output file identical!\n"))); else ACE_ERROR ((LM_ERROR, ACE_TEXT ("input file and the output file are different!\n"))); } if (!client_only) ACE_OS::unlink (output_file); ACE_END_TEST; return success; }
bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>& sync, const std::string& pkg_filepath) { const std::size_t BUF_SIZE = 8192 * 1024; // 8 MB std::vector<fs::file> filelist; u32 cur_file=0; fs::file original_file(pkg_filepath); original_file.seek(pkg_f.pos()); filelist.push_back(std::move(original_file)); // Save current file offset (probably zero) const u64 start_offset = pkg_f.pos(); u64 cur_offset = start_offset; u64 cur_file_offset = start_offset; // Get basic PKG information PKGHeader header; auto archive_seek = [&](const s64 new_offset, const fs::seek_mode damode = fs::seek_set) { if(damode == fs::seek_set) cur_offset = new_offset; else if (damode == fs::seek_cur) cur_offset += new_offset; u64 _offset = 0; for (u32 i = 0; i < filelist.size(); i++) { if (cur_offset < (_offset + filelist[i].size())) { cur_file = i; cur_file_offset = cur_offset - _offset; filelist[i].seek(cur_file_offset); break; } _offset += filelist[i].size(); } }; auto archive_read = [&](const void *data_ptr, const u64 num_bytes) { u64 num_bytes_left = filelist[cur_file].size() - cur_file_offset; //check if it continues in another file if (num_bytes > num_bytes_left) { filelist[cur_file].read((u8 *)data_ptr, num_bytes_left); if ((cur_file + 1) < filelist.size()) cur_file++; else { cur_offset += num_bytes_left; cur_file_offset = filelist[cur_file].size(); return num_bytes_left; } u64 num_read = filelist[cur_file].read((u8 *)data_ptr + num_bytes_left, num_bytes - num_bytes_left); cur_offset += (num_read + num_bytes_left); cur_file_offset = num_read; return (num_read+num_bytes_left); } u64 num_read = filelist[cur_file].read((u8 *)data_ptr, num_bytes); cur_offset += num_read; cur_file_offset += num_read; return num_read; }; if (archive_read(&header, sizeof(header)) != sizeof(header)) { LOG_ERROR(LOADER, "PKG file is too short!"); return false; } if (header.pkg_magic != "\x7FPKG"_u32) { LOG_ERROR(LOADER, "Not a PKG file!"); return false; } switch (const u16 type = header.pkg_type) { case PKG_RELEASE_TYPE_DEBUG: break; case PKG_RELEASE_TYPE_RELEASE: break; default: { LOG_ERROR(LOADER, "Unknown PKG type (0x%x)", type); return false; } } switch (const u16 platform = header.pkg_platform) { case PKG_PLATFORM_TYPE_PS3: break; case PKG_PLATFORM_TYPE_PSP: break; default: { LOG_ERROR(LOADER, "Unknown PKG platform (0x%x)", platform); return false; } } if (header.pkg_size > pkg_f.size()) { //Check if multi-files pkg if (pkg_filepath.length() < 7 || pkg_filepath.substr(pkg_filepath.length() - 7).compare("_00.pkg") != 0) { LOG_ERROR(LOADER, "PKG file size mismatch (pkg_size=0x%llx)", header.pkg_size); return false; } std::string name_wo_number = pkg_filepath.substr(0, pkg_filepath.length() - 7); u64 cursize = pkg_f.size(); while (cursize != header.pkg_size) { std::string archive_filename = fmt::format("%s_%2d.pkg", name_wo_number, filelist.size()); fs::file archive_file(archive_filename); if (!archive_file) { LOG_ERROR(LOADER, "Missing part of the multi-files pkg: %s", archive_filename); return false; } cursize += archive_file.size(); filelist.push_back(std::move(archive_file)); } } if (header.data_size + header.data_offset > header.pkg_size) { LOG_ERROR(LOADER, "PKG data size mismatch (data_size=0x%llx, data_offset=0x%llx, file_size=0x%llx)", header.data_size, header.data_offset, header.pkg_size); return false; } be_t<u32> drm_type{0}; be_t<u32> content_type{0}; archive_seek(header.pkg_info_off); for (u32 i = 0; i < header.pkg_info_num; i++) { struct packet_T { be_t<u32> id; be_t<u32> size; } packet; archive_read(&packet, sizeof(packet)); // TODO switch (+packet.id) { case 0x1: { if (packet.size == sizeof(drm_type)) { archive_read(&drm_type, sizeof(drm_type)); continue; } break; } case 0x2: { if (packet.size == sizeof(content_type)) { archive_read(&content_type, sizeof(content_type)); continue; } break; } } archive_seek(packet.size, fs::seek_cur); } // Allocate buffer with BUF_SIZE size or more if required const std::unique_ptr<u128[]> buf(new u128[std::max<u64>(BUF_SIZE, sizeof(PKGEntry) * header.file_count) / sizeof(u128)]); // Define decryption subfunction (`psp` arg selects the key for specific block) auto decrypt = [&](u64 offset, u64 size, const uchar* key) -> u64 { archive_seek(start_offset + header.data_offset + offset); // Read the data and set available size const u64 read = archive_read(buf.get(), size); // Get block count const u64 blocks = (read + 15) / 16; if (header.pkg_type == PKG_RELEASE_TYPE_DEBUG) { // Debug key be_t<u64> input[8] = { header.qa_digest[0], header.qa_digest[0], header.qa_digest[1], header.qa_digest[1], }; for (u64 i = 0; i < blocks; i++) { // Initialize stream cipher for current position input[7] = offset / 16 + i; union sha1_hash { u8 data[20]; u128 _v128; } hash; sha1(reinterpret_cast<const u8*>(input), sizeof(input), hash.data); buf[i] ^= hash._v128; } } if (header.pkg_type == PKG_RELEASE_TYPE_RELEASE) { aes_context ctx; // Set encryption key for stream cipher aes_setkey_enc(&ctx, key, 128); // Initialize stream cipher for start position be_t<u128> input = header.klicensee.value() + offset / 16; // Increment stream position for every block for (u64 i = 0; i < blocks; i++, input++) { u128 key; aes_crypt_ecb(&ctx, AES_ENCRYPT, reinterpret_cast<const u8*>(&input), reinterpret_cast<u8*>(&key)); buf[i] ^= key; } } // Return the amount of data written in buf return read; }; std::array<uchar, 16> dec_key; if (header.pkg_platform == PKG_PLATFORM_TYPE_PSP && content_type >= 0x15 && content_type <= 0x17) { const uchar psp2t1[] = {0xE3, 0x1A, 0x70, 0xC9, 0xCE, 0x1D, 0xD7, 0x2B, 0xF3, 0xC0, 0x62, 0x29, 0x63, 0xF2, 0xEC, 0xCB}; const uchar psp2t2[] = {0x42, 0x3A, 0xCA, 0x3A, 0x2B, 0xD5, 0x64, 0x9F, 0x96, 0x86, 0xAB, 0xAD, 0x6F, 0xD8, 0x80, 0x1F}; const uchar psp2t3[] = {0xAF, 0x07, 0xFD, 0x59, 0x65, 0x25, 0x27, 0xBA, 0xF1, 0x33, 0x89, 0x66, 0x8B, 0x17, 0xD9, 0xEA}; aes_context ctx; aes_setkey_enc(&ctx, content_type == 0x15 ? psp2t1 : content_type == 0x16 ? psp2t2 : psp2t3, 128); aes_crypt_ecb(&ctx, AES_ENCRYPT, reinterpret_cast<const uchar*>(&header.klicensee), dec_key.data()); decrypt(0, header.file_count * sizeof(PKGEntry), dec_key.data()); } else { std::memcpy(dec_key.data(), PKG_AES_KEY, dec_key.size()); decrypt(0, header.file_count * sizeof(PKGEntry), header.pkg_platform == PKG_PLATFORM_TYPE_PSP ? PKG_AES_KEY2 : dec_key.data()); } std::vector<PKGEntry> entries(header.file_count); std::memcpy(entries.data(), buf.get(), entries.size() * sizeof(PKGEntry)); for (const auto& entry : entries) { const bool is_psp = (entry.type & PKG_FILE_ENTRY_PSP) != 0; if (entry.name_size > 256) { LOG_ERROR(LOADER, "PKG name size is too big (0x%x)", entry.name_size); continue; } decrypt(entry.name_offset, entry.name_size, is_psp ? PKG_AES_KEY2 : dec_key.data()); const std::string name(reinterpret_cast<char*>(buf.get()), entry.name_size); LOG_NOTICE(LOADER, "Entry 0x%08x: %s", entry.type, name); switch (entry.type & 0xff) { case PKG_FILE_ENTRY_NPDRM: case PKG_FILE_ENTRY_NPDRMEDAT: case PKG_FILE_ENTRY_SDAT: case PKG_FILE_ENTRY_REGULAR: case PKG_FILE_ENTRY_UNK1: case 0xe: case 0x10: case 0x11: case 0x13: case 0x15: case 0x16: { const std::string path = dir + name; const bool did_overwrite = fs::is_file(path); if (did_overwrite && (entry.type&PKG_FILE_ENTRY_OVERWRITE) == 0) { LOG_NOTICE(LOADER, "Didn't overwrite %s", name); break; } if (fs::file out{ path, fs::rewrite }) { for (u64 pos = 0; pos < entry.file_size; pos += BUF_SIZE) { const u64 block_size = std::min<u64>(BUF_SIZE, entry.file_size - pos); if (decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : dec_key.data()) != block_size) { LOG_ERROR(LOADER, "Failed to extract file %s", path); break; } if (out.write(buf.get(), block_size) != block_size) { LOG_ERROR(LOADER, "Failed to write file %s", path); break; } if (sync.fetch_add((block_size + 0.0) / header.data_size) < 0.) { LOG_ERROR(LOADER, "Package installation cancelled: %s", dir); return false; } } if (did_overwrite) { LOG_WARNING(LOADER, "Overwritten file %s", name); } else { LOG_NOTICE(LOADER, "Created file %s", name); } } else { LOG_ERROR(LOADER, "Failed to create file %s", path); } break; } case PKG_FILE_ENTRY_FOLDER: case 0x12: { const std::string path = dir + name; if (fs::create_dir(path)) { LOG_NOTICE(LOADER, "Created directory %s", name); } else if (fs::is_dir(path)) { LOG_WARNING(LOADER, "Reused existing directory %s", name); } else { LOG_ERROR(LOADER, "Failed to create directory %s", path); } break; } default: { LOG_ERROR(LOADER, "Unknown PKG entry type (0x%x) %s", entry.type, name); } } } LOG_SUCCESS(LOADER, "Package successfully installed to %s", dir); return true; }
//----------------------------------------------------------------- void MP3Worker::run_implementation() { auto file_name = m_source_info.absoluteFilePath().replace('/', QDir::separator()); // QTemporaryFile and QThreads are not playing fine together, the temp names are being reused // and taglib fails upon reading the file. This approach seems to work. auto id = QUuid::createUuid(); QTemporaryFile temp_file(id.toString()); if(!temp_file.open()) { emit error_message(QString("Couldn't open temporary file for file '%1'.").arg(file_name)); return; } QFile original_file(file_name); if(!original_file.open(QFile::ReadOnly)) { emit error_message(QString("Couldn't open file '%1'.").arg(file_name)); return; } // taglib wouldn't open files with unicode names. temp_file.write(original_file.readAll()); temp_file.waitForBytesWritten(-1); temp_file.flush(); temp_file.close(); auto temp_name = temp_file.fileName() + MP3_EXTENSION; temp_file.rename(temp_name); // taglib won't open a file if it doesn't have the correct extension. ¿¿?? original_file.close(); QString track_title; { // ensure TagLib File object is destroyed at the end of scope. TagLib::MPEG::File file_metadata(temp_name.toStdString().c_str()); if(file_metadata.hasID3v1Tag() || file_metadata.hasID3v2Tag()) { if(m_configuration.useMetadataToRenameOutput()) { if(!file_metadata.hasID3v2Tag()) { track_title = parse_metadata(file_metadata.tag()); } else { track_title = parse_metadata_id3v2(file_metadata.ID3v2Tag()); } } emit progress(25); if(m_configuration.extractMetadataCoverPicture() && file_metadata.hasID3v2Tag()) { extract_cover(file_metadata.ID3v2Tag()); } emit progress(50); if(m_configuration.stripTagsFromMp3()) { file_metadata.strip(); file_metadata.save(); } } } emit progress(75); if(track_title.isEmpty()) { track_title = m_source_info.absoluteFilePath().split('/').last().remove(MP3_EXTENSION); } track_title = Utils::formatString(track_title, m_configuration.formatConfiguration()); auto source_name = m_source_info.absoluteFilePath().split('/').last(); emit information_message(QString("Renaming '%1' from '%2'.").arg(track_title).arg(source_name)); auto final_name = m_source_path + track_title; original_file.rename(original_file.fileName() + TEMP_EXTENSION); if(!QFile::copy(temp_file.fileName(), final_name)) { emit error_message(QString("Couldn't copy file '%1' to '%2'.").arg(m_source_info.absoluteFilePath()).arg(final_name)); original_file.rename(original_file.fileName().remove(TEMP_EXTENSION)); } else { original_file.remove(); } }