2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2002,2007 Free Software Foundation, Inc.
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.
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.
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/>.
27 #include <grub/emu/misc.h>
28 #include <grub/misc.h>
29 #include <grub/util/misc.h>
30 #include <grub/util/resolve.h>
31 #include <grub/i18n.h>
37 struct mod_list
*next
;
44 struct mod_list
*list
;
45 struct dep_list
*next
;
48 static char buf
[1024];
51 free_mod_list (struct mod_list
*head
)
55 struct mod_list
*next
;
58 free ((void *) head
->name
);
65 free_dep_list (struct dep_list
*head
)
69 struct dep_list
*next
;
72 free ((void *) head
->name
);
73 free_mod_list (head
->list
);
79 /* Read the list of dependencies. */
80 static struct dep_list
*
81 read_dep_list (FILE *fp
)
83 struct dep_list
*dep_list
= 0;
85 while (fgets (buf
, sizeof (buf
), fp
))
90 /* Get the target name. */
91 p
= strchr (buf
, ':');
93 grub_util_error (_("invalid line format: %s"), buf
);
97 dep
= xmalloc (sizeof (*dep
));
98 dep
->name
= xstrdup (buf
);
101 dep
->next
= dep_list
;
104 /* Add dependencies. */
107 struct mod_list
*mod
;
110 /* Skip whitespace. */
111 while (*p
&& grub_isspace (*p
))
119 /* Skip non-whitespace. */
120 while (*p
&& ! grub_isspace (*p
))
125 mod
= (struct mod_list
*) xmalloc (sizeof (*mod
));
126 mod
->name
= xstrdup (name
);
127 mod
->next
= dep
->list
;
136 get_module_name (const char *str
)
141 base
= strrchr (str
, '/');
147 ext
= strrchr (base
, '.');
148 if (ext
&& strcmp (ext
, ".mod") == 0)
152 name
= xmalloc (ext
- base
+ 1);
153 memcpy (name
, base
, ext
- base
);
154 name
[ext
- base
] = '\0';
158 return xstrdup (base
);
162 get_module_path (const char *prefix
, const char *str
)
169 ext
= strrchr (str
, '.');
170 if (ext
&& strcmp (ext
, ".mod") == 0)
171 base
= xstrdup (str
);
174 base
= xmalloc (strlen (str
) + 4 + 1);
175 sprintf (base
, "%s.mod", str
);
178 dir
= strchr (str
, '/');
182 ret
= grub_util_get_path (prefix
, base
);
188 add_module (const char *dir
,
189 struct dep_list
*dep_list
,
190 struct mod_list
**mod_head
,
191 struct grub_util_path_list
**path_head
,
195 struct grub_util_path_list
*path
;
196 struct mod_list
*mod
;
197 struct dep_list
*dep
;
199 mod_name
= get_module_name (name
);
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)
209 /* Resolve dependencies. */
210 for (dep
= dep_list
; dep
; dep
= dep
->next
)
211 if (strcmp (dep
->name
, mod_name
) == 0)
213 for (mod
= dep
->list
; mod
; mod
= mod
->next
)
214 add_module (dir
, dep_list
, mod_head
, path_head
, mod
->name
);
219 /* Add this module. */
220 mod
= (struct mod_list
*) xmalloc (sizeof (*mod
));
221 mod
->name
= mod_name
;
222 mod
->next
= *mod_head
;
226 path
= (struct grub_util_path_list
*) xmalloc (sizeof (*path
));
227 path
->name
= get_module_path (dir
, name
);
228 path
->next
= *path_head
;
232 struct grub_util_path_list
*
233 grub_util_resolve_dependencies (const char *prefix
,
234 const char *dep_list_file
,
239 struct dep_list
*dep_list
;
240 struct mod_list
*mod_list
= 0;
241 struct grub_util_path_list
*path_list
= 0;
243 path
= grub_util_get_path (prefix
, dep_list_file
);
244 fp
= grub_util_fopen (path
, "r");
246 grub_util_error (_("cannot open `%s': %s"), path
, strerror (errno
));
249 dep_list
= read_dep_list (fp
);
254 add_module (prefix
, dep_list
, &mod_list
, &path_list
, *modules
);
258 free_dep_list (dep_list
);
259 free_mod_list (mod_list
);
261 { /* Reverse the path_list */
262 struct grub_util_path_list
*p
, *prev
, *next
;
264 for (p
= path_list
, prev
= NULL
; p
; p
= next
)