]> git.proxmox.com Git - grub2.git/blame - util/resolve.c
Put recheck back
[grub2.git] / util / resolve.c
CommitLineData
6a161fa9 1/*
4b13b216 2 * GRUB -- GRand Unified Bootloader
5a79f472 3 * Copyright (C) 2002,2007 Free Software Foundation, Inc.
6a161fa9 4 *
5a79f472 5 * GRUB is free software: you can redistribute it and/or modify
6a161fa9 6 * it under the terms of the GNU General Public License as published by
5a79f472 7 * the Free Software Foundation, either version 3 of the License, or
6a161fa9 8 * (at your option) any later version.
9 *
5a79f472 10 * GRUB is distributed in the hope that it will be useful,
6a161fa9 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
5a79f472 16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
6a161fa9 17 */
18
1d12cf29
YB
19#include <config.h>
20
6a161fa9 21#include <stdio.h>
22#include <string.h>
23#include <stdlib.h>
24#include <ctype.h>
25
8c411768 26#include <grub/emu/misc.h>
4b13b216 27#include <grub/util/misc.h>
8c411768 28#include <grub/util/resolve.h>
6e0632e2 29#include <grub/i18n.h>
6a161fa9 30
31/* Module. */
32struct mod_list
33{
34 const char *name;
35 struct mod_list *next;
36};
37
38/* Dependency. */
39struct dep_list
40{
41 const char *name;
42 struct mod_list *list;
43 struct dep_list *next;
44};
45
46static char buf[1024];
47
48static void
49free_mod_list (struct mod_list *head)
50{
51 while (head)
52 {
53 struct mod_list *next;
54
55 next = head->next;
56 free ((void *) head->name);
57 free (head);
58 head = next;
59 }
60}
61
62static void
63free_dep_list (struct dep_list *head)
64{
65 while (head)
66 {
67 struct dep_list *next;
68
69 next = head->next;
70 free ((void *) head->name);
71 free_mod_list (head->list);
72 free (head);
73 head = next;
74 }
75}
76
77/* Read the list of dependencies. */
78static struct dep_list *
79read_dep_list (FILE *fp)
80{
81 struct dep_list *dep_list = 0;
b39f9d20 82
6a161fa9 83 while (fgets (buf, sizeof (buf), fp))
84 {
85 char *p;
86 struct dep_list *dep;
87
88 /* Get the target name. */
89 p = strchr (buf, ':');
90 if (! p)
6e0632e2 91 grub_util_error (_("invalid line format: %s"), buf);
6a161fa9 92
93 *p++ = '\0';
94
95 dep = xmalloc (sizeof (*dep));
96 dep->name = xstrdup (buf);
97 dep->list = 0;
b39f9d20 98
6a161fa9 99 dep->next = dep_list;
100 dep_list = dep;
101
102 /* Add dependencies. */
103 while (*p)
104 {
105 struct mod_list *mod;
106 char *name;
107
4241d2b1 108 /* Skip whitespace. */
6a161fa9 109 while (*p && isspace (*p))
110 p++;
111
112 if (! *p)
113 break;
114
115 name = p;
116
4241d2b1 117 /* Skip non-whitespace. */
6a161fa9 118 while (*p && ! isspace (*p))
119 p++;
120
121 *p++ = '\0';
b39f9d20 122
6a161fa9 123 mod = (struct mod_list *) xmalloc (sizeof (*mod));
124 mod->name = xstrdup (name);
125 mod->next = dep->list;
126 dep->list = mod;
127 }
128 }
129
130 return dep_list;
131}
132
133static char *
134get_module_name (const char *str)
135{
136 char *base;
137 char *ext;
b39f9d20 138
6a161fa9 139 base = strrchr (str, '/');
140 if (! base)
141 base = (char *) str;
142 else
143 base++;
144
145 ext = strrchr (base, '.');
146 if (ext && strcmp (ext, ".mod") == 0)
147 {
148 char *name;
b39f9d20 149
6a161fa9 150 name = xmalloc (ext - base + 1);
151 memcpy (name, base, ext - base);
152 name[ext - base] = '\0';
153 return name;
154 }
b39f9d20 155
6a161fa9 156 return xstrdup (base);
157}
158
159static char *
160get_module_path (const char *prefix, const char *str)
161{
162 char *dir;
163 char *base;
164 char *ext;
165 char *ret;
b39f9d20 166
6a161fa9 167 ext = strrchr (str, '.');
168 if (ext && strcmp (ext, ".mod") == 0)
169 base = xstrdup (str);
170 else
171 {
172 base = xmalloc (strlen (str) + 4 + 1);
173 sprintf (base, "%s.mod", str);
174 }
b39f9d20 175
6a161fa9 176 dir = strchr (str, '/');
177 if (dir)
178 return base;
179
4b13b216 180 ret = grub_util_get_path (prefix, base);
6a161fa9 181 free (base);
182 return ret;
183}
184
185static void
186add_module (const char *dir,
187 struct dep_list *dep_list,
188 struct mod_list **mod_head,
4b13b216 189 struct grub_util_path_list **path_head,
6a161fa9 190 const char *name)
191{
192 char *mod_name;
4b13b216 193 struct grub_util_path_list *path;
6a161fa9 194 struct mod_list *mod;
195 struct dep_list *dep;
b39f9d20 196
6a161fa9 197 mod_name = get_module_name (name);
198
199 /* Check if the module has already been added. */
200 for (mod = *mod_head; mod; mod = mod->next)
201 if (strcmp (mod->name, mod_name) == 0)
202 {
203 free (mod_name);
204 return;
205 }
206
207 /* Resolve dependencies. */
208 for (dep = dep_list; dep; dep = dep->next)
209 if (strcmp (dep->name, mod_name) == 0)
210 {
211 for (mod = dep->list; mod; mod = mod->next)
212 add_module (dir, dep_list, mod_head, path_head, mod->name);
213
214 break;
215 }
216
217 /* Add this module. */
218 mod = (struct mod_list *) xmalloc (sizeof (*mod));
219 mod->name = mod_name;
220 mod->next = *mod_head;
221 *mod_head = mod;
222
223 /* Add this path. */
4b13b216 224 path = (struct grub_util_path_list *) xmalloc (sizeof (*path));
6a161fa9 225 path->name = get_module_path (dir, name);
226 path->next = *path_head;
227 *path_head = path;
228}
229
4b13b216 230struct grub_util_path_list *
231grub_util_resolve_dependencies (const char *prefix,
6a161fa9 232 const char *dep_list_file,
233 char *modules[])
234{
235 char *path;
236 FILE *fp;
237 struct dep_list *dep_list;
238 struct mod_list *mod_list = 0;
4b13b216 239 struct grub_util_path_list *path_list = 0;
977329f5 240
4b13b216 241 path = grub_util_get_path (prefix, dep_list_file);
6a161fa9 242 fp = fopen (path, "r");
243 if (! fp)
6e0632e2 244 grub_util_error (_("cannot open %s"), path);
6a161fa9 245
246 free (path);
247 dep_list = read_dep_list (fp);
248 fclose (fp);
249
250 while (*modules)
251 {
252 add_module (prefix, dep_list, &mod_list, &path_list, *modules);
253 modules++;
254 }
255
256 free_dep_list (dep_list);
257 free_mod_list (mod_list);
258
977329f5 259 { /* Reverse the path_list */
4b13b216 260 struct grub_util_path_list *p, *prev, *next;
977329f5 261
262 for (p = path_list, prev = NULL; p; p = next)
263 {
264 next = p->next;
265 p->next = prev;
266 prev = p;
267 }
268
269 return prev;
270 }
6a161fa9 271}