Files
bsb2/user/imgbuilder.cc
Niklas Gollenstede 4245798955 fixes for A2
mostly include some things that should and remove some things that shouldn't have been included in the handout (yes this does hint at some places that need to be touched for A2)
2025-11-24 15:04:26 +01:00

70 lines
1.6 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 size_t 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, size_t 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
std::array<uint32_t, block_size / sizeof(uint32_t)> size{0};
size[0] = static_cast<uint32_t>(argc - 1);
for (size_t i = 1; i < argc; ++i) {
struct stat sb;
if (stat(argv[i], &sb) != 0) die("stat");
// 4 GB Limit
if (sb.st_size >= UINT32_MAX) {
errno = EFBIG;
die("stat");
}
size[i] = sb.st_size;
}
writeBuffer(size.data(), block_size);
// DATA: Each App
for (size_t i = 1; i < argc; ++i) {
std::vector<char> buf(size[i]);
std::ifstream input(argv[i], std::ios::binary);
if (!input) die("fopen");
input.read(buf.data(), size[i]);
writeBuffer(buf.data(), size[i]);
// Fill to block size, if required
if (size[i] % block_size != 0)
writeBuffer(zeros, block_size - (size[i] % block_size));
}
std::cout.flush();
return EXIT_SUCCESS;
}