]> git.proxmox.com Git - grub2.git/blame_incremental - util/resolve.c
Put recheck back
[grub2.git] / util / resolve.c
... / ...
CommitLineData
1/*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2002,2007 Free Software Foundation, Inc.
4 *
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * GRUB is distributed in the hope that it will be useful,
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
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <config.h>
20
21#include <stdio.h>
22#include <string.h>
23#include <stdlib.h>
24#include <ctype.h>
25
26#include <grub/emu/misc.h>
27#include <grub/util/misc.h>
28#include <grub/util/resolve.h>
29#include <grub/i18n.h>
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;
82
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)
91 grub_util_error (_("invalid line format: %s"), buf);
92
93 *p++ = '\0';
94
95 dep = xmalloc (sizeof (*dep));
96 dep->name = xstrdup (buf);
97 dep->list = 0;
98
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
108 /* Skip whitespace. */
109 while (*p && isspace (*p))
110 p++;
111
112 if (! *p)
113 break;
114
115 name = p;
116
117 /* Skip non-whitespace. */
118 while (*p && ! isspace (*p))
119 p++;
120
121 *p++ = '\0';
122
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;
138
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;
149
150 name = xmalloc (ext - base + 1);
151 memcpy (name, base, ext - base);
152 name[ext - base] = '\0';
153 return name;
154 }
155
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;
166
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 }
175
176 dir = strchr (str, '/');
177 if (dir)
178 return base;
179
180 ret = grub_util_get_path (prefix, base);
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,
189 struct grub_util_path_list **path_head,
190 const char *name)
191{
192 char *mod_name;
193 struct grub_util_path_list *path;
194 struct mod_list *mod;
195 struct dep_list *dep;
196
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. */
224 path = (struct grub_util_path_list *) xmalloc (sizeof (*path));
225 path->name = get_module_path (dir, name);
226 path->next = *path_head;
227 *path_head = path;
228}
229
230struct grub_util_path_list *
231grub_util_resolve_dependencies (const char *prefix,
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;
239 struct grub_util_path_list *path_list = 0;
240
241 path = grub_util_get_path (prefix, dep_list_file);
242 fp = fopen (path, "r");
243 if (! fp)
244 grub_util_error (_("cannot open %s"), path);
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
259 { /* Reverse the path_list */
260 struct grub_util_path_list *p, *prev, *next;
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 }
271}