parttool.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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/env.h>
  26. #include <grub/lib.h>
  27. #include <grub/device.h>
  28. #include <grub/disk.h>
  29. #include <grub/partition.h>
  30. #include <grub/parttool.h>
  31. #include <grub/command.h>
  32. #include <grub/i18n.h>
  33. GRUB_EXPORT(grub_parttool_reg);
  34. GRUB_EXPORT(grub_parttool_unregister);
  35. static struct grub_parttool *parts = 0;
  36. static int curhandle = 0;
  37. static grub_dl_t mymod;
  38. static char helpmsg[] =
  39. "Perform COMMANDS on partition.\n"
  40. "Use \"parttool PARTITION help\" for the list "
  41. "of available commands.";
  42. int
  43. grub_parttool_reg (const char *part_name,
  44. const grub_parttool_function_t func,
  45. const struct grub_parttool_argdesc *args)
  46. {
  47. struct grub_parttool *cur;
  48. int nargs = 0;
  49. if (! parts)
  50. grub_dl_ref (mymod);
  51. cur = (struct grub_parttool *) grub_malloc (sizeof (struct grub_parttool));
  52. cur->next = parts;
  53. cur->name = grub_strdup (part_name);
  54. cur->handle = curhandle++;
  55. for (nargs = 0; args[nargs].name != 0; nargs++);
  56. cur->nargs = nargs;
  57. cur->args = (struct grub_parttool_argdesc *)
  58. grub_malloc ((nargs + 1) * sizeof (struct grub_parttool_argdesc));
  59. grub_memcpy (cur->args, args,
  60. (nargs + 1) * sizeof (struct grub_parttool_argdesc));
  61. cur->func = func;
  62. parts = cur;
  63. return cur->handle;
  64. }
  65. void
  66. grub_parttool_unregister (int handle)
  67. {
  68. struct grub_parttool *prev = 0, *cur, *t;
  69. for (cur = parts; cur; )
  70. if (cur->handle == handle)
  71. {
  72. grub_free (cur->args);
  73. grub_free (cur->name);
  74. if (prev)
  75. prev->next = cur->next;
  76. else
  77. parts = cur->next;
  78. t = cur;
  79. cur = cur->next;
  80. grub_free (t);
  81. }
  82. else
  83. {
  84. prev = cur;
  85. cur = cur->next;
  86. }
  87. if (! parts)
  88. grub_dl_unref (mymod);
  89. }
  90. static grub_err_t
  91. show_help (grub_device_t dev)
  92. {
  93. struct grub_parttool *cur;
  94. int found = 0;
  95. for (cur = parts; cur; cur = cur->next)
  96. if (grub_strcmp (dev->disk->partition->partmap->name, cur->name) == 0)
  97. {
  98. struct grub_parttool_argdesc *curarg;
  99. found = 1;
  100. for (curarg = cur->args; curarg->name; curarg++)
  101. {
  102. int spacing = 20;
  103. spacing -= grub_strlen (curarg->name);
  104. grub_printf ("%s", curarg->name);
  105. switch (curarg->type)
  106. {
  107. case GRUB_PARTTOOL_ARG_BOOL:
  108. grub_printf ("+/-");
  109. spacing -= 3;
  110. break;
  111. case GRUB_PARTTOOL_ARG_VAL:
  112. grub_printf ("=VAL");
  113. spacing -= 4;
  114. break;
  115. case GRUB_PARTTOOL_ARG_END:
  116. break;
  117. }
  118. while (spacing-- > 0)
  119. grub_printf (" ");
  120. grub_printf ("%s\n", curarg->desc);
  121. }
  122. }
  123. if (! found)
  124. grub_printf ("Sorry no parttool is available for %s\n",
  125. dev->disk->partition->partmap->name);
  126. return GRUB_ERR_NONE;
  127. }
  128. static grub_err_t
  129. grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)),
  130. int argc, char **args)
  131. {
  132. grub_device_t dev;
  133. struct grub_parttool *cur, *ptool;
  134. int *parsed;
  135. int i, j;
  136. grub_err_t err = GRUB_ERR_NONE;
  137. if (argc < 1)
  138. {
  139. grub_printf ("%s\n", helpmsg);
  140. return grub_error (GRUB_ERR_BAD_ARGUMENT, "too few arguments");
  141. }
  142. if (args[0][0] == '(' && args[0][grub_strlen (args[0]) - 1] == ')')
  143. {
  144. args[0][grub_strlen (args[0]) - 1] = 0;
  145. dev = grub_device_open (args[0] + 1);
  146. args[0][grub_strlen (args[0]) - 1] = ')';
  147. }
  148. else
  149. dev = grub_device_open (args[0]);
  150. if (! dev)
  151. return grub_errno;
  152. if (! dev->disk)
  153. {
  154. grub_device_close (dev);
  155. return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a disk");
  156. }
  157. if (! dev->disk->partition)
  158. {
  159. grub_device_close (dev);
  160. return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a partition");
  161. }
  162. /* Load modules. */
  163. #if !GRUB_NO_MODULES
  164. {
  165. const char *prefix;
  166. prefix = grub_env_get ("prefix");
  167. if (prefix)
  168. {
  169. char *filename;
  170. filename = grub_xasprintf ("%s/parttool.lst", prefix);
  171. if (filename)
  172. {
  173. grub_file_t file;
  174. file = grub_file_open (filename);
  175. if (file)
  176. {
  177. char *buf = 0;
  178. for (;; grub_free(buf))
  179. {
  180. char *p, *name;
  181. buf = grub_getline (file);
  182. if (! buf)
  183. break;
  184. name = buf;
  185. if (! grub_isgraph (name[0]))
  186. continue;
  187. p = grub_strchr (name, ':');
  188. if (! p)
  189. continue;
  190. *p = '\0';
  191. while (*++p == ' ')
  192. ;
  193. if (! grub_isgraph (*p))
  194. continue;
  195. if (grub_strcmp (name, dev->disk->partition->partmap->name)
  196. != 0)
  197. continue;
  198. grub_dl_load (p);
  199. }
  200. grub_file_close (file);
  201. }
  202. grub_free (filename);
  203. }
  204. }
  205. /* Ignore errors. */
  206. grub_errno = GRUB_ERR_NONE;
  207. }
  208. #endif
  209. if (argc == 1)
  210. return show_help (dev);
  211. for (i = 1; i < argc; i++)
  212. if (grub_strcmp (args[i], "help") == 0)
  213. return show_help (dev);
  214. parsed = (int *) grub_zalloc (argc * sizeof (int));
  215. for (i = 1; i < argc; i++)
  216. if (! parsed[i])
  217. {
  218. struct grub_parttool_argdesc *curarg;
  219. struct grub_parttool_args *pargs;
  220. for (cur = parts; cur; cur = cur->next)
  221. if (grub_strcmp (dev->disk->partition->partmap->name, cur->name) == 0)
  222. {
  223. for (curarg = cur->args; curarg->name; curarg++)
  224. if (grub_strncmp (curarg->name, args[i],
  225. grub_strlen (curarg->name)) == 0
  226. && ((curarg->type == GRUB_PARTTOOL_ARG_BOOL
  227. && (args[i][grub_strlen (curarg->name)] == '+'
  228. || args[i][grub_strlen (curarg->name)] == '-'
  229. || args[i][grub_strlen (curarg->name)] == 0))
  230. || (curarg->type == GRUB_PARTTOOL_ARG_VAL
  231. && args[i][grub_strlen (curarg->name)] == '=')))
  232. break;
  233. if (curarg->name)
  234. break;
  235. }
  236. if (! cur)
  237. return grub_error (GRUB_ERR_BAD_ARGUMENT, "unrecognised argument %s",
  238. args[i]);
  239. ptool = cur;
  240. pargs = (struct grub_parttool_args *)
  241. grub_zalloc (ptool->nargs * sizeof (struct grub_parttool_args));
  242. for (j = i; j < argc; j++)
  243. if (! parsed[j])
  244. {
  245. for (curarg = ptool->args; curarg->name; curarg++)
  246. if (grub_strncmp (curarg->name, args[i],
  247. grub_strlen (curarg->name)) == 0
  248. && ((curarg->type == GRUB_PARTTOOL_ARG_BOOL
  249. && (args[j][grub_strlen (curarg->name)] == '+'
  250. || args[j][grub_strlen (curarg->name)] == '-'
  251. || args[j][grub_strlen (curarg->name)] == 0))
  252. || (curarg->type == GRUB_PARTTOOL_ARG_VAL
  253. && args[j][grub_strlen (curarg->name)] == '=')))
  254. {
  255. parsed[j] = 1;
  256. pargs[curarg - ptool->args].set = 1;
  257. switch (curarg->type)
  258. {
  259. case GRUB_PARTTOOL_ARG_BOOL:
  260. pargs[curarg - ptool->args].bool
  261. = (args[j][grub_strlen (curarg->name)] != '-');
  262. break;
  263. case GRUB_PARTTOOL_ARG_VAL:
  264. pargs[curarg - ptool->args].str
  265. = (args[j] + grub_strlen (curarg->name) + 1);
  266. break;
  267. case GRUB_PARTTOOL_ARG_END:
  268. break;
  269. }
  270. }
  271. }
  272. err = ptool->func (dev, pargs);
  273. grub_free (pargs);
  274. if (err)
  275. break;
  276. }
  277. grub_free (parsed);
  278. grub_device_close (dev);
  279. return err;
  280. }
  281. static grub_command_t cmd;
  282. GRUB_MOD_INIT(parttool)
  283. {
  284. mymod = mod;
  285. cmd = grub_register_command ("parttool", grub_cmd_parttool,
  286. N_("PARTITION COMMANDS"),
  287. helpmsg);
  288. }
  289. GRUB_MOD_FINI(parttool)
  290. {
  291. grub_unregister_command (cmd);
  292. }