]> git.proxmox.com Git - grub2.git/blame - util/resolve.c
bump version to 2.06-13+pmx2
[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>
0ae70393 25#include <errno.h>
6a161fa9 26
8c411768 27#include <grub/emu/misc.h>
88d51eff 28#include <grub/misc.h>
4b13b216 29#include <grub/util/misc.h>
8c411768 30#include <grub/util/resolve.h>
6e0632e2 31#include <grub/i18n.h>
6a161fa9 32
33/* Module. */
34struct mod_list
35{
36 const char *name;
37 struct mod_list *next;
38};
39
40/* Dependency. */
41struct dep_list
42{
43 const char *name;
44 struct mod_list *list;
45 struct dep_list *next;
46};
47
48static char buf[1024];
49
50static void
51free_mod_list (struct mod_list *head)
52{
53 while (head)
54 {
55 struct mod_list *next;
56
57 next = head->next;
58 free ((void *) head->name);
59 free (head);
60 head = next;
61 }
62}
63
64static void
65free_dep_list (struct dep_list *head)
66{
67 while (head)
68 {
69 struct dep_list *next;
70
71 next = head->next;
72 free ((void *) head->name);
73 free_mod_list (head->list);
74 free (head);
75 head = next;
76 }
77}
78
79/* Read the list of dependencies. */
80static struct dep_list *
81read_dep_list (FILE *fp)
82{
83 struct dep_list *dep_list = 0;
b39f9d20 84
6a161fa9 85 while (fgets (buf, sizeof (buf), fp))
86 {
87 char *p;
88 struct dep_list *dep;
89
90 /* Get the target name. */
91 p = strchr (buf, ':');
92 if (! p)
6e0632e2 93 grub_util_error (_("invalid line format: %s"), buf);
6a161fa9 94
95 *p++ = '\0';
96
97 dep = xmalloc (sizeof (*dep));
98 dep->name = xstrdup (buf);
99 dep->list = 0;
b39f9d20 100
6a161fa9 101 dep->next = dep_list;
102 dep_list = dep;
103
104 /* Add dependencies. */
105 while (*p)
106 {
107 struct mod_list *mod;
108 char *name;
109
4241d2b1 110 /* Skip whitespace. */
88d51eff 111 while (*p && grub_isspace (*p))
6a161fa9 112 p++;
113
114 if (! *p)
115 break;
116
117 name = p;
118
4241d2b1 119 /* Skip non-whitespace. */
88d51eff 120 while (*p && ! grub_isspace (*p))
6a161fa9 121 p++;
122
123 *p++ = '\0';
b39f9d20 124
6a161fa9 125 mod = (struct mod_list *) xmalloc (sizeof (*mod));
126 mod->name = xstrdup (name);
127 mod->next = dep->list;
128 dep->list = mod;
129 }
130 }
131
132 return dep_list;
133}
134
135static char *
136get_module_name (const char *str)
137{
138 char *base;
139 char *ext;
b39f9d20 140
6a161fa9 141 base = strrchr (str, '/');
142 if (! base)
143 base = (char *) str;
144 else
145 base++;
146
147 ext = strrchr (base, '.');
148 if (ext && strcmp (ext, ".mod") == 0)
149 {
150 char *name;
b39f9d20 151
6a161fa9 152 name = xmalloc (ext - base + 1);
153 memcpy (name, base, ext - base);
154 name[ext - base] = '\0';
155 return name;
156 }
b39f9d20 157
6a161fa9 158 return xstrdup (base);
159}
160
161static char *
162get_module_path (const char *prefix, const char *str)
163{
164 char *dir;
165 char *base;
166 char *ext;
167 char *ret;
b39f9d20 168
6a161fa9 169 ext = strrchr (str, '.');
170 if (ext && strcmp (ext, ".mod") == 0)
171 base = xstrdup (str);
172 else
173 {
174 base = xmalloc (strlen (str) + 4 + 1);
175 sprintf (base, "%s.mod", str);
176 }
b39f9d20 177
6a161fa9 178 dir = strchr (str, '/');
179 if (dir)
180 return base;
181
4b13b216 182 ret = grub_util_get_path (prefix, base);
6a161fa9 183 free (base);
184 return ret;
185}
186
187static void
188add_module (const char *dir,
189 struct dep_list *dep_list,
190 struct mod_list **mod_head,
4b13b216 191 struct grub_util_path_list **path_head,
6a161fa9 192 const char *name)
193{
194 char *mod_name;
4b13b216 195 struct grub_util_path_list *path;
6a161fa9 196 struct mod_list *mod;
197 struct dep_list *dep;
b39f9d20 198
6a161fa9 199 mod_name = get_module_name (name);
200
201 /* Check if the module has already been added. */
202 for (mod = *mod_head; mod; mod = mod->next)
203 if (strcmp (mod->name, mod_name) == 0)
204 {
205 free (mod_name);
206 return;
207 }
208
209 /* Resolve dependencies. */
210 for (dep = dep_list; dep; dep = dep->next)
211 if (strcmp (dep->name, mod_name) == 0)
212 {
213 for (mod = dep->list; mod; mod = mod->next)
214 add_module (dir, dep_list, mod_head, path_head, mod->name);
215
216 break;
217 }
218
219 /* Add this module. */
220 mod = (struct mod_list *) xmalloc (sizeof (*mod));
221 mod->name = mod_name;
222 mod->next = *mod_head;
223 *mod_head = mod;
224
225 /* Add this path. */
4b13b216 226 path = (struct grub_util_path_list *) xmalloc (sizeof (*path));
6a161fa9 227 path->name = get_module_path (dir, name);
228 path->next = *path_head;
229 *path_head = path;
230}
231
4b13b216 232struct grub_util_path_list *
233grub_util_resolve_dependencies (const char *prefix,
6a161fa9 234 const char *dep_list_file,
235 char *modules[])
236{
237 char *path;
238 FILE *fp;
239 struct dep_list *dep_list;
240 struct mod_list *mod_list = 0;
4b13b216 241 struct grub_util_path_list *path_list = 0;
977329f5 242
4b13b216 243 path = grub_util_get_path (prefix, dep_list_file);
bb338aaf 244 fp = grub_util_fopen (path, "r");
6a161fa9 245 if (! fp)
0ae70393 246 grub_util_error (_("cannot open `%s': %s"), path, strerror (errno));
6a161fa9 247
248 free (path);
249 dep_list = read_dep_list (fp);
250 fclose (fp);
251
252 while (*modules)
253 {
254 add_module (prefix, dep_list, &mod_list, &path_list, *modules);
255 modules++;
256 }
257
258 free_dep_list (dep_list);
259 free_mod_list (mod_list);
260
977329f5 261 { /* Reverse the path_list */
4b13b216 262 struct grub_util_path_list *p, *prev, *next;
977329f5 263
264 for (p = path_list, prev = NULL; p; p = next)
265 {
266 next = p->next;
267 p->next = prev;
268 prev = p;
269 }
270
271 return prev;
272 }
6a161fa9 273}
0e075ac3
AB
274
275void
276grub_util_free_path_list (struct grub_util_path_list *path_list)
277{
278 struct grub_util_path_list *next;
279
280 while (path_list)
281 {
282 next = path_list->next;
283 free ((void *) path_list->name);
284 free (path_list);
285 path_list = next;
286 }
287}