parttool.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /* parttool.c - common dispatcher and parser for partition operations */
  2. /*
  3. * GRUB -- GRand Unified Bootloader
  4. * Copyright (C) 2009 Free Software Foundation, Inc.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20. #include <grub/types.h>
  21. #include <grub/misc.h>
  22. #include <grub/mm.h>
  23. #include <grub/err.h>
  24. #include <grub/dl.h>
  25. #include <grub/normal.h>
  26. #include <grub/device.h>
  27. #include <grub/disk.h>
  28. #include <grub/partition.h>
  29. #include <grub/parttool.h>
  30. #include <grub/command.h>
  31. #include <grub/i18n.h>
  32. GRUB_MOD_LICENSE ("GPLv2+");
  33. static struct grub_parttool *parts = 0;
  34. static int curhandle = 0;
  35. static grub_dl_t mymod;
  36. static char helpmsg[] =
  37. N_("Perform COMMANDS on partition.\n"
  38. "Use `parttool PARTITION help' for the list "
  39. "of available commands.");
  40. int
  41. grub_parttool_register(const char *part_name,
  42. const grub_parttool_function_t func,
  43. const struct grub_parttool_argdesc *args)
  44. {
  45. struct grub_parttool *cur;
  46. int nargs = 0;
  47. if (! parts)
  48. grub_dl_ref (mymod);
  49. cur = (struct grub_parttool *) grub_malloc (sizeof (struct grub_parttool));
  50. cur->next = parts;
  51. cur->name = grub_strdup (part_name);
  52. cur->handle = curhandle++;
  53. for (nargs = 0; args[nargs].name != 0; nargs++);
  54. cur->nargs = nargs;
  55. cur->args = (struct grub_parttool_argdesc *)
  56. grub_calloc (nargs + 1, sizeof (struct grub_parttool_argdesc));
  57. if (!cur->args)
  58. {
  59. grub_free (cur);
  60. curhandle--;
  61. return -1;
  62. }
  63. grub_memcpy (cur->args, args,
  64. (nargs + 1) * sizeof (struct grub_parttool_argdesc));
  65. cur->func = func;
  66. parts = cur;
  67. return cur->handle;
  68. }
  69. void
  70. grub_parttool_unregister (int handle)
  71. {
  72. struct grub_parttool *prev = 0, *cur, *t;
  73. for (cur = parts; cur; )
  74. if (cur->handle == handle)
  75. {
  76. grub_free (cur->args);
  77. grub_free (cur->name);
  78. if (prev)
  79. prev->next = cur->next;
  80. else
  81. parts = cur->next;
  82. t = cur;
  83. cur = cur->next;
  84. grub_free (t);
  85. }
  86. else
  87. {
  88. prev = cur;
  89. cur = cur->next;
  90. }
  91. if (! parts)
  92. grub_dl_unref (mymod);
  93. }
  94. static grub_err_t
  95. show_help (grub_device_t dev)
  96. {
  97. int found = 0;
  98. struct grub_parttool *cur;
  99. for (cur = parts; cur; cur = cur->next)
  100. if (grub_strcmp (dev->disk->partition->partmap->name, cur->name) == 0)
  101. {
  102. struct grub_parttool_argdesc *curarg;
  103. found = 1;
  104. for (curarg = cur->args; curarg->name; curarg++)
  105. {
  106. int spacing = 20;
  107. spacing -= grub_strlen (curarg->name);
  108. grub_printf ("%s", curarg->name);
  109. switch (curarg->type)
  110. {
  111. case GRUB_PARTTOOL_ARG_BOOL:
  112. grub_printf ("+/-");
  113. spacing -= 3;
  114. break;
  115. case GRUB_PARTTOOL_ARG_VAL:
  116. grub_xputs (_("=VAL"));
  117. spacing -= 4;
  118. break;
  119. case GRUB_PARTTOOL_ARG_END:
  120. break;
  121. }
  122. while (spacing-- > 0)
  123. grub_printf (" ");
  124. grub_puts_ (curarg->desc);
  125. }
  126. }
  127. if (! found)
  128. grub_printf_ (N_("Sorry, no parttool is available for %s\n"),
  129. dev->disk->partition->partmap->name);
  130. return GRUB_ERR_NONE;
  131. }
  132. static grub_err_t
  133. grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
  134. int argc, char **args)
  135. {
  136. grub_device_t dev;
  137. struct grub_parttool *cur, *ptool;
  138. int *parsed;
  139. int i, j;
  140. grub_err_t err = GRUB_ERR_NONE;
  141. if (argc < 1)
  142. {
  143. grub_puts_ (helpmsg);
  144. return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few arguments");
  145. }
  146. if (args[0][0] == '(' && args[0][grub_strlen (args[0]) - 1] == ')')
  147. {
  148. args[0][grub_strlen (args[0]) - 1] = 0;
  149. dev = grub_device_open (args[0] + 1);
  150. args[0][grub_strlen (args[0]) - 1] = ')';
  151. }
  152. else
  153. dev = grub_device_open (args[0]);
  154. if (! dev)
  155. return grub_errno;
  156. if (! dev->disk)
  157. {
  158. grub_device_close (dev);
  159. return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a disk");
  160. }
  161. if (! dev->disk->partition)
  162. {
  163. grub_device_close (dev);
  164. return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a partition");
  165. }
  166. /* Load modules. */
  167. if (! grub_no_modules)
  168. {
  169. const char *prefix;
  170. prefix = grub_env_get ("prefix");
  171. if (prefix)
  172. {
  173. char *filename;
  174. filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM
  175. "/parttool.lst", prefix);
  176. if (filename)
  177. {
  178. grub_file_t file;
  179. file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE_LIST);
  180. if (file)
  181. {
  182. char *buf = 0;
  183. for (;; grub_free(buf))
  184. {
  185. char *p, *name;
  186. buf = grub_file_getline (file);
  187. if (! buf)
  188. break;
  189. name = buf;
  190. while (grub_isspace (name[0]))
  191. name++;
  192. if (! grub_isgraph (name[0]))
  193. continue;
  194. p = grub_strchr (name, ':');
  195. if (! p)
  196. continue;
  197. *p = '\0';
  198. p++;
  199. while (*p == ' ' || *p == '\t')
  200. p++;
  201. if (! grub_isgraph (*p))
  202. continue;
  203. if (grub_strcmp (name, dev->disk->partition->partmap->name)
  204. != 0)
  205. continue;
  206. grub_dl_load (p);
  207. }
  208. grub_file_close (file);
  209. }
  210. grub_free (filename);
  211. }
  212. }
  213. /* Ignore errors. */
  214. grub_errno = GRUB_ERR_NONE;
  215. }
  216. if (argc == 1)
  217. {
  218. err = show_help (dev);
  219. grub_device_close (dev);
  220. return err;
  221. }
  222. for (i = 1; i < argc; i++)
  223. if (grub_strcmp (args[i], "help") == 0)
  224. {
  225. err = show_help (dev);
  226. grub_device_close (dev);
  227. return err;
  228. }
  229. parsed = (int *) grub_calloc (argc, sizeof (int));
  230. for (i = 1; i < argc; i++)
  231. if (! parsed[i])
  232. {
  233. struct grub_parttool_argdesc *curarg;
  234. struct grub_parttool_args *pargs;
  235. for (cur = parts; cur; cur = cur->next)
  236. if (grub_strcmp (dev->disk->partition->partmap->name, cur->name) == 0)
  237. {
  238. for (curarg = cur->args; curarg->name; curarg++)
  239. if (grub_strncmp (curarg->name, args[i],
  240. grub_strlen (curarg->name)) == 0
  241. && ((curarg->type == GRUB_PARTTOOL_ARG_BOOL
  242. && (args[i][grub_strlen (curarg->name)] == '+'
  243. || args[i][grub_strlen (curarg->name)] == '-'
  244. || args[i][grub_strlen (curarg->name)] == 0))
  245. || (curarg->type == GRUB_PARTTOOL_ARG_VAL
  246. && args[i][grub_strlen (curarg->name)] == '=')))
  247. break;
  248. if (curarg->name)
  249. break;
  250. }
  251. if (! cur)
  252. {
  253. grub_free (parsed);
  254. grub_device_close (dev);
  255. return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"),
  256. args[i]);
  257. }
  258. ptool = cur;
  259. pargs = (struct grub_parttool_args *)
  260. grub_calloc (ptool->nargs, sizeof (struct grub_parttool_args));
  261. for (j = i; j < argc; j++)
  262. if (! parsed[j])
  263. {
  264. for (curarg = ptool->args; curarg->name; curarg++)
  265. if (grub_strncmp (curarg->name, args[j],
  266. grub_strlen (curarg->name)) == 0
  267. && ((curarg->type == GRUB_PARTTOOL_ARG_BOOL
  268. && (args[j][grub_strlen (curarg->name)] == '+'
  269. || args[j][grub_strlen (curarg->name)] == '-'
  270. || args[j][grub_strlen (curarg->name)] == 0))
  271. || (curarg->type == GRUB_PARTTOOL_ARG_VAL
  272. && args[j][grub_strlen (curarg->name)] == '=')))
  273. {
  274. parsed[j] = 1;
  275. pargs[curarg - ptool->args].set = 1;
  276. switch (curarg->type)
  277. {
  278. case GRUB_PARTTOOL_ARG_BOOL:
  279. pargs[curarg - ptool->args].b
  280. = (args[j][grub_strlen (curarg->name)] != '-');
  281. break;
  282. case GRUB_PARTTOOL_ARG_VAL:
  283. pargs[curarg - ptool->args].str
  284. = (args[j] + grub_strlen (curarg->name) + 1);
  285. break;
  286. case GRUB_PARTTOOL_ARG_END:
  287. break;
  288. }
  289. }
  290. }
  291. err = ptool->func (dev, pargs);
  292. grub_free (pargs);
  293. if (err)
  294. break;
  295. }
  296. grub_free (parsed);
  297. grub_device_close (dev);
  298. return err;
  299. }
  300. static grub_command_t cmd;
  301. GRUB_MOD_INIT(parttool)
  302. {
  303. mymod = mod;
  304. cmd = grub_register_command ("parttool", grub_cmd_parttool,
  305. N_("PARTITION COMMANDS"),
  306. helpmsg);
  307. }
  308. GRUB_MOD_FINI(parttool)
  309. {
  310. grub_unregister_command (cmd);
  311. }