123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- /*
- * GRUB -- GRand Unified Bootloader
- * Copyright (C) 2002,2007 Free Software Foundation, Inc.
- *
- * GRUB is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * GRUB 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
- */
- #include <config.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <errno.h>
- #include <grub/emu/misc.h>
- #include <grub/misc.h>
- #include <grub/util/misc.h>
- #include <grub/util/resolve.h>
- #include <grub/i18n.h>
- /* Module. */
- struct mod_list
- {
- const char *name;
- struct mod_list *next;
- };
- /* Dependency. */
- struct dep_list
- {
- const char *name;
- struct mod_list *list;
- struct dep_list *next;
- };
- static char buf[1024];
- static void
- free_mod_list (struct mod_list *head)
- {
- while (head)
- {
- struct mod_list *next;
- next = head->next;
- free ((void *) head->name);
- free (head);
- head = next;
- }
- }
- static void
- free_dep_list (struct dep_list *head)
- {
- while (head)
- {
- struct dep_list *next;
- next = head->next;
- free ((void *) head->name);
- free_mod_list (head->list);
- free (head);
- head = next;
- }
- }
- /* Read the list of dependencies. */
- static struct dep_list *
- read_dep_list (FILE *fp)
- {
- struct dep_list *dep_list = 0;
- while (fgets (buf, sizeof (buf), fp))
- {
- char *p;
- struct dep_list *dep;
- /* Get the target name. */
- p = strchr (buf, ':');
- if (! p)
- grub_util_error (_("invalid line format: %s"), buf);
- *p++ = '\0';
- dep = xmalloc (sizeof (*dep));
- dep->name = xstrdup (buf);
- dep->list = 0;
- dep->next = dep_list;
- dep_list = dep;
- /* Add dependencies. */
- while (*p)
- {
- struct mod_list *mod;
- char *name;
- /* Skip whitespace. */
- while (*p && grub_isspace (*p))
- p++;
- if (! *p)
- break;
- name = p;
- /* Skip non-whitespace. */
- while (*p && ! grub_isspace (*p))
- p++;
- *p++ = '\0';
- mod = (struct mod_list *) xmalloc (sizeof (*mod));
- mod->name = xstrdup (name);
- mod->next = dep->list;
- dep->list = mod;
- }
- }
- return dep_list;
- }
- static char *
- get_module_name (const char *str)
- {
- char *base;
- char *ext;
- base = strrchr (str, '/');
- if (! base)
- base = (char *) str;
- else
- base++;
- ext = strrchr (base, '.');
- if (ext && strcmp (ext, ".mod") == 0)
- {
- char *name;
- name = xmalloc (ext - base + 1);
- memcpy (name, base, ext - base);
- name[ext - base] = '\0';
- return name;
- }
- return xstrdup (base);
- }
- static char *
- get_module_path (const char *prefix, const char *str)
- {
- char *dir;
- char *base;
- char *ext;
- char *ret;
- ext = strrchr (str, '.');
- if (ext && strcmp (ext, ".mod") == 0)
- base = xstrdup (str);
- else
- {
- base = xmalloc (strlen (str) + 4 + 1);
- sprintf (base, "%s.mod", str);
- }
- dir = strchr (str, '/');
- if (dir)
- return base;
- ret = grub_util_get_path (prefix, base);
- free (base);
- return ret;
- }
- static void
- add_module (const char *dir,
- struct dep_list *dep_list,
- struct mod_list **mod_head,
- struct grub_util_path_list **path_head,
- const char *name)
- {
- char *mod_name;
- struct grub_util_path_list *path;
- struct mod_list *mod;
- struct dep_list *dep;
- mod_name = get_module_name (name);
- /* Check if the module has already been added. */
- for (mod = *mod_head; mod; mod = mod->next)
- if (strcmp (mod->name, mod_name) == 0)
- {
- free (mod_name);
- return;
- }
- /* Resolve dependencies. */
- for (dep = dep_list; dep; dep = dep->next)
- if (strcmp (dep->name, mod_name) == 0)
- {
- for (mod = dep->list; mod; mod = mod->next)
- add_module (dir, dep_list, mod_head, path_head, mod->name);
- break;
- }
- /* Add this module. */
- mod = (struct mod_list *) xmalloc (sizeof (*mod));
- mod->name = mod_name;
- mod->next = *mod_head;
- *mod_head = mod;
- /* Add this path. */
- path = (struct grub_util_path_list *) xmalloc (sizeof (*path));
- path->name = get_module_path (dir, name);
- path->next = *path_head;
- *path_head = path;
- }
- struct grub_util_path_list *
- grub_util_resolve_dependencies (const char *prefix,
- const char *dep_list_file,
- char *modules[])
- {
- char *path;
- FILE *fp;
- struct dep_list *dep_list;
- struct mod_list *mod_list = 0;
- struct grub_util_path_list *path_list = 0;
- path = grub_util_get_path (prefix, dep_list_file);
- fp = grub_util_fopen (path, "r");
- if (! fp)
- grub_util_error (_("cannot open `%s': %s"), path, strerror (errno));
- free (path);
- dep_list = read_dep_list (fp);
- fclose (fp);
- while (*modules)
- {
- add_module (prefix, dep_list, &mod_list, &path_list, *modules);
- modules++;
- }
- free_dep_list (dep_list);
- free_mod_list (mod_list);
- { /* Reverse the path_list */
- struct grub_util_path_list *p, *prev, *next;
- for (p = path_list, prev = NULL; p; p = next)
- {
- next = p->next;
- p->next = prev;
- prev = p;
- }
- return prev;
- }
- }
- void
- grub_util_free_path_list (struct grub_util_path_list *path_list)
- {
- struct grub_util_path_list *next;
- while (path_list)
- {
- next = path_list->next;
- free ((void *) path_list->name);
- free (path_list);
- path_list = next;
- }
- }
|