#include #include #include #include #include namespace fs = std::filesystem; using namespace XCEngine::Resources; namespace { void PrintUsage() { std::cout << "Usage:\n" << " artifact_inspect \n" << " artifact_inspect --extract \n"; } bool WritePayloadToFile(const fs::path& outputPath, const XCEngine::Containers::Array& payload) { std::error_code ec; const fs::path parent = outputPath.parent_path(); if (!parent.empty()) { fs::create_directories(parent, ec); if (ec) { std::cerr << "Failed to create output directory: " << parent.string() << "\n"; return false; } } std::ofstream output(outputPath, std::ios::binary | std::ios::trunc); if (!output.is_open()) { std::cerr << "Failed to open output file: " << outputPath.string() << "\n"; return false; } if (!payload.Empty()) { output.write(reinterpret_cast(payload.Data()), static_cast(payload.Size())); } if (!output) { std::cerr << "Failed to write output file: " << outputPath.string() << "\n"; return false; } return true; } void PrintEntry(const ArtifactContainerEntryView& entry) { std::cout << "- name: " << entry.name.CStr() << ", type: " << GetResourceTypeName(entry.resourceType) << ", localID: " << entry.localID << ", size: " << entry.payloadSize << "\n"; } } // namespace int main(int argc, char** argv) { if (argc != 2 && argc != 5) { PrintUsage(); return 1; } const XCEngine::Containers::String artifactPath(argv[1] == nullptr ? "" : argv[1]); ArtifactContainerReader reader; XCEngine::Containers::String errorMessage; if (!reader.Open(artifactPath, &errorMessage)) { std::cerr << "Failed to open artifact container: " << (errorMessage.Empty() ? artifactPath.CStr() : errorMessage.CStr()) << "\n"; return 2; } std::cout << "Artifact: " << reader.GetPath().CStr() << "\n"; std::cout << "Entries: " << reader.GetEntryCount() << "\n"; for (const ArtifactContainerEntryView& entry : reader.GetEntries()) { PrintEntry(entry); } if (argc == 5) { const std::string mode = argv[2] == nullptr ? std::string() : std::string(argv[2]); if (mode != "--extract") { PrintUsage(); return 1; } const XCEngine::Containers::String entryName(argv[3] == nullptr ? "" : argv[3]); XCEngine::Containers::Array payload; if (!reader.ReadEntryPayload(entryName, payload, &errorMessage)) { std::cerr << "Failed to read entry payload: " << (errorMessage.Empty() ? entryName.CStr() : errorMessage.CStr()) << "\n"; return 3; } const fs::path outputPath(argv[4] == nullptr ? "" : argv[4]); if (!WritePayloadToFile(outputPath, payload)) { return 4; } std::cout << "Extracted entry '" << entryName.CStr() << "' to " << outputPath.string() << "\n"; } return 0; }