git mirror - github.com/owenewans/holy - branch master
clone: https://src.holypkg.eu/holy/

file src/early-init.c

#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>

static void fail(const char *what)
{
    perror(what);
    for (;;) pause();
}

static void wait_device(const char *device)
{
    const struct timespec delay = {0, 100000000};
    struct stat st;
    unsigned int attempt;
    if (strncmp(device, "/dev/", 5) || !device[5]) {
        errno = EINVAL;
        fail("holy-init: root requires a /dev block device");
    }
    for (attempt = 0; attempt < 300; ++attempt) {
        if (!stat(device, &st)) break;
        if (errno != ENOENT) fail("holy-init: root device");
        nanosleep(&delay, NULL);
    }
    if (attempt == 300) { errno = ETIMEDOUT; fail("holy-init: root device"); }
    if (!S_ISBLK(st.st_mode)) { errno = ENOTBLK; fail("holy-init: root device"); }
}

static void mount_disk(const char *device, const char *esp)
{
    static const char *const mounts[] = { "/dev", "/proc", "/sys", "/run", "/tmp" };
    struct stat st;
    size_t i;
    wait_device(device);
    if (mkdir("/newroot", 0755) || mount(device, "/newroot", "ext4", 0, NULL))
        fail("holy-init: mount ext4 root");
    if (access("/newroot/sbin/init", X_OK)) fail("holy-init: missing disk init");
    if (esp) {
        wait_device(esp);
        if (lstat("/newroot/boot", &st)) fail("holy-init: boot directory");
        if (!S_ISDIR(st.st_mode)) { errno = ENOTDIR; fail("holy-init: boot directory"); }
        if (mount(esp, "/newroot/boot", "vfat", MS_NOSUID | MS_NODEV | MS_NOEXEC,
                  "uid=0,gid=0,fmask=0133,dmask=0022"))
            fail("holy-init: mount FAT ESP");
    }
    for (i = 0; i < sizeof mounts / sizeof *mounts; ++i) {
        char destination[32];
        int size = snprintf(destination, sizeof destination, "/newroot%s", mounts[i]);
        if (size < 0 || (size_t)size >= sizeof destination ||
            mount(mounts[i], destination, NULL, MS_MOVE, NULL))
            fail("holy-init: move runtime mount");
    }
}

int main(void)
{
    FILE *input;
    char *line = NULL, *word, *device = NULL, *esp = NULL;
    size_t capacity = 0;
    int console, fd;
    char *service = "boot";
    char *args[] = { "/sbin/init", "--services-dir", "/etc/dinit.d",
                     "--socket-path", "/run/dinitctl", "--service", NULL, NULL };
    char *disk_args[] = { "/usr/bin/busybox", "switch_root", "/newroot",
                         "/sbin/init", "--services-dir", "/etc/dinit.d",
                         "--socket-path", "/run/dinitctl", "--service", NULL, NULL };
    if (getpid() != 1) {
        fputs("holy-init: requires PID 1\n", stderr);
        return 2;
    }
    if (mount("devtmpfs", "/dev", "devtmpfs", MS_NOSUID, "mode=0755"))
        fail("holy-init: devtmpfs");
    console = open("/dev/console", O_RDWR);
    if (console < 0) fail("holy-init: console");
    for (fd = 0; fd < 3; ++fd)
        if (dup2(console, fd) < 0) fail("holy-init: console descriptor");
    if (console > 2) close(console);
    if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL))
        fail("holy-init: private mounts");
    if (mount("proc", "/proc", "proc", MS_NOSUID | MS_NODEV | MS_NOEXEC, NULL) ||
        mount("sysfs", "/sys", "sysfs", MS_NOSUID | MS_NODEV | MS_NOEXEC, NULL) ||
        mount("tmpfs", "/run", "tmpfs", MS_NOSUID | MS_NODEV, "mode=0755") ||
        mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV, "mode=1777"))
        fail("holy-init: runtime mounts");
    if (mkdir("/dev/pts", 0755) ||
        mount("devpts", "/dev/pts", "devpts", MS_NOSUID | MS_NOEXEC,
              "newinstance,ptmxmode=0666,mode=0620"))
        fail("holy-init: devpts");
    if (setenv("PATH", "/usr/bin", 1) || setenv("HOME", "/root", 1))
        fail("holy-init: environment");
    input = fopen("/proc/cmdline", "r");
    if (!input || getline(&line, &capacity, input) < 0)
        fail("holy-init: kernel command line");
    fclose(input);
    for (word = strtok(line, " \t\r\n"); word; word = strtok(NULL, " \t\r\n")) {
        if (!strcmp(word, "holy.test=1")) service = "holy-test";
        if (!strcmp(word, "holy.install-test=1")) service = "holy-install-test";
        if (!strncmp(word, "holy.root=", 10)) {
            if (device || !word[10]) { errno = EINVAL; fail("holy-init: duplicate or empty root"); }
            device = strdup(word + 10);
            if (!device) fail("holy-init: root allocation");
        }
        if (!strncmp(word, "holy.esp=", 9)) {
            if (esp || !word[9]) { errno = EINVAL; fail("holy-init: duplicate or empty ESP"); }
            esp = strdup(word + 9);
            if (!esp) fail("holy-init: ESP allocation");
        }
        if (!strncmp(word, "holy.rootfstype=", 16) && strcmp(word + 16, "ext4")) {
            errno = ENOTSUP;
            fail("holy-init: only ext4 disk roots supported");
        }
    }
    free(line);
    if (esp && !device) { errno = EINVAL; fail("holy-init: ESP requires disk root"); }
    if (device) {
        mount_disk(device, esp);
        free(device);
        free(esp);
        disk_args[9] = service;
        execv(disk_args[0], disk_args);
        fail("holy-init: switch_root");
    }
    args[6] = service;
    execv(args[0], args);
    fail("holy-init: exec dinit");
    return 1;
}