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/>.
24 #include <grub/util/resolve.h>
25 #include <grub/util/misc.h>
31 struct mod_list
*next
;
38 struct mod_list
*list
;
39 struct dep_list
*next
;
42 static char buf
[1024];
45 free_mod_list (struct mod_list
*head
)
49 struct mod_list
*next
;
52 free ((void *) head
->name
);
59 free_dep_list (struct dep_list
*head
)
63 struct dep_list
*next
;
66 free ((void *) head
->name
);
67 free_mod_list (head
->list
);
73 /* Read the list of dependencies. */
74 static struct dep_list
*
75 read_dep_list (FILE *fp
)
77 struct dep_list
*dep_list
= 0;
79 while (fgets (buf
, sizeof (buf
), fp
))
84 /* Get the target name. */
85 p
= strchr (buf
, ':');
87 grub_util_error ("invalid line format: %s", buf
);
91 dep
= xmalloc (sizeof (*dep
));
92 dep
->name
= xstrdup (buf
);
98 /* Add dependencies. */
101 struct mod_list
*mod
;
104 /* Skip whitespace. */
105 while (*p
&& isspace (*p
))
113 /* Skip non-whitespace. */
114 while (*p
&& ! isspace (*p
))
119 mod
= (struct mod_list
*) xmalloc (sizeof (*mod
));
120 mod
->name
= xstrdup (name
);
121 mod
->next
= dep
->list
;
130 get_module_name (const char *str
)
135 base
= strrchr (str
, '/');
141 ext
= strrchr (base
, '.');
142 if (ext
&& strcmp (ext
, ".mod") == 0)
146 name
= xmalloc (ext
- base
+ 1);
147 memcpy (name
, base
, ext
- base
);
148 name
[ext
- base
] = '\0';
152 return xstrdup (base
);
156 get_module_path (const char *prefix
, const char *str
)
163 ext
= strrchr (str
, '.');
164 if (ext
&& strcmp (ext
, ".mod") == 0)
165 base
= xstrdup (str
);
168 base
= xmalloc (strlen (str
) + 4 + 1);
169 sprintf (base
, "%s.mod", str
);
172 dir
= strchr (str
, '/');
176 ret
= grub_util_get_path (prefix
, base
);
182 add_module (const char *dir
,
183 struct dep_list
*dep_list
,
184 struct mod_list
**mod_head
,
185 struct grub_util_path_list
**path_head
,
189 struct grub_util_path_list
*path
;
190 struct mod_list
*mod
;
191 struct dep_list
*dep
;
193 mod_name
= get_module_name (name
);
195 /* Check if the module has already been added. */
196 for (mod
= *mod_head
; mod
; mod
= mod
->next
)
197 if (strcmp (mod
->name
, mod_name
) == 0)
203 /* Resolve dependencies. */
204 for (dep
= dep_list
; dep
; dep
= dep
->next
)
205 if (strcmp (dep
->name
, mod_name
) == 0)
207 for (mod
= dep
->list
; mod
; mod
= mod
->next
)
208 add_module (dir
, dep_list
, mod_head
, path_head
, mod
->name
);
213 /* Add this module. */
214 mod
= (struct mod_list
*) xmalloc (sizeof (*mod
));
215 mod
->name
= mod_name
;
216 mod
->next
= *mod_head
;
220 path
= (struct grub_util_path_list
*) xmalloc (sizeof (*path
));
221 path
->name
= get_module_path (dir
, name
);
222 path
->next
= *path_head
;
226 struct grub_util_path_list
*
227 grub_util_resolve_dependencies (const char *prefix
,
228 const char *dep_list_file
,
233 struct dep_list
*dep_list
;
234 struct mod_list
*mod_list
= 0;
235 struct grub_util_path_list
*path_list
= 0;
237 path
= grub_util_get_path (prefix
, dep_list_file
);
238 fp
= fopen (path
, "r");
240 grub_util_error ("cannot open %s", path
);
243 dep_list
= read_dep_list (fp
);
248 add_module (prefix
, dep_list
, &mod_list
, &path_list
, *modules
);
252 free_dep_list (dep_list
);
253 free_mod_list (mod_list
);
255 { /* Reverse the path_list */
256 struct grub_util_path_list
*p
, *prev
, *next
;
258 for (p
= path_list
, prev
= NULL
; p
; p
= next
)