mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Default to installing GRUB if an existing installation uses GRUB.
This commit is contained in:
parent
44c0a1f979
commit
019a8c239a
8 changed files with 163 additions and 42 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -69,6 +69,7 @@ static enum filesystem_error biosboot_inspect(struct filesystem** fs_ptr,
|
|||
fs->handler = &biosboot_handler;
|
||||
fs->handler_private = NULL;
|
||||
fs->fstype_name = "biosboot";
|
||||
fs->flags = FILESYSTEM_FLAG_NOT_FILESYSTEM;
|
||||
return *fs_ptr = fs, FILESYSTEM_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -67,6 +67,7 @@ static enum filesystem_error extended_inspect(struct filesystem** fs_ptr,
|
|||
fs->handler = &extended_handler;
|
||||
fs->handler_private = NULL;
|
||||
fs->fstype_name = "extended";
|
||||
fs->flags = FILESYSTEM_FLAG_NOT_FILESYSTEM;
|
||||
return *fs_ptr = fs, FILESYSTEM_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Jonas 'Sortie' Termansen.
|
||||
* Copyright (c) 2015, 2016 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
@ -35,6 +35,7 @@ struct filesystem_handler;
|
|||
#define FILESYSTEM_FLAG_UUID (1 << 0)
|
||||
#define FILESYSTEM_FLAG_FSCK_SHOULD (1 << 1)
|
||||
#define FILESYSTEM_FLAG_FSCK_MUST (1 << 2)
|
||||
#define FILESYSTEM_FLAG_NOT_FILESYSTEM (1 << 3)
|
||||
|
||||
struct filesystem
|
||||
{
|
||||
|
|
|
@ -148,7 +148,8 @@ bootloader to boot the operating system. You will be offered the choice of
|
|||
installing GRUB as the bootloader. Note however that this GRUB is not able to
|
||||
detect other operating systems and you will have to configure it manually if you
|
||||
wish to use it in a dual boot scheme. The answer will default to yes if no
|
||||
existing partitions are found, and will default to no if some are found.
|
||||
existing partitions are found, or if an existing Sortix installation is found
|
||||
that uses the provided bootloader; and will otherwise default to no.
|
||||
.Pp
|
||||
Single-boot configurations should use the offered bootloader. Dual-boot
|
||||
configurations should refuse it and arrange for bootloading by other means. The
|
||||
|
|
|
@ -27,7 +27,7 @@ release.o \
|
|||
|
||||
OBJS=$(MAIN_OBJS) $(UTIL_OBJS)
|
||||
|
||||
SYSINSTALL_DEPS=devices execute fileops interactive manifest
|
||||
SYSINSTALL_DEPS=conf devices execute fileops interactive manifest release
|
||||
SYSMERGE_DEPS=conf fileops execute hooks manifest release
|
||||
SYSUPGRADE_DEPS=conf devices execute fileops hooks interactive manifest release
|
||||
|
||||
|
|
|
@ -173,19 +173,6 @@ struct filesystem* search_for_filesystem_by_spec(const char* spec)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool check_existing_systems(void)
|
||||
{
|
||||
for ( size_t di = 0; di < hds_count; di++ )
|
||||
{
|
||||
struct blockdevice* dbdev = &hds[di]->bdev;
|
||||
if ( dbdev->fs )
|
||||
return true;
|
||||
else if ( dbdev->pt )
|
||||
return 1 <= dbdev->pt->partitions_count;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool check_lacking_partition_table(void)
|
||||
{
|
||||
for ( size_t di = 0; di < hds_count; di++ )
|
||||
|
@ -324,7 +311,7 @@ bool load_mountpoints(const char* fstab_path,
|
|||
return true;
|
||||
}
|
||||
|
||||
void mountpoint_mount(struct mountpoint* mountpoint)
|
||||
bool mountpoint_mount(struct mountpoint* mountpoint)
|
||||
{
|
||||
struct filesystem* fs = mountpoint->fs;
|
||||
// TODO: It would be ideal to get an exclusive lock so that no other
|
||||
|
@ -333,17 +320,29 @@ void mountpoint_mount(struct mountpoint* mountpoint)
|
|||
const char* bdev_path = bdev->p ? bdev->p->path : bdev->hd->path;
|
||||
assert(bdev_path);
|
||||
if ( fs->flags & FILESYSTEM_FLAG_FSCK_MUST && !fsck(fs) )
|
||||
errx(2, "Failed to fsck %s", bdev_path);
|
||||
{
|
||||
warnx("Failed to fsck %s", bdev_path);
|
||||
return false;
|
||||
}
|
||||
if ( !fs->driver )
|
||||
errx(2, "%s: Don't know how to mount a %s filesystem",
|
||||
bdev_path, fs->fstype_name);
|
||||
{
|
||||
warnx("%s: Don't know how to mount a %s filesystem",
|
||||
bdev_path, fs->fstype_name);
|
||||
return false;
|
||||
}
|
||||
const char* pretend_where = mountpoint->entry.fs_file;
|
||||
const char* where = mountpoint->absolute;
|
||||
struct stat st;
|
||||
if ( stat(where, &st) < 0 )
|
||||
err(2, "stat: %s", where);
|
||||
{
|
||||
warn("stat: %s", where);
|
||||
return false;
|
||||
}
|
||||
if ( (mountpoint->pid = fork()) < 0 )
|
||||
err(2, "%s: Unable to mount: fork", bdev_path);
|
||||
{
|
||||
warn("%s: Unable to mount: fork", bdev_path);
|
||||
return false;
|
||||
}
|
||||
// TODO: This design is broken. The filesystem should tell us when it is
|
||||
// ready instead of having to poll like this.
|
||||
if ( mountpoint->pid == 0 )
|
||||
|
@ -366,36 +365,41 @@ void mountpoint_mount(struct mountpoint* mountpoint)
|
|||
int code;
|
||||
waitpid(mountpoint->pid, &code, 0);
|
||||
mountpoint->pid = -1;
|
||||
exit(2);
|
||||
return false;
|
||||
}
|
||||
if ( newst.st_dev != st.st_dev || newst.st_ino != st.st_ino )
|
||||
break;
|
||||
int code;
|
||||
pid_t child = waitpid(mountpoint->pid, &code, WNOHANG);
|
||||
if ( child < 0 )
|
||||
err(2, "waitpid");
|
||||
{
|
||||
warn("waitpid");
|
||||
return false;
|
||||
}
|
||||
if ( child != 0 )
|
||||
{
|
||||
mountpoint->pid = -1;
|
||||
if ( WIFSIGNALED(code) )
|
||||
errx(2, "%s: Mount failed: %s: %s", bdev_path, fs->driver,
|
||||
strsignal(WTERMSIG(code)));
|
||||
warnx("%s: Mount failed: %s: %s", bdev_path, fs->driver,
|
||||
strsignal(WTERMSIG(code)));
|
||||
else if ( !WIFEXITED(code) )
|
||||
errx(2, "%s: Mount failed: %s: %s", bdev_path, fs->driver,
|
||||
"Unexpected unusual termination");
|
||||
warnx("%s: Mount failed: %s: %s", bdev_path, fs->driver,
|
||||
"Unexpected unusual termination");
|
||||
else if ( WEXITSTATUS(code) == 127 )
|
||||
errx(2, "%s: Mount failed: %s: %s", bdev_path, fs->driver,
|
||||
"Filesystem driver is absent");
|
||||
warnx("%s: Mount failed: %s: %s", bdev_path, fs->driver,
|
||||
"Filesystem driver is absent");
|
||||
else if ( WEXITSTATUS(code) == 0 )
|
||||
errx(2, "%s: Mount failed: %s: Unexpected successful exit",
|
||||
bdev_path, fs->driver);
|
||||
warnx("%s: Mount failed: %s: Unexpected successful exit",
|
||||
bdev_path, fs->driver);
|
||||
else
|
||||
errx(2, "%s: Mount failed: %s: Exited with status %i", bdev_path,
|
||||
fs->driver, WEXITSTATUS(code));
|
||||
warnx("%s: Mount failed: %s: Exited with status %i", bdev_path,
|
||||
fs->driver, WEXITSTATUS(code));
|
||||
return false;
|
||||
}
|
||||
struct timespec delay = timespec_make(0, 50L * 1000L * 1000L);
|
||||
nanosleep(&delay, NULL);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void mountpoint_unmount(struct mountpoint* mountpoint)
|
||||
|
|
|
@ -42,14 +42,13 @@ void unscan_devices(void);
|
|||
void scan_devices(void);
|
||||
struct filesystem* search_for_filesystem_by_uuid(const unsigned char* uuid);
|
||||
struct filesystem* search_for_filesystem_by_spec(const char* spec);
|
||||
bool check_existing_systems(void);
|
||||
bool check_lacking_partition_table(void);
|
||||
bool fsck(struct filesystem* fs);
|
||||
void free_mountpoints(struct mountpoint* mnts, size_t mnts_count);
|
||||
bool load_mountpoints(const char* fstab_path,
|
||||
struct mountpoint** mountpoints_out,
|
||||
size_t* mountpoints_used_out);
|
||||
void mountpoint_mount(struct mountpoint* mountpoint);
|
||||
bool mountpoint_mount(struct mountpoint* mountpoint);
|
||||
void mountpoint_unmount(struct mountpoint* mountpoint);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,11 +51,13 @@
|
|||
#include <mount/partition.h>
|
||||
#include <mount/uuid.h>
|
||||
|
||||
#include "conf.h"
|
||||
#include "devices.h"
|
||||
#include "execute.h"
|
||||
#include "fileops.h"
|
||||
#include "interactive.h"
|
||||
#include "manifest.h"
|
||||
#include "release.h"
|
||||
|
||||
const char* prompt_man_section = "7";
|
||||
const char* prompt_man_page = "installation";
|
||||
|
@ -105,6 +107,116 @@ static bool missing_bios_boot_partition(struct filesystem* root_fs)
|
|||
return !search_bios_boot_search(pt);
|
||||
}
|
||||
|
||||
static bool should_install_bootloader_path(const char* mnt,
|
||||
struct blockdevice* bdev)
|
||||
{
|
||||
char* release_errpath;
|
||||
if ( asprintf(&release_errpath, "%s: /etc/sortix-release",
|
||||
path_of_blockdevice(bdev)) < 0 )
|
||||
{
|
||||
warn("malloc");
|
||||
return false;
|
||||
}
|
||||
char* release_path;
|
||||
if ( asprintf(&release_path, "%s/etc/sortix-release", mnt) < 0 )
|
||||
{
|
||||
warn("malloc");
|
||||
free(release_errpath);
|
||||
return false;
|
||||
}
|
||||
struct release release;
|
||||
if ( !os_release_load(&release, release_path, release_errpath) )
|
||||
{
|
||||
free(release_path);
|
||||
free(release_errpath);
|
||||
return false;
|
||||
}
|
||||
free(release_path);
|
||||
free(release_errpath);
|
||||
char* conf_path;
|
||||
if ( asprintf(&conf_path, "%s/etc/upgrade.conf", mnt) < 0 )
|
||||
{
|
||||
warn("malloc");
|
||||
return false;
|
||||
}
|
||||
// TODO: The load_upgrade_conf function might exit the process on failure,
|
||||
// but we don't want that. Redesign the mountpoint code so the caller
|
||||
// controls this.
|
||||
pid_t pid = fork();
|
||||
if ( pid < 0 )
|
||||
{
|
||||
warn("fork");
|
||||
free(conf_path);
|
||||
return false;
|
||||
}
|
||||
if ( !pid )
|
||||
{
|
||||
struct conf conf;
|
||||
load_upgrade_conf(&conf, conf_path);
|
||||
bool should = conf.grub;
|
||||
_exit(should ? 0 : 1);
|
||||
}
|
||||
int status;
|
||||
if ( waitpid(pid, &status, 0) < 0 )
|
||||
return false;
|
||||
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
|
||||
}
|
||||
|
||||
static bool should_install_bootloader_bdev(struct blockdevice* bdev)
|
||||
{
|
||||
if ( !bdev->fs )
|
||||
return false;
|
||||
if ( bdev->fs->flags & FILESYSTEM_FLAG_NOT_FILESYSTEM )
|
||||
return false;
|
||||
if ( !bdev->fs->driver )
|
||||
return false;
|
||||
char mnt[] = "/tmp/fs.XXXXXX";
|
||||
if ( !mkdtemp(mnt) )
|
||||
{
|
||||
warn("mkdtemp: %s", "/tmp/fs.XXXXXX");
|
||||
return false;
|
||||
}
|
||||
struct mountpoint mp = { 0 };
|
||||
mp.absolute = mnt;
|
||||
mp.fs = bdev->fs;
|
||||
mp.entry.fs_file = mnt;
|
||||
if ( !mountpoint_mount(&mp) )
|
||||
{
|
||||
rmdir(mnt);
|
||||
return false;
|
||||
}
|
||||
bool should = should_install_bootloader_path(mnt, bdev);
|
||||
mountpoint_unmount(&mp);
|
||||
rmdir(mnt);
|
||||
return should;
|
||||
}
|
||||
|
||||
static bool should_install_bootloader(void)
|
||||
{
|
||||
bool any_systems = false;
|
||||
for ( size_t i = 0; i < hds_count; i++ )
|
||||
{
|
||||
struct harddisk* hd = hds[i];
|
||||
if ( hd->bdev.pt )
|
||||
{
|
||||
for ( size_t n = 0; n < hd->bdev.pt->partitions_count; n++ )
|
||||
{
|
||||
any_systems = true;
|
||||
struct partition* p = hd->bdev.pt->partitions[n];
|
||||
if ( should_install_bootloader_bdev(&p->bdev) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if ( hd->bdev.fs )
|
||||
{
|
||||
any_systems = true;
|
||||
if ( should_install_bootloader_bdev(&hd->bdev) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return !any_systems;
|
||||
}
|
||||
|
||||
static bool passwd_check(const char* passwd_path,
|
||||
bool (*check)(struct passwd*, void*),
|
||||
void* check_ctx)
|
||||
|
@ -460,7 +572,10 @@ int main(void)
|
|||
text("\n");
|
||||
}
|
||||
|
||||
text("Searching for existing installations...\n");
|
||||
scan_devices();
|
||||
bool bootloader_default = should_install_bootloader();
|
||||
text("\n");
|
||||
|
||||
textf("You need a bootloader to start the operating system. GRUB is the "
|
||||
"standard %s bootloader and this installer comes with a copy. "
|
||||
|
@ -476,9 +591,7 @@ int main(void)
|
|||
char grub_password[512];
|
||||
while ( true )
|
||||
{
|
||||
const char* def = "yes";
|
||||
if ( check_existing_systems() )
|
||||
def = "no";
|
||||
const char* def = bootloader_default ? "yes" : "no";
|
||||
prompt(accept_grub, sizeof(accept_grub),
|
||||
"Install a new GRUB bootloader?", def);
|
||||
if ( strcasecmp(accept_grub, "no") == 0 ||
|
||||
|
@ -704,7 +817,8 @@ int main(void)
|
|||
mnt->absolute = absolute;
|
||||
if ( mkdir_p(mnt->absolute, 0755) < 0 )
|
||||
err(2, "mkdir: %s", mnt->absolute);
|
||||
mountpoint_mount(mnt);
|
||||
if ( !mountpoint_mount(mnt) )
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if ( chdir(fs) < 0 )
|
||||
|
|
Loading…
Reference in a new issue