68 lines
1.7 KiB
C++
68 lines
1.7 KiB
C++
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <cstdint>
|
|
#include <format>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <print>
|
|
#include <vector>
|
|
|
|
constexpr std::streamsize block_size = 4096;
|
|
const uint8_t zeros[block_size] = {};
|
|
|
|
template <class... Args>
|
|
static void die(std::format_string<Args...> fmt, Args &&...args) {
|
|
auto msg = std::format(fmt, std::forward<Args>(args)...);
|
|
perror(msg.c_str());
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
static void writeBuffer(const void *data, std::streamsize size) {
|
|
std::cout.write(reinterpret_cast<const char *>(data), size);
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
if (argc < 2) {
|
|
std::println(stderr, "usage: {} <list of flat binaries>\n", argv[0]);
|
|
return EXIT_FAILURE;
|
|
} else if (argc > 1000) {
|
|
std::println(stderr, "Only a maximum of 1000 apps are supported\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
// HEADER: Number of apps + size of each app in bytes
|
|
std::array<uint32_t, block_size / sizeof(uint32_t)> sizes{0};
|
|
sizes[0] = static_cast<uint32_t>(argc - 1);
|
|
for (size_t i = 1; i < argc; ++i) {
|
|
struct stat file;
|
|
if (stat(argv[i], &file) != 0) die("stat");
|
|
if (file.st_size >= UINT32_MAX) { // 4 GB Limit
|
|
errno = EFBIG;
|
|
die("stat");
|
|
}
|
|
sizes[i] = file.st_size;
|
|
}
|
|
writeBuffer(sizes.data(), block_size);
|
|
|
|
// DATA: Each App
|
|
for (size_t i = 1; i < argc; ++i) {
|
|
std::vector<char> buf(sizes[i]);
|
|
std::ifstream input(argv[i], std::ios::binary);
|
|
if (!input) die("fopen");
|
|
|
|
input.read(buf.data(), sizes[i]);
|
|
|
|
writeBuffer(buf.data(), sizes[i]);
|
|
|
|
// Fill to block size, if required
|
|
if (sizes[i] % block_size != 0)
|
|
writeBuffer(zeros, block_size - (sizes[i] % block_size));
|
|
}
|
|
|
|
std::cout.flush();
|
|
return EXIT_SUCCESS;
|
|
}
|