boot-loader.c revision 4d34c4951ab1b9c85fd3aefd40deb87ae05b4c65
/*-*- 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 (strcmp(fn, info->loader_entries[i].path) == 0) {
info->loader_entry_active = i;
break;
}
}
free(fn);
return 0;
}