]>
Commit | Line | Data |
---|---|---|
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. */ | |
32 | struct mod_list | |
33 | { | |
34 | const char *name; | |
35 | struct mod_list *next; | |
36 | }; | |
37 | ||
38 | /* Dependency. */ | |
39 | struct dep_list | |
40 | { | |
41 | const char *name; | |
42 | struct mod_list *list; | |
43 | struct dep_list *next; | |
44 | }; | |
45 | ||
46 | static char buf[1024]; | |
47 | ||
48 | static void | |
49 | free_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 | ||
62 | static void | |
63 | free_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. */ | |
78 | static struct dep_list * | |
79 | read_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 | ||
133 | static char * | |
134 | get_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 | ||
159 | static char * | |
160 | get_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 | ||
185 | static void | |
186 | add_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 | 230 | struct grub_util_path_list * |
231 | grub_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 | } |