deployd/script/main.c
2025-08-02 02:03:28 +03:00

149 lines
3.9 KiB
C

#include "include/conf.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "include/dirs.h"
#include "include/stages.h"
#include "include/deploy.h"
#include "include/metadata.h"
#include "include/main.h"
static char *sh_load_script(const char *script);
static bool sh_read_meta(const char *buffer,
sh_Metadata *meta,
sh_PtrRange *sysadm,
uint8_t *stages);
int main(int argc, const char *argv[]) {
if (getuid() != 0 || getgid() != 0) {
sh_print_error("Give me root!");
return 1;
}
if (argc < 2) {
sh_print_errorf("Usage: %s <script> [--force-unlock] [subcommand]",
argv[0]);
return 1;
}
puts("Ensuring directorites...");
if (!sh_dirs_ensure()) {
return 1;
}
const char *script = argv[1];
const bool force_unlock =
(argc > 2 && strcmp(argv[2], "--force-unlock") == 0);
const char *subcommand = NULL;
if (force_unlock) {
if (argc > 3) {
subcommand = argv[3];
}
} else {
if (argc > 2) {
subcommand = argv[2];
}
}
/* Load script */
puts("Loading deployer script into memory...");
char *buffer = sh_load_script(script);
if (!buffer) {
return 1;
}
/* Read metadata */
puts("Ready metadata...");
sh_Metadata meta = {0};
sh_PtrRange sysadm = {0};
uint8_t stages = 0;
if (!sh_read_meta(buffer, &meta, &sysadm, &stages)) {
SH_FREE(buffer);
return 1;
}
/* Run deploy */
printf("Running deployer %s...\n", meta.name);
const int ret =
sh_run_deploy(force_unlock, subcommand, buffer, &meta, &sysadm, stages);
/* Cleanup */
puts("Cleaning up resources...");
SH_FREE(buffer);
printf("Deploy finished with exit code %d\n", ret);
return ret;
}
static char *sh_load_script(const char *script) {
FILE *file = fopen(script, "r");
if (!file) {
sh_print_perrorf("Failed to open '%s'", script);
return NULL;
}
if (fseek(file, 0, SEEK_END) != 0) {
sh_print_perrorf("Failed to seek to end of '%s'", script);
(void)fclose(file);
return NULL;
}
const long filesize = ftell(file);
if (filesize < 0) {
sh_print_perrorf("Failed to get file size for '%s'", script);
(void)fclose(file);
return NULL;
}
if (fseek(file, 0, SEEK_SET) != 0) {
sh_print_perrorf("Failed to seek to beginning of '%s'", script);
(void)fclose(file);
return NULL;
}
char *buffer = SH_MALLOC((size_t)(filesize + 1));
if (!buffer) {
sh_print_perrorf("Failed to allocate memory for file '%s'", script);
(void)fclose(file);
return NULL;
}
const size_t readsize = fread(buffer, 1, (size_t)filesize, file);
if (readsize != (size_t)filesize) {
if (ferror(file)) {
sh_print_perrorf("Error reading from file '%s'", script);
} else if (feof(file)) {
sh_print_perrorf("Unexpected end of file '%s'", script);
} else {
sh_print_perrorf("Failed to read entire file '%s'", script);
}
SH_FREE(buffer);
(void)fclose(file);
return NULL;
}
buffer[filesize] = '\0';
(void)fclose(file);
return buffer;
}
static bool sh_read_meta(const char *buffer,
sh_Metadata *meta,
sh_PtrRange *sysadm,
uint8_t *stages) {
if (!sh_Metadata_read(meta, buffer)) {
sh_print_error("Failed to read metadata");
return false;
}
if (!sh_Metadata_is_full_script(meta)) {
sh_print_error("Script has missing metadata");
return false;
}
*stages = sh_find_stages(buffer, sysadm);
if ((*stages & SH_STAGE_ERROR) != 0) {
return false;
}
return true;
}