/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/

/***
  This file is part of systemd.

  Copyright 2013 Kay Sievers

  systemd 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.

  systemd is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License
  along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/

#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <getopt.h>
#include <locale.h>
#include <string.h>
#include <ctype.h>
#include <sys/timex.h>

#include "boot.h"
#include "boot-loader.h"
#include "build.h"
#include "util.h"
#include "strv.h"
#include "conf-files.h"

static char *loader_fragment_read_title(const char *fragment) {
        FILE *f;
        char line[LINE_MAX];
        char *title = NULL;

        f = fopen(fragment, "re");
        if (!f)
                return NULL;

        while (fgets(line, sizeof(line), f) != NULL) {
                char *s;
                size_t l;

                l = strlen(line);
                if (l < 1)
                        continue;
                if (line[l-1] == '\n')
                        line[l-1] = '\0';

                s = line;
                while (isspace(s[0]))
                        s++;

                if (s[0] == '#')
                        continue;

                if (!startswith(s, "title"))
                        continue;

                s += strlen("title");
                if (!isspace(s[0]))
                        continue;
                while (isspace(s[0]))
                        s++;

                title = strdup(s);
                break;
        }

        fclose(f);
        return title;
}

int boot_loader_read_entries(struct boot_info *info) {
        _cleanup_strv_free_ char **files = NULL;
        static const char *loader_dir[] = { "/boot/loader/entries", NULL};
        unsigned int count;
        unsigned int i;
        int err;

        err = conf_files_list_strv(&files, ".conf", NULL, loader_dir);
        if (err < 0)
                return err;

        count = strv_length(files);
        info->loader_entries = new0(struct boot_info_entry, count);
        if (!info->loader_entries)
                return -ENOMEM;

        for (i = 0; i < count; i++) {
                info->loader_entries[i].title = loader_fragment_read_title(files[i]);
                info->loader_entries[i].path = strdup(files[i]);
                if (!info->loader_entries[i].title || !info->loader_entries[i].path) {
                        free(info->loader_entries[i].title);
                        free(info->loader_entries[i].path);
                        return -ENOMEM;
                }
                info->loader_entries_count++;
        }

        return 0;
}

int boot_loader_find_active_entry(struct boot_info *info, const char *loader_active) {
        char *fn;
        unsigned int i;

        if (!loader_active)
                return -ENOENT;
        if (info->loader_entries_count == 0)
                return -ENOENT;

        if (asprintf(&fn, "/boot/loader/entries/%s.conf", loader_active) < 0)
                return -ENOMEM;

        for (i = 0; i < info->loader_entries_count; i++) {
                if (streq(fn, info->loader_entries[i].path)) {
                        info->loader_entry_active = i;
                        break;
                }
        }

        free(fn);
        return 0;
}