resolve.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2002,2007 Free Software Foundation, Inc.
  4. *
  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.
  9. *
  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.
  14. *
  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/>.
  17. */
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <ctype.h>
  22. #include <grub/util/resolve.h>
  23. #include <grub/util/misc.h>
  24. /* Module. */
  25. struct mod_list
  26. {
  27. const char *name;
  28. struct mod_list *next;
  29. };
  30. /* Dependency. */
  31. struct dep_list
  32. {
  33. const char *name;
  34. struct mod_list *list;
  35. struct dep_list *next;
  36. };
  37. static char buf[1024];
  38. static void
  39. free_mod_list (struct mod_list *head)
  40. {
  41. while (head)
  42. {
  43. struct mod_list *next;
  44. next = head->next;
  45. free ((void *) head->name);
  46. free (head);
  47. head = next;
  48. }
  49. }
  50. static void
  51. free_dep_list (struct dep_list *head)
  52. {
  53. while (head)
  54. {
  55. struct dep_list *next;
  56. next = head->next;
  57. free ((void *) head->name);
  58. free_mod_list (head->list);
  59. free (head);
  60. head = next;
  61. }
  62. }
  63. /* Read the list of dependencies. */
  64. static struct dep_list *
  65. read_dep_list (FILE *fp)
  66. {
  67. struct dep_list *dep_list = 0;
  68. while (fgets (buf, sizeof (buf), fp))
  69. {
  70. char *p;
  71. struct dep_list *dep;
  72. /* Get the target name. */
  73. p = strchr (buf, ':');
  74. if (! p)
  75. grub_util_error ("invalid line format: %s", buf);
  76. *p++ = '\0';
  77. dep = xmalloc (sizeof (*dep));
  78. dep->name = xstrdup (buf);
  79. dep->list = 0;
  80. dep->next = dep_list;
  81. dep_list = dep;
  82. /* Add dependencies. */
  83. while (*p)
  84. {
  85. struct mod_list *mod;
  86. char *name;
  87. /* Skip whitespace. */
  88. while (*p && isspace (*p))
  89. p++;
  90. if (! *p)
  91. break;
  92. name = p;
  93. /* Skip non-whitespace. */
  94. while (*p && ! isspace (*p))
  95. p++;
  96. *p++ = '\0';
  97. mod = (struct mod_list *) xmalloc (sizeof (*mod));
  98. mod->name = xstrdup (name);
  99. mod->next = dep->list;
  100. dep->list = mod;
  101. }
  102. }
  103. return dep_list;
  104. }
  105. static void
  106. add_module (const char *dir,
  107. struct dep_list *dep_list,
  108. struct mod_list **mod_head,
  109. struct grub_util_path_list **path_head,
  110. const char *name)
  111. {
  112. char *mod_name;
  113. struct grub_util_path_list *path;
  114. struct mod_list *mod;
  115. struct dep_list *dep;
  116. mod_name = grub_util_get_module_name (name);
  117. /* Check if the module has already been added. */
  118. for (mod = *mod_head; mod; mod = mod->next)
  119. if (strcmp (mod->name, mod_name) == 0)
  120. {
  121. free (mod_name);
  122. return;
  123. }
  124. /* Resolve dependencies. */
  125. for (dep = dep_list; dep; dep = dep->next)
  126. if (strcmp (dep->name, mod_name) == 0)
  127. {
  128. for (mod = dep->list; mod; mod = mod->next)
  129. add_module (dir, dep_list, mod_head, path_head, mod->name);
  130. break;
  131. }
  132. /* Add this module. */
  133. mod = (struct mod_list *) xmalloc (sizeof (*mod));
  134. mod->name = mod_name;
  135. mod->next = *mod_head;
  136. *mod_head = mod;
  137. /* Add this path. */
  138. path = (struct grub_util_path_list *) xmalloc (sizeof (*path));
  139. path->name = grub_util_get_module_path (dir, name);
  140. path->next = *path_head;
  141. *path_head = path;
  142. }
  143. struct grub_util_path_list *
  144. grub_util_resolve_dependencies (const char *prefix,
  145. const char *dep_list_file,
  146. char *modules[])
  147. {
  148. char *path;
  149. FILE *fp;
  150. struct dep_list *dep_list;
  151. struct mod_list *mod_list = 0;
  152. struct grub_util_path_list *path_list = 0;
  153. path = grub_util_get_path (prefix, dep_list_file);
  154. fp = fopen (path, "r");
  155. if (! fp)
  156. grub_util_error ("cannot open %s", path);
  157. free (path);
  158. dep_list = read_dep_list (fp);
  159. fclose (fp);
  160. while (*modules)
  161. {
  162. add_module (prefix, dep_list, &mod_list, &path_list, *modules);
  163. modules++;
  164. }
  165. free_dep_list (dep_list);
  166. free_mod_list (mod_list);
  167. { /* Reverse the path_list */
  168. struct grub_util_path_list *p, *prev, *next;
  169. for (p = path_list, prev = NULL; p; p = next)
  170. {
  171. next = p->next;
  172. p->next = prev;
  173. prev = p;
  174. }
  175. return prev;
  176. }
  177. }