<commit_before>/*
 * This file is part of clr-boot-manager.
 *
 * Copyright © 2016 Intel Corporation
 *
 * clr-boot-manager is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 */

#define _GNU_SOURCE

#include <assert.h>

#include "bootman.h"
#include "bootman_private.h"
#include "nica/files.h"

static bool boot_manager_update_image(BootManager *self);
static bool boot_manager_update_native(BootManager *self);

/**
 * Sort by release number, putting highest first
 */
static int kernel_compare_reverse(const void *a, const void *b)
{
        const Kernel *ka = *(const Kernel **)a;
        const Kernel *kb = *(const Kernel **)b;

        if (ka->release > kb->release) {
                return -1;
        }
        return 1;
}

bool boot_manager_update(BootManager *self)
{
        assert(self != NULL);
        bool ret = false;

        /* Image mode is very simple, no prep/cleanup */
        if (boot_manager_is_image_mode(self)) {
                return boot_manager_update_image(self);
        }

        /* Do a native update */
        ret = boot_manager_update_native(self);

        /* TODO: Insert cleanup code here */
        return ret;
}

/**
 * Update the target with logical view of an image creation
 *
 * Quite simply, we install all potential kernels to the specified boot
 * directory, and ensure it's equiped with a boot loader. The kernel with
 * the highest release number is selected as the default kernel.
 *
 * This method assumes the boot partition is *already mounted* at the target,
 * therefore it is an _error_ for the target to not exist. No attempt is
 * made to determine the running kernel or to mount a boot partition.
 */
static bool boot_manager_update_image(BootManager *self)
{
        assert(self != NULL);
        autofree(KernelArray) *kernels = NULL;
        autofree(char) *boot_dir = NULL;
        const Kernel *default_kernel = NULL;

        /* Grab the available kernels */
        kernels = boot_manager_get_kernels(self);
        if (!kernels || kernels->len == 0) {
                fprintf(stderr, "No kernels discovered in %s, bailing\n", self->kernel_dir);
                return false;
        }
<commit_msg>Add the mount/umount handler<commit_after>/*
 * This file is part of clr-boot-manager.
 *
 * Copyright © 2016 Intel Corporation
 *
 * clr-boot-manager is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1
 * of the License, or (at your option) any later version.
 */

#define _GNU_SOURCE

#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/mount.h>
#include <unistd.h>

#include "bootman.h"
#include "bootman_private.h"
#include "files.h"
#include "nica/files.h"

static bool boot_manager_update_image(BootManager *self);
static bool boot_manager_update_native(BootManager *self);

/**
 * Sort by release number, putting highest first
 */
static int kernel_compare_reverse(const void *a, const void *b)
{
        const Kernel *ka = *(const Kernel **)a;
        const Kernel *kb = *(const Kernel **)b;

        if (ka->release > kb->release) {
                return -1;
        }
        return 1;
}

bool boot_manager_update(BootManager *self)
{
        assert(self != NULL);
        bool ret = false;
        autofree(char) *boot_dir = NULL;
        bool did_mount = false;

        /* Image mode is very simple, no prep/cleanup */
        if (boot_manager_is_image_mode(self)) {
                return boot_manager_update_image(self);
        }

        /* Get our boot directory */
        boot_dir = boot_manager_get_boot_dir(self);
        if (!boot_dir) {
                DECLARE_OOM();
                return false;
        }

        /* Prepare mounts */
        if (boot_manager_get_can_mount(self)) {
                /* Already mounted at the default boot dir, nothing for us to do */
                if (cbm_is_mounted(boot_dir, NULL)) {
                        goto perform;
                }
                autofree(char) *root_device = NULL;
                autofree(char) *root_base = NULL;
                autofree(char) *abs_bootdir = NULL;

                /* Determine root device */
                root_device = get_boot_device();
                if (!root_device) {
                        fprintf(stderr, "FATAL: Cannot determine boot device\n");
                        return false;
                }

                /* Resolve the actual device */
                root_base = realpath(root_device, NULL);
                if (!root_base) {
                        DECLARE_OOM();
                        return false;
                }

                abs_bootdir = cbm_get_mountpoint_for_device(root_base);

                if (abs_bootdir) {
                        /* User has already mounted the ESP somewhere else, use that */
                        if (!boot_manager_set_boot_dir(self, abs_bootdir)) {
                                fprintf(stderr, "FATAL: Cannot initialise with premounted ESP\n");
                                return false;
                        }
                        /* Successfully using their premounted ESP, go use it */
                        goto perform;
                }

                /* The boot directory isn't mounted, so we'll mount it now */
                if (!nc_file_exists(boot_dir)) {
                        nc_mkdir_p(boot_dir, 0755);
                }
                if (mount(root_base, boot_dir, "vfat", MS_MGC_VAL, "") < 0) {
                        fprintf(stderr,
                                "FATAL: Cannot mount boot device %s on %s: %s\n",
                                root_base,
                                boot_dir,
                                strerror(errno));
                        return false;
                }
                did_mount = true;
        }

perform:
        /* Do a native update */
        ret = boot_manager_update_native(self);

        /* Cleanup and umount */
        if (did_mount) {
                if (umount(boot_dir) < 0) {
                        fprintf(stderr, "WARNING: Could not unmount boot directory\n");
                }
        }

        /* Done */
        return ret;
}

/**
 * Update the target with logical view of an image creation
 *
 * Quite simply, we install all potential kernels to the specified boot
 * directory, and ensure it's equiped with a boot loader. The kernel with
 * the highest release number is selected as the default kernel.
 *
 * This method assumes the boot partition is *already mounted* at the target,
 * therefore it is an _error_ for the target to not exist. No attempt is
 * made to determine the running kernel or to mount a boot partition.
 */
static bool boot_manager_update_image(BootManager *self)
{
        assert(self != NULL);
        autofree(KernelArray) *kernels = NULL;
        autofree(char) *boot_dir = NULL;
        const Kernel *default_kernel = NULL;

        /* Grab the available kernels */
        kernels = boot_manager_get_kernels(self);
        if (!kernels || kernels->len == 0) {
                fprintf(stderr, "No kernels discovered in %s, bailing\n", self->kernel_dir);
                return false;
        }

{'fraction_non_alphanumeric': 0.08970055055727139, 'fraction_numerical': 0.0032227742715187323, 'mean_word_length': 1.9105119187182493, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2931185', 'n_tokens_mistral': 2111, 'n_tokens_neox': 1983, 'n_words': 683}