apio
16b0531d42
All checks were successful
continuous-integration/drone/push Build is passing
init is now split into two parts: preinit, which lives in the initrd and prepares the root file system for init, and the actual /usr/bin/init, which lives in the root partition and starts services and reaps zombies. The kernel now looks for /bin/preinit instead of /bin/init as the executable for the init process. All configuration files in initrd/etc have been moved to base/etc. (The plan is to have only moon and preinit in the initrd.) Since the current Ext2 implementation is read-only (and it's on a CDROM so it would be read-only anyways), /home/selene is a tmpfs (as well as /tmp), to allow for a writable home directory. The system is slower now, but that's to expect since the Ext2 code doesn't use caching and the ATA code still uses PIO.
87 lines
2.0 KiB
C++
87 lines
2.0 KiB
C++
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/syscall.h>
|
|
#include <unistd.h>
|
|
|
|
// FIXME: Make this configurable.
|
|
#define LUNA_ROOT_PARTITION "/dev/cd0p2"
|
|
|
|
static void mount_devfs()
|
|
{
|
|
if (mkdir("/dev", 0755) < 0 && errno != EEXIST && errno != EROFS) exit(255);
|
|
|
|
if (mount("/dev", "devfs", "devfs") < 0) exit(255);
|
|
}
|
|
|
|
static void open_std_streams()
|
|
{
|
|
stdin = fopen("/dev/console", "r");
|
|
stdout = fopen("/dev/console", "w");
|
|
stderr = fopen("/dev/console", "w");
|
|
}
|
|
|
|
static void fail(const char* message)
|
|
{
|
|
open_std_streams();
|
|
fprintf(stderr, "preinit: fatal error: %s\n", message);
|
|
exit(255);
|
|
}
|
|
|
|
static void fail_errno(const char* message)
|
|
{
|
|
int err = errno;
|
|
open_std_streams();
|
|
fprintf(stderr, "preinit: fatal error: %s (%s)\n", message, strerror(err));
|
|
exit(255);
|
|
}
|
|
|
|
static void mount_rootfs()
|
|
{
|
|
if (mkdir("/osroot", 0755) < 0 && errno != EEXIST) exit(255);
|
|
|
|
if (mount("/osroot", "ext2", LUNA_ROOT_PARTITION) < 0) fail_errno("Cannot mount the root partition");
|
|
}
|
|
|
|
int main()
|
|
{
|
|
if (getpid() != 1)
|
|
{
|
|
fprintf(stderr, "error: preinit must be run as the init process.\n");
|
|
return 1;
|
|
}
|
|
|
|
mount_devfs();
|
|
mount_rootfs();
|
|
|
|
struct stat st;
|
|
if (stat("/osroot/mnt", &st) < 0 || !S_ISDIR(st.st_mode)) fail("No suitable temporary mountpoint for pivot_root");
|
|
|
|
// Now that we have mounted the root file system, remove the /dev mount on the current ramfs root.
|
|
umount("/dev");
|
|
|
|
long rc = syscall(SYS_pivot_root, "/osroot", "/osroot/mnt");
|
|
if (rc < 0) exit(255);
|
|
|
|
chdir("/");
|
|
umount("/mnt");
|
|
|
|
// Now, mount the /dev file system on the new root.
|
|
mount_devfs();
|
|
|
|
/*setenv("PATH", "/bin:/usr/bin", 1);
|
|
char* argv[] = { "init", nullptr };
|
|
char* envp[] = { nullptr };
|
|
execvpe(argv[0], argv, envp);*/
|
|
|
|
char* argv[] = { "/usr/bin/init", nullptr };
|
|
execv(argv[0], argv);
|
|
|
|
fail_errno("Failed to execute init");
|
|
|
|
return 255;
|
|
}
|