1
0
mirror of synced 2026-01-13 15:17:07 +00:00
2020-09-09 15:11:45 -07:00

174 lines
6.1 KiB
C++

#define _CRT_SECURE_NO_WARNINGS
// cray_ios_disasm.cpp : Defines the entry point for the console application.
//
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "utils.h"
#include <boost/filesystem.hpp>
/*
UNICOS .gzc format:
- It's gzip compressed
Each file has the following header:
00000000000071C7 <-- seems constant
0000000000002243 <-- seems constant within file, but different between files (2243 for non-unicos media, 2279 for unicos root and usr)
0000000000000465 <-- variable
00000000000081A0 <-- mode and type
0000000000000002 <-- seems constant
0000000000000002 <-- seems constant
0000000000000001 <-- seems constant
0000000000000000 <-- seems constant
0000000000000000 <-- seems constant
0000000000000000 <-- seems constant
0000000000000000 <-- seems constant
0000000000000000 <-- seems constant
0000000000000000 <-- seems constant
0000000000000000 <-- seems constant
0000000000000000 <-- seems constant
0000000000000000 <-- seems constant
0000000033C5DF41 <-- creation (?) time
000000000000000A <-- length of file name (file name is 0-terminated and follows immediately after the header)
0000000000000C8B <-- file payload length (payload starts immediately after file name)
[0x00000000] 0x00000000000071c7 unsigned __int64
[0x00000001] 0x0000000000002243 unsigned __int64
[0x00000002] 0x0000000000007ec0 unsigned __int64
[0x00000003] 0x00000000000045e8 unsigned __int64
[0x00000004] 0x0000000000000002 unsigned __int64
[0x00000005] 0x0000000000000002 unsigned __int64
[0x00000006] 0x00000000000000d3 unsigned __int64
[0x00000007] 0x0000000000000000 unsigned __int64
[0x00000008] 0x0000000000000000 unsigned __int64
[0x00000009] 0x0000000000000000 unsigned __int64
[0x0000000a] 0x0000000000000000 unsigned __int64
[0x0000000b] 0x0000000000000000 unsigned __int64
[0x0000000c] 0x0000000000000000 unsigned __int64
[0x0000000d] 0x0000000000000000 unsigned __int64
[0x0000000e] 0x0000000000000000 unsigned __int64
[0x0000000f] 0x0000000000000000 unsigned __int64
[0x00000010] 0x00000000355e00c0 unsigned __int64
This is a binary cpio header!!!
Field Width Field Name Meaning
========================================================
6 magic magic number "070707"
6 dev device where file resides
6 ino I-number of file
6 mode file mode
6 uid owner user ID
6 gid owner group ID
6 nlink number of links to file
6 rdev device major/minor for special file
11 mtime modify time of file
6 namesize length of file name
11 filesize length of file to follow
So, chances are, the unicos CPIO can open this file
It is. And what this tool should be doing is to convert these binary cpio files into text cpio ones. Doing that on stdio would allow for pipeing through gzip and re-create the archives in a
compatible, but easy-to-use format. To turn stdio into binary (on windows), do this:
#include <fstream>
#include <iostream>
#ifdef _WIN32
#include <io.h>
#include <fcntl.h>
#endif
int main() {
#ifdef _WIN32
setmode(fileno(stdout),O_BINARY);
setmode(fileno(stdin),O_BINARY);
#endif
std::cout << "hi" << std::endl;
}
*/
struct FileHeader_s {
uint64_t Words[17];
uint64_t FileNameLen;
uint64_t FileLen;
};
int PrintUsage(const char *aExecName, const char *ErrorStr) {
if (ErrorStr != nullptr) std::cout << "Error: " << ErrorStr << std::endl;
std::cout << "Usage: " << aExecName << " <Uncompressed gzc file name>" << std::endl;
return 1;
}
int main(int argc, const char **argv) {
CommandLine_c CommandLine(argc, argv);
try {
std::string InFileName;
while (CommandLine.HasMoreParams()) {
std::string CurParam = CommandLine.GetNextParam();
if (InFileName.empty()) {
InFileName = CurParam;
} else {
throw Generic_x("Invalid command line");
}
}
if (InFileName.empty()) throw Generic_x("File name was not specified");
std::cout << "Extracting file..." << std::endl;
std::ifstream InFile(InFileName, std::ios::in | std::ios::binary);
while (!InFile.eof()) {
FileHeader_s FileHeader;
InFile.read((char*)(&FileHeader), sizeof(FileHeader_s));
if (!InFile.good()) throw Generic_x() << "Can't read from file";
if (InFile.gcount() != sizeof(FileHeader_s)) throw Generic_x() << "Can't read file header at offset: " << HexPrinter(InFile.tellg());
for (size_t i = 0; i < sizeof(FileHeader_s::Words) / sizeof(FileHeader_s::Words[0]); ++i) {
FileHeader.Words[i] = SwapBytes(FileHeader.Words[i]);
}
FileHeader.FileNameLen = SwapBytes(FileHeader.FileNameLen);
FileHeader.FileLen = SwapBytes(FileHeader.FileLen);
std::string FileName;
FileName.resize(FileHeader.FileNameLen);
InFile.read((char*)(&FileName[0]), FileHeader.FileNameLen);
if (!InFile.good()) throw Generic_x() << "Can't read from file";
if (uint64_t(InFile.gcount()) != FileHeader.FileNameLen) throw Generic_x() << "Can't read file name at offset: " << HexPrinter(InFile.tellg());
std::cout << FileName;
if (FileHeader.FileLen > 0) {
std::cout << " size: " << DecPrinter(FileHeader.FileLen);
boost::filesystem::path Path(FileName);
boost::filesystem::path ParentPath = Path.parent_path();
if (!ParentPath.empty()) boost::filesystem::create_directories(ParentPath);
std::ofstream OutFile(FileName, std::ios::out | std::ios::binary);
bool SkipWrite = false;
if (!OutFile.good()) {
std::cerr << "Can't create file: " << FileName << std::endl;
SkipWrite = true;
}
char C;
for (uint64_t i = 0; i < FileHeader.FileLen; ++i) {
InFile.read(&C, 1);
if (!InFile.good()) throw Generic_x() << "Can't read from file";
if (InFile.gcount() != 1) throw Generic_x() << "Can't read file data at offset: " << HexPrinter(InFile.tellg());
if (!SkipWrite) {
OutFile.write(&C, 1);
if (!OutFile.good()) throw Generic_x() << "Can't create file: " << FileName;
}
}
OutFile.close();
} else {
if (FileName == "TRAILER!!!") {
break;
}
}
std::cout << std::endl;
}
}
catch (std::exception &Ex) {
return PrintUsage(argv[0], Ex.what());
}
return 0;
}