| /*-*- 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; |
| } |