getroot.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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. if (strncmp (name, "device:", sizeof ("device:") - 1) == 0)
  99. {
  100. char *dev_name = name + sizeof ("device:") - 1;
  101. size_t size = sizeof ("/dev/") - 1 + strlen (dev_name) + 1;
  102. char *next;
  103. ret = malloc (size);
  104. next = stpncpy (ret, "/dev/", size);
  105. stpncpy (next, dev_name, size - (next - ret));
  106. }
  107. else if (!strncmp (name, "file:", sizeof ("file:") - 1))
  108. ret = strdup (name + sizeof ("file:") - 1);
  109. else
  110. ret = strdup (name);
  111. munmap (argz, argz_len);
  112. return ret;
  113. }
  114. static int
  115. is_fulldisk (const char *child, const char *parent)
  116. {
  117. if (strcmp (parent, child) == 0)
  118. return 1;
  119. if (strncmp (parent, "/dev/", sizeof ("/dev/") - 1) == 0
  120. && child[0] !=0 && strcmp (parent + sizeof ("/dev/") - 1, child) == 0)
  121. return 1;
  122. if (strncmp (child, "/dev/", sizeof ("/dev/") - 1) == 0
  123. && parent[0] != 0 && strcmp (child + sizeof ("/dev/") - 1, parent) == 0)
  124. return 1;
  125. return 0;
  126. }
  127. char *
  128. grub_util_part_to_disk (const char *os_dev,
  129. struct stat *st,
  130. int *is_part)
  131. {
  132. char *path;
  133. grub_disk_addr_t offset;
  134. char *p;
  135. if (! S_ISBLK (st->st_mode))
  136. {
  137. *is_part = 0;
  138. return xstrdup (os_dev);
  139. }
  140. if (!grub_util_hurd_get_disk_info (os_dev, NULL, &offset, NULL, &path))
  141. return xstrdup (os_dev);
  142. /* Some versions of Hurd use badly glued Linux code to handle partitions
  143. resulting in partitions being promoted to disks. */
  144. if (path && !(offset == 0 && is_fulldisk (path, os_dev)
  145. && (strncmp ("/dev/sd", os_dev, 7) == 0
  146. || strncmp ("/dev/hd", os_dev, 7) == 0)))
  147. {
  148. *is_part = !is_fulldisk (path, os_dev);
  149. if (path[0] != '/')
  150. {
  151. char *n = xasprintf ("/dev/%s", path);
  152. free (path);
  153. path = n;
  154. }
  155. return path;
  156. }
  157. free (path);
  158. path = xstrdup (os_dev);
  159. p = strchr (path + 7, 's');
  160. if (p)
  161. {
  162. *is_part = 1;
  163. *p = '\0';
  164. }
  165. return path;
  166. }
  167. enum grub_dev_abstraction_types
  168. grub_util_get_dev_abstraction_os (const char *os_dev __attribute__((unused)))
  169. {
  170. return GRUB_DEV_ABSTRACTION_NONE;
  171. }
  172. int
  173. grub_util_pull_device_os (const char *os_dev __attribute__ ((unused)),
  174. enum grub_dev_abstraction_types ab __attribute__ ((unused)))
  175. {
  176. return 0;
  177. }
  178. char *
  179. grub_util_get_grub_dev_os (const char *os_dev __attribute__ ((unused)))
  180. {
  181. return NULL;
  182. }
  183. grub_disk_addr_t
  184. grub_util_find_partition_start_os (const char *dev)
  185. {
  186. grub_uint32_t secsize;
  187. grub_disk_addr_t offset;
  188. char *path;
  189. if (!grub_util_hurd_get_disk_info (dev, &secsize, &offset, NULL, &path))
  190. return 0;
  191. if (path && !(offset == 0 && is_fulldisk (path, dev)
  192. && (strncmp ("/dev/sd", dev, 7) == 0
  193. || strncmp ("/dev/hd", dev, 7) == 0)))
  194. {
  195. free (path);
  196. return (secsize / 512) * offset;
  197. }
  198. free (path);
  199. return -1;
  200. }
  201. char **
  202. grub_guess_root_devices (const char *dir)
  203. {
  204. char **os_dev = NULL;
  205. os_dev = xmalloc (2 * sizeof (os_dev[0]));
  206. /* GNU/Hurd specific function. */
  207. os_dev[0] = grub_util_find_hurd_root_device (dir);
  208. if (!os_dev[0])
  209. {
  210. free (os_dev);
  211. return 0;
  212. }
  213. os_dev[1] = 0;
  214. return os_dev;
  215. }