Files
bsb2/user/imgbuilder.cc
2026-01-05 10:41:27 +01:00

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;
}