malloc->zalloc
[grub2/phcoder.git] / util / resolve.c
blob8b33beba024331d0c52dbf6a54cd651ef0d5a495
1 /*
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/>.
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <ctype.h>
24 #include <grub/util/resolve.h>
25 #include <grub/util/misc.h>
27 /* Module. */
28 struct mod_list
30 const char *name;
31 struct mod_list *next;
34 /* Dependency. */
35 struct dep_list
37 const char *name;
38 struct mod_list *list;
39 struct dep_list *next;
42 static char buf[1024];
44 static void
45 free_mod_list (struct mod_list *head)
47 while (head)
49 struct mod_list *next;
51 next = head->next;
52 free ((void *) head->name);
53 free (head);
54 head = next;
58 static void
59 free_dep_list (struct dep_list *head)
61 while (head)
63 struct dep_list *next;
65 next = head->next;
66 free ((void *) head->name);
67 free_mod_list (head->list);
68 free (head);
69 head = next;
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))
81 char *p;
82 struct dep_list *dep;
84 /* Get the target name. */
85 p = strchr (buf, ':');
86 if (! p)
87 grub_util_error ("invalid line format: %s", buf);
89 *p++ = '\0';
91 dep = xmalloc (sizeof (*dep));
92 dep->name = xstrdup (buf);
93 dep->list = 0;
95 dep->next = dep_list;
96 dep_list = dep;
98 /* Add dependencies. */
99 while (*p)
101 struct mod_list *mod;
102 char *name;
104 /* Skip whitespace. */
105 while (*p && isspace (*p))
106 p++;
108 if (! *p)
109 break;
111 name = p;
113 /* Skip non-whitespace. */
114 while (*p && ! isspace (*p))
115 p++;
117 *p++ = '\0';
119 mod = (struct mod_list *) xmalloc (sizeof (*mod));
120 mod->name = xstrdup (name);
121 mod->next = dep->list;
122 dep->list = mod;
126 return dep_list;
129 static char *
130 get_module_name (const char *str)
132 char *base;
133 char *ext;
135 base = strrchr (str, '/');
136 if (! base)
137 base = (char *) str;
138 else
139 base++;
141 ext = strrchr (base, '.');
142 if (ext && strcmp (ext, ".mod") == 0)
144 char *name;
146 name = xmalloc (ext - base + 1);
147 memcpy (name, base, ext - base);
148 name[ext - base] = '\0';
149 return name;
152 return xstrdup (base);
155 static char *
156 get_module_path (const char *prefix, const char *str)
158 char *dir;
159 char *base;
160 char *ext;
161 char *ret;
163 ext = strrchr (str, '.');
164 if (ext && strcmp (ext, ".mod") == 0)
165 base = xstrdup (str);
166 else
168 base = xmalloc (strlen (str) + 4 + 1);
169 sprintf (base, "%s.mod", str);
172 dir = strchr (str, '/');
173 if (dir)
174 return base;
176 ret = grub_util_get_path (prefix, base);
177 free (base);
178 return ret;
181 static void
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,
186 const char *name)
188 char *mod_name;
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)
199 free (mod_name);
200 return;
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);
210 break;
213 /* Add this module. */
214 mod = (struct mod_list *) xmalloc (sizeof (*mod));
215 mod->name = mod_name;
216 mod->next = *mod_head;
217 *mod_head = mod;
219 /* Add this path. */
220 path = (struct grub_util_path_list *) xmalloc (sizeof (*path));
221 path->name = get_module_path (dir, name);
222 path->next = *path_head;
223 *path_head = path;
226 struct grub_util_path_list *
227 grub_util_resolve_dependencies (const char *prefix,
228 const char *dep_list_file,
229 char *modules[])
231 char *path;
232 FILE *fp;
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");
239 if (! fp)
240 grub_util_error ("cannot open %s", path);
242 free (path);
243 dep_list = read_dep_list (fp);
244 fclose (fp);
246 while (*modules)
248 add_module (prefix, dep_list, &mod_list, &path_list, *modules);
249 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)
260 next = p->next;
261 p->next = prev;
262 prev = p;
265 return prev;