getroot.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 1999,2000,2001,2002,2003,2006,2007,2008,2009,2010,2011,2012,2013 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 <config-util.h>
  19. #include <config.h>
  20. #include <sys/stat.h>
  21. #include <sys/types.h>
  22. #include <assert.h>
  23. #include <fcntl.h>
  24. #include <unistd.h>
  25. #include <string.h>
  26. #include <dirent.h>
  27. #include <errno.h>
  28. #include <error.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <stdint.h>
  32. #ifdef HAVE_LIMITS_H
  33. #include <limits.h>
  34. #endif
  35. #include <grub/types.h>
  36. #include <grub/util/misc.h>
  37. #include <grub/mm.h>
  38. #include <grub/misc.h>
  39. #include <grub/emu/misc.h>
  40. #include <grub/emu/hostdisk.h>
  41. #include <grub/emu/getroot.h>
  42. #include <sys/wait.h>
  43. #include <hurd.h>
  44. #include <hurd/lookup.h>
  45. #include <hurd/fs.h>
  46. #include <sys/mman.h>
  47. static char *
  48. grub_util_find_hurd_root_device (const char *path)
  49. {
  50. file_t file;
  51. error_t err;
  52. char *argz = NULL, *name = NULL, *ret;
  53. size_t argz_len = 0;
  54. int i;
  55. file = file_name_lookup (path, 0, 0);
  56. if (file == MACH_PORT_NULL)
  57. /* TRANSLATORS: The first %s is the file being looked at, the second %s is
  58. the error message. */
  59. grub_util_error (_("cannot open `%s': %s"), path, strerror (errno));
  60. /* This returns catenated 0-terminated strings. */
  61. err = file_get_fs_options (file, &argz, &argz_len);
  62. if (err)
  63. /* TRANSLATORS: On GNU/Hurd, a "translator" is similar to a filesystem
  64. mount, but handled by a userland daemon, whose invocation command line
  65. is being fetched here. First %s is the file being looked at (for which
  66. we are fetching the "translator" command line), second %s is the error
  67. message.
  68. */
  69. grub_util_error (_("cannot get translator command line "
  70. "for path `%s': %s"), path, strerror(err));
  71. if (argz_len == 0)
  72. grub_util_error (_("translator command line is empty for path `%s'"), path);
  73. /* Make sure the string is terminated. */
  74. argz[argz_len-1] = 0;
  75. /* Skip first word (translator path) and options. */
  76. for (i = strlen (argz) + 1; i < argz_len; i += strlen (argz + i) + 1)
  77. {
  78. if (argz[i] != '-')
  79. {
  80. /* Non-option. Only accept one, assumed to be the FS path. */
  81. /* XXX: this should be replaced by an RPC to the translator. */
  82. if (name)
  83. /* TRANSLATORS: we expect to get something like
  84. /hurd/foobar --option1 --option2=baz /dev/something
  85. */
  86. grub_util_error (_("translator `%s' for path `%s' has several "
  87. "non-option words, at least `%s' and `%s'"),
  88. argz, path, name, argz + i);
  89. name = argz + i;
  90. }
  91. }
  92. if (!name)
  93. /* TRANSLATORS: we expect to get something like
  94. /hurd/foobar --option1 --option2=baz /dev/something
  95. */
  96. grub_util_error (_("translator `%s' for path `%s' is given only options, "
  97. "cannot find device part"), argz, path);
  98. int part = -1;
  99. if (strncmp (name, "part:", sizeof ("part:") - 1) == 0)
  100. {
  101. char *next = strchr (name + sizeof ("part:") - 1, ':');
  102. if (next)
  103. {
  104. part = atoi (name + sizeof ("part:") - 1);
  105. name = next + 1;
  106. }
  107. }
  108. if (strncmp (name, "device:", sizeof ("device:") - 1) == 0)
  109. {
  110. char *dev_name = name + sizeof ("device:") - 1;
  111. if (dev_name[0] == '@')
  112. {
  113. /*
  114. * Non-bootstrap disk driver, the /dev/ entry is normally set up with
  115. * the same @.
  116. */
  117. char *next_name = strchr (dev_name, ':');
  118. if (next_name)
  119. dev_name = next_name + 1;
  120. }
  121. if (part >= 0)
  122. ret = xasprintf("/dev/%ss%u", dev_name, part);
  123. else
  124. ret = xasprintf("/dev/%s", dev_name);
  125. }
  126. else if (!strncmp (name, "file:", sizeof ("file:") - 1))
  127. ret = strdup (name + sizeof ("file:") - 1);
  128. else
  129. ret = strdup (name);
  130. munmap (argz, argz_len);
  131. return ret;
  132. }
  133. static int
  134. is_fulldisk (const char *child, const char *parent)
  135. {
  136. if (strcmp (parent, child) == 0)
  137. return 1;
  138. if (strncmp (parent, "/dev/", sizeof ("/dev/") - 1) == 0
  139. && child[0] !=0 && strcmp (parent + sizeof ("/dev/") - 1, child) == 0)
  140. return 1;
  141. if (strncmp (child, "/dev/", sizeof ("/dev/") - 1) == 0
  142. && parent[0] != 0 && strcmp (child + sizeof ("/dev/") - 1, parent) == 0)
  143. return 1;
  144. return 0;
  145. }
  146. char *
  147. grub_util_part_to_disk (const char *os_dev,
  148. struct stat *st,
  149. int *is_part)
  150. {
  151. char *path;
  152. grub_disk_addr_t offset;
  153. char *p;
  154. if (! S_ISBLK (st->st_mode))
  155. {
  156. *is_part = 0;
  157. return xstrdup (os_dev);
  158. }
  159. if (!grub_util_hurd_get_disk_info (os_dev, NULL, &offset, NULL, &path))
  160. return xstrdup (os_dev);
  161. /* Some versions of Hurd use badly glued Linux code to handle partitions
  162. resulting in partitions being promoted to disks. */
  163. if (path && !(offset == 0 && is_fulldisk (path, os_dev)
  164. && (strncmp ("/dev/sd", os_dev, 7) == 0
  165. || strncmp ("/dev/hd", os_dev, 7) == 0)))
  166. {
  167. *is_part = !is_fulldisk (path, os_dev);
  168. if (path[0] != '/')
  169. {
  170. char *n = xasprintf ("/dev/%s", path);
  171. free (path);
  172. path = n;
  173. }
  174. return path;
  175. }
  176. free (path);
  177. path = xstrdup (os_dev);
  178. p = strchr (path + 7, 's');
  179. if (p)
  180. {
  181. *is_part = 1;
  182. *p = '\0';
  183. }
  184. return path;
  185. }
  186. enum grub_dev_abstraction_types
  187. grub_util_get_dev_abstraction_os (const char *os_dev __attribute__((unused)))
  188. {
  189. return GRUB_DEV_ABSTRACTION_NONE;
  190. }
  191. int
  192. grub_util_pull_device_os (const char *os_dev __attribute__ ((unused)),
  193. enum grub_dev_abstraction_types ab __attribute__ ((unused)))
  194. {
  195. return 0;
  196. }
  197. char *
  198. grub_util_get_grub_dev_os (const char *os_dev __attribute__ ((unused)))
  199. {
  200. return NULL;
  201. }
  202. grub_disk_addr_t
  203. grub_util_find_partition_start_os (const char *dev)
  204. {
  205. grub_uint32_t secsize;
  206. grub_disk_addr_t offset;
  207. char *path;
  208. if (!grub_util_hurd_get_disk_info (dev, &secsize, &offset, NULL, &path))
  209. return 0;
  210. if (path && !(offset == 0 && is_fulldisk (path, dev)
  211. && (strncmp ("/dev/sd", dev, 7) == 0
  212. || strncmp ("/dev/hd", dev, 7) == 0)))
  213. {
  214. free (path);
  215. return (secsize / 512) * offset;
  216. }
  217. free (path);
  218. return -1;
  219. }
  220. char **
  221. grub_guess_root_devices (const char *dir)
  222. {
  223. char **os_dev = NULL;
  224. os_dev = xmalloc (2 * sizeof (os_dev[0]));
  225. /* GNU/Hurd specific function. */
  226. os_dev[0] = grub_util_find_hurd_root_device (dir);
  227. if (!os_dev[0])
  228. {
  229. free (os_dev);
  230. return 0;
  231. }
  232. os_dev[1] = 0;
  233. return os_dev;
  234. }