grub-install-common.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,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.h>
  19. #include <grub/types.h>
  20. #include <grub/emu/misc.h>
  21. #include <grub/util/misc.h>
  22. #include <grub/misc.h>
  23. #include <grub/device.h>
  24. #include <grub/disk.h>
  25. #include <grub/file.h>
  26. #include <grub/fs.h>
  27. #include <grub/env.h>
  28. #include <grub/term.h>
  29. #include <grub/mm.h>
  30. #include <grub/lib/hexdump.h>
  31. #include <grub/crypto.h>
  32. #include <grub/command.h>
  33. #include <grub/i18n.h>
  34. #include <grub/zfs/zfs.h>
  35. #include <grub/util/install.h>
  36. #include <grub/util/resolve.h>
  37. #include <grub/emu/hostfile.h>
  38. #include <grub/emu/config.h>
  39. #include <grub/emu/hostfile.h>
  40. #include <stdio.h>
  41. #include <unistd.h>
  42. #include <string.h>
  43. #include <stdlib.h>
  44. #include <errno.h>
  45. #pragma GCC diagnostic ignored "-Wformat-nonliteral"
  46. char *
  47. grub_install_help_filter (int key, const char *text,
  48. void *input __attribute__ ((unused)))
  49. {
  50. switch (key)
  51. {
  52. case GRUB_INSTALL_OPTIONS_INSTALL_THEMES:
  53. return xasprintf(text, "starfield");
  54. case GRUB_INSTALL_OPTIONS_INSTALL_FONTS:
  55. return xasprintf(text, "unicode");
  56. case GRUB_INSTALL_OPTIONS_DIRECTORY:
  57. case GRUB_INSTALL_OPTIONS_DIRECTORY2:
  58. return xasprintf(text, grub_util_get_pkglibdir ());
  59. case GRUB_INSTALL_OPTIONS_LOCALE_DIRECTORY:
  60. return xasprintf(text, grub_util_get_localedir ());
  61. case GRUB_INSTALL_OPTIONS_THEMES_DIRECTORY:
  62. return grub_util_path_concat (2, grub_util_get_pkgdatadir (), "themes");
  63. default:
  64. return (char *) text;
  65. }
  66. }
  67. #pragma GCC diagnostic error "-Wformat-nonliteral"
  68. static int (*compress_func) (const char *src, const char *dest) = NULL;
  69. char *grub_install_copy_buffer;
  70. static char *dtb;
  71. int
  72. grub_install_copy_file (const char *src,
  73. const char *dst,
  74. int is_needed)
  75. {
  76. grub_util_fd_t in, out;
  77. ssize_t r;
  78. grub_util_info ("copying `%s' -> `%s'", src, dst);
  79. in = grub_util_fd_open (src, GRUB_UTIL_FD_O_RDONLY);
  80. if (!GRUB_UTIL_FD_IS_VALID (in))
  81. {
  82. if (is_needed)
  83. grub_util_error (_("cannot open `%s': %s"), src, grub_util_fd_strerror ());
  84. else
  85. grub_util_info (_("cannot open `%s': %s"), src, grub_util_fd_strerror ());
  86. return 0;
  87. }
  88. out = grub_util_fd_open (dst, GRUB_UTIL_FD_O_WRONLY
  89. | GRUB_UTIL_FD_O_CREATTRUNC);
  90. if (!GRUB_UTIL_FD_IS_VALID (out))
  91. {
  92. grub_util_error (_("cannot open `%s': %s"), dst,
  93. grub_util_fd_strerror ());
  94. grub_util_fd_close (in);
  95. return 0;
  96. }
  97. if (!grub_install_copy_buffer)
  98. grub_install_copy_buffer = xmalloc (GRUB_INSTALL_COPY_BUFFER_SIZE);
  99. while (1)
  100. {
  101. r = grub_util_fd_read (in, grub_install_copy_buffer, GRUB_INSTALL_COPY_BUFFER_SIZE);
  102. if (r <= 0)
  103. break;
  104. r = grub_util_fd_write (out, grub_install_copy_buffer, r);
  105. if (r <= 0)
  106. break;
  107. }
  108. if (grub_util_fd_sync (out) < 0)
  109. r = -1;
  110. if (grub_util_fd_close (in) < 0)
  111. r = -1;
  112. if (grub_util_fd_close (out) < 0)
  113. r = -1;
  114. if (r < 0)
  115. grub_util_error (_("cannot copy `%s' to `%s': %s"),
  116. src, dst, grub_util_fd_strerror ());
  117. return 1;
  118. }
  119. static int
  120. grub_install_compress_file (const char *in_name,
  121. const char *out_name,
  122. int is_needed)
  123. {
  124. int ret;
  125. if (!compress_func)
  126. ret = grub_install_copy_file (in_name, out_name, is_needed);
  127. else
  128. {
  129. grub_util_info ("compressing `%s' -> `%s'", in_name, out_name);
  130. ret = !compress_func (in_name, out_name);
  131. if (!ret && is_needed)
  132. grub_util_warn (_("can't compress `%s' to `%s'"), in_name, out_name);
  133. }
  134. if (!ret && is_needed)
  135. grub_util_error (_("cannot copy `%s' to `%s': %s"),
  136. in_name, out_name, grub_util_fd_strerror ());
  137. return ret;
  138. }
  139. static int
  140. is_path_separator (char c)
  141. {
  142. #if defined (__MINGW32__) || defined (__CYGWIN__)
  143. if (c == '\\')
  144. return 1;
  145. #endif
  146. if (c == '/')
  147. return 1;
  148. return 0;
  149. }
  150. void
  151. grub_install_mkdir_p (const char *dst)
  152. {
  153. char *t = xstrdup (dst);
  154. char *p;
  155. for (p = t; *p; p++)
  156. {
  157. if (is_path_separator (*p))
  158. {
  159. char s = *p;
  160. *p = '\0';
  161. grub_util_mkdir (t);
  162. *p = s;
  163. }
  164. }
  165. grub_util_mkdir (t);
  166. free (t);
  167. }
  168. static void
  169. clean_grub_dir (const char *di)
  170. {
  171. grub_util_fd_dir_t d;
  172. grub_util_fd_dirent_t de;
  173. d = grub_util_fd_opendir (di);
  174. if (!d)
  175. grub_util_error (_("cannot open directory `%s': %s"),
  176. di, grub_util_fd_strerror ());
  177. while ((de = grub_util_fd_readdir (d)))
  178. {
  179. const char *ext = strrchr (de->d_name, '.');
  180. if ((ext && (strcmp (ext, ".mod") == 0
  181. || strcmp (ext, ".lst") == 0
  182. || strcmp (ext, ".img") == 0
  183. || strcmp (ext, ".mo") == 0)
  184. && strcmp (de->d_name, "menu.lst") != 0)
  185. || strcmp (de->d_name, "efiemu32.o") == 0
  186. || strcmp (de->d_name, "efiemu64.o") == 0)
  187. {
  188. char *x = grub_util_path_concat (2, di, de->d_name);
  189. if (grub_util_unlink (x) < 0)
  190. grub_util_error (_("cannot delete `%s': %s"), x,
  191. grub_util_fd_strerror ());
  192. free (x);
  193. }
  194. }
  195. grub_util_fd_closedir (d);
  196. }
  197. struct install_list
  198. {
  199. int is_default;
  200. char **entries;
  201. size_t n_entries;
  202. size_t n_alloc;
  203. };
  204. struct install_list install_modules = { 1, 0, 0, 0 };
  205. struct install_list modules = { 1, 0, 0, 0 };
  206. struct install_list install_locales = { 1, 0, 0, 0 };
  207. struct install_list install_fonts = { 1, 0, 0, 0 };
  208. struct install_list install_themes = { 1, 0, 0, 0 };
  209. char *grub_install_source_directory = NULL;
  210. char *grub_install_locale_directory = NULL;
  211. char *grub_install_themes_directory = NULL;
  212. int
  213. grub_install_is_short_mbrgap_supported (void)
  214. {
  215. int i, j;
  216. static const char *whitelist[] =
  217. {
  218. "part_msdos", "biosdisk", "affs", "afs", "bfs", "archelp",
  219. "cpio", "cpio_be", "newc", "odc", "ext2", "fat", "exfat",
  220. "f2fs", "fshelp", "hfs", "hfsplus", "iso9660", "jfs", "minix",
  221. "minix2", "minix3", "minix_be", "minix2_be", "nilfs2", "ntfs",
  222. "ntfscomp", "reiserfs", "romfs", "sfs", "tar", "udf", "ufs1",
  223. "ufs1_be", "ufs2", "xfs"
  224. };
  225. for (i = 0; i < modules.n_entries; i++) {
  226. for (j = 0; j < ARRAY_SIZE (whitelist); j++)
  227. if (strcmp(modules.entries[i], whitelist[j]) == 0)
  228. break;
  229. if (j == ARRAY_SIZE (whitelist))
  230. return 0;
  231. }
  232. return 1;
  233. }
  234. void
  235. grub_install_push_module (const char *val)
  236. {
  237. modules.is_default = 0;
  238. if (modules.n_entries + 1 >= modules.n_alloc)
  239. {
  240. modules.n_alloc <<= 1;
  241. if (modules.n_alloc < 16)
  242. modules.n_alloc = 16;
  243. modules.entries = xrealloc (modules.entries,
  244. modules.n_alloc * sizeof (*modules.entries));
  245. }
  246. modules.entries[modules.n_entries++] = xstrdup (val);
  247. modules.entries[modules.n_entries] = NULL;
  248. }
  249. void
  250. grub_install_pop_module (void)
  251. {
  252. modules.n_entries--;
  253. free (modules.entries[modules.n_entries]);
  254. modules.entries[modules.n_entries] = NULL;
  255. }
  256. static void
  257. handle_install_list (struct install_list *il, const char *val,
  258. int default_all)
  259. {
  260. const char *ptr;
  261. char **ce;
  262. il->is_default = 0;
  263. free (il->entries);
  264. il->entries = NULL;
  265. il->n_entries = 0;
  266. if (strcmp (val, "all") == 0 && default_all)
  267. {
  268. il->is_default = 1;
  269. return;
  270. }
  271. ptr = val;
  272. while (1)
  273. {
  274. while (*ptr && grub_isspace (*ptr))
  275. ptr++;
  276. if (!*ptr)
  277. break;
  278. while (*ptr && !grub_isspace (*ptr))
  279. ptr++;
  280. il->n_entries++;
  281. }
  282. il->n_alloc = il->n_entries + 1;
  283. il->entries = xcalloc (il->n_alloc, sizeof (il->entries[0]));
  284. ptr = val;
  285. for (ce = il->entries; ; ce++)
  286. {
  287. const char *bptr;
  288. while (*ptr && grub_isspace (*ptr))
  289. ptr++;
  290. if (!*ptr)
  291. break;
  292. bptr = ptr;
  293. while (*ptr && !grub_isspace (*ptr))
  294. ptr++;
  295. *ce = xmalloc (ptr - bptr + 1);
  296. memcpy (*ce, bptr, ptr - bptr);
  297. (*ce)[ptr - bptr] = '\0';
  298. }
  299. *ce = NULL;
  300. }
  301. static char **pubkeys;
  302. static size_t npubkeys;
  303. static char *sbat;
  304. static int disable_shim_lock;
  305. static grub_compression_t compression;
  306. int
  307. grub_install_parse (int key, char *arg)
  308. {
  309. switch (key)
  310. {
  311. case 'C':
  312. if (grub_strcmp (arg, "xz") == 0)
  313. {
  314. #ifdef HAVE_LIBLZMA
  315. compression = GRUB_COMPRESSION_XZ;
  316. #else
  317. grub_util_error ("%s",
  318. _("grub-mkimage is compiled without XZ support"));
  319. #endif
  320. }
  321. else if (grub_strcmp (arg, "none") == 0)
  322. compression = GRUB_COMPRESSION_NONE;
  323. else if (grub_strcmp (arg, "auto") == 0)
  324. compression = GRUB_COMPRESSION_AUTO;
  325. else
  326. grub_util_error (_("Unknown compression format %s"), arg);
  327. return 1;
  328. case 'k':
  329. pubkeys = xrealloc (pubkeys,
  330. sizeof (pubkeys[0])
  331. * (npubkeys + 1));
  332. pubkeys[npubkeys++] = xstrdup (arg);
  333. return 1;
  334. case GRUB_INSTALL_OPTIONS_SBAT:
  335. if (sbat)
  336. free (sbat);
  337. sbat = xstrdup (arg);
  338. return 1;
  339. case GRUB_INSTALL_OPTIONS_DISABLE_SHIM_LOCK:
  340. disable_shim_lock = 1;
  341. return 1;
  342. case GRUB_INSTALL_OPTIONS_VERBOSITY:
  343. verbosity++;
  344. return 1;
  345. case GRUB_INSTALL_OPTIONS_DIRECTORY:
  346. case GRUB_INSTALL_OPTIONS_DIRECTORY2:
  347. free (grub_install_source_directory);
  348. grub_install_source_directory = xstrdup (arg);
  349. return 1;
  350. case GRUB_INSTALL_OPTIONS_LOCALE_DIRECTORY:
  351. free (grub_install_locale_directory);
  352. grub_install_locale_directory = xstrdup (arg);
  353. return 1;
  354. case GRUB_INSTALL_OPTIONS_THEMES_DIRECTORY:
  355. free (grub_install_themes_directory);
  356. grub_install_themes_directory = xstrdup (arg);
  357. return 1;
  358. case GRUB_INSTALL_OPTIONS_INSTALL_MODULES:
  359. handle_install_list (&install_modules, arg, 0);
  360. return 1;
  361. case GRUB_INSTALL_OPTIONS_MODULES:
  362. handle_install_list (&modules, arg, 0);
  363. return 1;
  364. case GRUB_INSTALL_OPTIONS_INSTALL_LOCALES:
  365. handle_install_list (&install_locales, arg, 0);
  366. return 1;
  367. case GRUB_INSTALL_OPTIONS_INSTALL_THEMES:
  368. handle_install_list (&install_themes, arg, 0);
  369. return 1;
  370. case GRUB_INSTALL_OPTIONS_INSTALL_FONTS:
  371. handle_install_list (&install_fonts, arg, 0);
  372. return 1;
  373. case GRUB_INSTALL_OPTIONS_DTB:
  374. if (dtb)
  375. free (dtb);
  376. dtb = xstrdup (arg);
  377. return 1;
  378. case GRUB_INSTALL_OPTIONS_INSTALL_COMPRESS:
  379. if (strcmp (arg, "no") == 0
  380. || strcmp (arg, "none") == 0)
  381. {
  382. compress_func = NULL;
  383. return 1;
  384. }
  385. if (strcmp (arg, "gz") == 0)
  386. {
  387. compress_func = grub_install_compress_gzip;
  388. return 1;
  389. }
  390. if (strcmp (arg, "xz") == 0)
  391. {
  392. compress_func = grub_install_compress_xz;
  393. return 1;
  394. }
  395. if (strcmp (arg, "lzo") == 0)
  396. {
  397. compress_func = grub_install_compress_lzop;
  398. return 1;
  399. }
  400. grub_util_error (_("Unrecognized compression `%s'"), arg);
  401. case GRUB_INSTALL_OPTIONS_GRUB_MKIMAGE:
  402. return 1;
  403. default:
  404. return 0;
  405. }
  406. }
  407. static int
  408. decompressors (void)
  409. {
  410. if (compress_func == grub_install_compress_gzip)
  411. {
  412. grub_install_push_module ("gzio");
  413. return 1;
  414. }
  415. if (compress_func == grub_install_compress_xz)
  416. {
  417. grub_install_push_module ("xzio");
  418. grub_install_push_module ("gcry_crc");
  419. return 2;
  420. }
  421. if (compress_func == grub_install_compress_lzop)
  422. {
  423. grub_install_push_module ("lzopio");
  424. grub_install_push_module ("adler32");
  425. grub_install_push_module ("gcry_crc");
  426. return 3;
  427. }
  428. return 0;
  429. }
  430. void
  431. grub_install_make_image_wrap_file (const char *dir, const char *prefix,
  432. FILE *fp, const char *outname,
  433. char *memdisk_path,
  434. char *config_path,
  435. const char *mkimage_target, int note)
  436. {
  437. const struct grub_install_image_target_desc *tgt;
  438. const char *const compnames[] =
  439. {
  440. [GRUB_COMPRESSION_AUTO] = "auto",
  441. [GRUB_COMPRESSION_NONE] = "none",
  442. [GRUB_COMPRESSION_XZ] = "xz",
  443. [GRUB_COMPRESSION_LZMA] = "lzma",
  444. };
  445. grub_size_t slen = 1;
  446. char *s, *p;
  447. char **pk, **md;
  448. int dc = decompressors ();
  449. if (memdisk_path)
  450. slen += 20 + grub_strlen (memdisk_path);
  451. if (config_path)
  452. slen += 20 + grub_strlen (config_path);
  453. for (pk = pubkeys; pk < pubkeys + npubkeys; pk++)
  454. slen += 20 + grub_strlen (*pk);
  455. for (md = modules.entries; *md; md++)
  456. {
  457. slen += 10 + grub_strlen (*md);
  458. }
  459. p = s = xmalloc (slen);
  460. if (memdisk_path)
  461. {
  462. p = grub_stpcpy (p, "--memdisk '");
  463. p = grub_stpcpy (p, memdisk_path);
  464. *p++ = '\'';
  465. *p++ = ' ';
  466. }
  467. if (config_path)
  468. {
  469. p = grub_stpcpy (p, "--config '");
  470. p = grub_stpcpy (p, config_path);
  471. *p++ = '\'';
  472. *p++ = ' ';
  473. }
  474. for (pk = pubkeys; pk < pubkeys + npubkeys; pk++)
  475. {
  476. p = grub_stpcpy (p, "--pubkey '");
  477. p = grub_stpcpy (p, *pk);
  478. *p++ = '\'';
  479. *p++ = ' ';
  480. }
  481. for (md = modules.entries; *md; md++)
  482. {
  483. *p++ = '\'';
  484. p = grub_stpcpy (p, *md);
  485. *p++ = '\'';
  486. *p++ = ' ';
  487. }
  488. *p = '\0';
  489. grub_util_info ("grub-mkimage --directory '%s' --prefix '%s'"
  490. " --output '%s' "
  491. " --dtb '%s' "
  492. "--sbat '%s' "
  493. "--format '%s' --compression '%s' %s %s %s\n",
  494. dir, prefix,
  495. outname, dtb ? : "", sbat ? : "", mkimage_target,
  496. compnames[compression], note ? "--note" : "",
  497. disable_shim_lock ? "--disable-shim-lock" : "", s);
  498. free (s);
  499. tgt = grub_install_get_image_target (mkimage_target);
  500. if (!tgt)
  501. grub_util_error (_("unknown target format %s"), mkimage_target);
  502. grub_install_generate_image (dir, prefix, fp, outname,
  503. modules.entries, memdisk_path,
  504. pubkeys, npubkeys, config_path, tgt,
  505. note, compression, dtb, sbat,
  506. disable_shim_lock);
  507. while (dc--)
  508. grub_install_pop_module ();
  509. }
  510. void
  511. grub_install_make_image_wrap (const char *dir, const char *prefix,
  512. const char *outname, char *memdisk_path,
  513. char *config_path,
  514. const char *mkimage_target, int note)
  515. {
  516. FILE *fp;
  517. fp = grub_util_fopen (outname, "wb");
  518. if (! fp)
  519. grub_util_error (_("cannot open `%s': %s"), outname,
  520. strerror (errno));
  521. grub_install_make_image_wrap_file (dir, prefix, fp, outname,
  522. memdisk_path, config_path,
  523. mkimage_target, note);
  524. if (grub_util_file_sync (fp) < 0)
  525. grub_util_error (_("cannot sync `%s': %s"), outname, strerror (errno));
  526. fclose (fp);
  527. }
  528. static void
  529. copy_by_ext (const char *srcd,
  530. const char *dstd,
  531. const char *extf,
  532. int req)
  533. {
  534. grub_util_fd_dir_t d;
  535. grub_util_fd_dirent_t de;
  536. d = grub_util_fd_opendir (srcd);
  537. if (!d && !req)
  538. return;
  539. if (!d)
  540. grub_util_error (_("cannot open directory `%s': %s"),
  541. srcd, grub_util_fd_strerror ());
  542. while ((de = grub_util_fd_readdir (d)))
  543. {
  544. const char *ext = strrchr (de->d_name, '.');
  545. if (ext && strcmp (ext, extf) == 0)
  546. {
  547. char *srcf = grub_util_path_concat (2, srcd, de->d_name);
  548. char *dstf = grub_util_path_concat (2, dstd, de->d_name);
  549. grub_install_compress_file (srcf, dstf, 1);
  550. free (srcf);
  551. free (dstf);
  552. }
  553. }
  554. grub_util_fd_closedir (d);
  555. }
  556. static void
  557. copy_all (const char *srcd,
  558. const char *dstd)
  559. {
  560. grub_util_fd_dir_t d;
  561. grub_util_fd_dirent_t de;
  562. d = grub_util_fd_opendir (srcd);
  563. if (!d)
  564. grub_util_error (_("cannot open directory `%s': %s"),
  565. srcd, grub_util_fd_strerror ());
  566. while ((de = grub_util_fd_readdir (d)))
  567. {
  568. char *srcf;
  569. char *dstf;
  570. if (strcmp (de->d_name, ".") == 0
  571. || strcmp (de->d_name, "..") == 0)
  572. continue;
  573. srcf = grub_util_path_concat (2, srcd, de->d_name);
  574. if (grub_util_is_special_file (srcf)
  575. || grub_util_is_directory (srcf))
  576. continue;
  577. dstf = grub_util_path_concat (2, dstd, de->d_name);
  578. grub_install_compress_file (srcf, dstf, 1);
  579. free (srcf);
  580. free (dstf);
  581. }
  582. grub_util_fd_closedir (d);
  583. }
  584. #if (defined (GRUB_UTIL) && defined(ENABLE_NLS) && ENABLE_NLS)
  585. static const char *
  586. get_localedir (void)
  587. {
  588. if (grub_install_locale_directory)
  589. return grub_install_locale_directory;
  590. else
  591. return grub_util_get_localedir ();
  592. }
  593. static void
  594. copy_locales (const char *dstd)
  595. {
  596. grub_util_fd_dir_t d;
  597. grub_util_fd_dirent_t de;
  598. const char *locale_dir = get_localedir ();
  599. d = grub_util_fd_opendir (locale_dir);
  600. if (!d)
  601. {
  602. grub_util_warn (_("cannot open directory `%s': %s"),
  603. locale_dir, grub_util_fd_strerror ());
  604. return;
  605. }
  606. while ((de = grub_util_fd_readdir (d)))
  607. {
  608. char *srcf;
  609. char *dstf;
  610. char *ext;
  611. if (strcmp (de->d_name, ".") == 0)
  612. continue;
  613. if (strcmp (de->d_name, "..") == 0)
  614. continue;
  615. ext = grub_strrchr (de->d_name, '.');
  616. if (ext && (grub_strcmp (ext, ".mo") == 0
  617. || grub_strcmp (ext, ".gmo") == 0))
  618. {
  619. srcf = grub_util_path_concat (2, locale_dir, de->d_name);
  620. dstf = grub_util_path_concat (2, dstd, de->d_name);
  621. ext = grub_strrchr (dstf, '.');
  622. grub_strcpy (ext, ".mo");
  623. }
  624. else
  625. {
  626. srcf = grub_util_path_concat_ext (4, locale_dir, de->d_name,
  627. "LC_MESSAGES", PACKAGE, ".mo");
  628. dstf = grub_util_path_concat_ext (2, dstd, de->d_name, ".mo");
  629. }
  630. grub_install_compress_file (srcf, dstf, 0);
  631. free (srcf);
  632. free (dstf);
  633. }
  634. grub_util_fd_closedir (d);
  635. }
  636. #endif
  637. static void
  638. grub_install_copy_nls(const char *src __attribute__ ((unused)),
  639. const char *dst __attribute__ ((unused)))
  640. {
  641. #if (defined (GRUB_UTIL) && defined(ENABLE_NLS) && ENABLE_NLS)
  642. char *dst_locale;
  643. dst_locale = grub_util_path_concat (2, dst, "locale");
  644. grub_install_mkdir_p (dst_locale);
  645. clean_grub_dir (dst_locale);
  646. if (install_locales.is_default)
  647. {
  648. char *srcd = grub_util_path_concat (2, src, "po");
  649. copy_by_ext (srcd, dst_locale, ".mo", 0);
  650. copy_locales (dst_locale);
  651. free (srcd);
  652. }
  653. else
  654. {
  655. size_t i;
  656. const char *locale_dir = get_localedir ();
  657. for (i = 0; i < install_locales.n_entries; i++)
  658. {
  659. char *srcf = grub_util_path_concat_ext (3, src, "po",
  660. install_locales.entries[i],
  661. ".mo");
  662. char *dstf = grub_util_path_concat_ext (2, dst_locale,
  663. install_locales.entries[i],
  664. ".mo");
  665. if (grub_install_compress_file (srcf, dstf, 0))
  666. {
  667. free (srcf);
  668. free (dstf);
  669. continue;
  670. }
  671. free (srcf);
  672. srcf = grub_util_path_concat_ext (4, locale_dir,
  673. install_locales.entries[i],
  674. "LC_MESSAGES", PACKAGE, ".mo");
  675. if (grub_install_compress_file (srcf, dstf, 0) == 0)
  676. grub_util_error (_("cannot find locale `%s'"),
  677. install_locales.entries[i]);
  678. free (srcf);
  679. free (dstf);
  680. }
  681. }
  682. free (dst_locale);
  683. #endif
  684. }
  685. static struct
  686. {
  687. const char *cpu;
  688. const char *platform;
  689. } platforms[GRUB_INSTALL_PLATFORM_MAX] =
  690. {
  691. [GRUB_INSTALL_PLATFORM_I386_PC] = { "i386", "pc" },
  692. [GRUB_INSTALL_PLATFORM_I386_EFI] = { "i386", "efi" },
  693. [GRUB_INSTALL_PLATFORM_I386_QEMU] = { "i386", "qemu" },
  694. [GRUB_INSTALL_PLATFORM_I386_COREBOOT] = { "i386", "coreboot" },
  695. [GRUB_INSTALL_PLATFORM_I386_MULTIBOOT] = { "i386", "multiboot" },
  696. [GRUB_INSTALL_PLATFORM_I386_IEEE1275] = { "i386", "ieee1275" },
  697. [GRUB_INSTALL_PLATFORM_X86_64_EFI] = { "x86_64", "efi" },
  698. [GRUB_INSTALL_PLATFORM_I386_XEN] = { "i386", "xen" },
  699. [GRUB_INSTALL_PLATFORM_X86_64_XEN] = { "x86_64", "xen" },
  700. [GRUB_INSTALL_PLATFORM_I386_XEN_PVH] = { "i386", "xen_pvh" },
  701. [GRUB_INSTALL_PLATFORM_MIPSEL_LOONGSON] = { "mipsel", "loongson" },
  702. [GRUB_INSTALL_PLATFORM_MIPSEL_QEMU_MIPS] = { "mipsel", "qemu_mips" },
  703. [GRUB_INSTALL_PLATFORM_MIPS_QEMU_MIPS] = { "mips", "qemu_mips" },
  704. [GRUB_INSTALL_PLATFORM_MIPSEL_ARC] = { "mipsel", "arc" },
  705. [GRUB_INSTALL_PLATFORM_MIPS_ARC] = { "mips", "arc" },
  706. [GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275] = { "sparc64", "ieee1275" },
  707. [GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275] = { "powerpc", "ieee1275" },
  708. [GRUB_INSTALL_PLATFORM_IA64_EFI] = { "ia64", "efi" },
  709. [GRUB_INSTALL_PLATFORM_ARM_EFI] = { "arm", "efi" },
  710. [GRUB_INSTALL_PLATFORM_ARM64_EFI] = { "arm64", "efi" },
  711. [GRUB_INSTALL_PLATFORM_ARM_UBOOT] = { "arm", "uboot" },
  712. [GRUB_INSTALL_PLATFORM_ARM_COREBOOT] = { "arm", "coreboot" },
  713. [GRUB_INSTALL_PLATFORM_RISCV32_EFI] = { "riscv32", "efi" },
  714. [GRUB_INSTALL_PLATFORM_RISCV64_EFI] = { "riscv64", "efi" },
  715. };
  716. char *
  717. grub_install_get_platforms_string (void)
  718. {
  719. char **arr = xmalloc (sizeof (char *) * ARRAY_SIZE (platforms));
  720. int platform_strins_len = 0;
  721. char *platforms_string;
  722. char *ptr;
  723. unsigned i;
  724. for (i = 0; i < ARRAY_SIZE (platforms); i++)
  725. {
  726. arr[i] = xasprintf ("%s-%s", platforms[i].cpu,
  727. platforms[i].platform);
  728. platform_strins_len += strlen (arr[i]) + 2;
  729. }
  730. ptr = platforms_string = xmalloc (platform_strins_len);
  731. qsort (arr, ARRAY_SIZE (platforms), sizeof (char *), grub_qsort_strcmp);
  732. for (i = 0; i < ARRAY_SIZE (platforms); i++)
  733. {
  734. strcpy (ptr, arr[i]);
  735. ptr += strlen (arr[i]);
  736. *ptr++ = ',';
  737. *ptr++ = ' ';
  738. free (arr[i]);
  739. }
  740. ptr[-2] = 0;
  741. free (arr);
  742. return platforms_string;
  743. }
  744. char *
  745. grub_install_get_platform_name (enum grub_install_plat platid)
  746. {
  747. return xasprintf ("%s-%s", platforms[platid].cpu,
  748. platforms[platid].platform);
  749. }
  750. const char *
  751. grub_install_get_platform_cpu (enum grub_install_plat platid)
  752. {
  753. return platforms[platid].cpu;
  754. }
  755. const char *
  756. grub_install_get_platform_platform (enum grub_install_plat platid)
  757. {
  758. return platforms[platid].platform;
  759. }
  760. void
  761. grub_install_copy_files (const char *src,
  762. const char *dst,
  763. enum grub_install_plat platid)
  764. {
  765. char *dst_platform, *dst_fonts;
  766. const char *pkgdatadir = grub_util_get_pkgdatadir ();
  767. char *themes_dir;
  768. {
  769. char *platform;
  770. platform = xasprintf ("%s-%s", platforms[platid].cpu,
  771. platforms[platid].platform);
  772. dst_platform = grub_util_path_concat (2, dst, platform);
  773. free (platform);
  774. }
  775. dst_fonts = grub_util_path_concat (2, dst, "fonts");
  776. grub_install_mkdir_p (dst_platform);
  777. clean_grub_dir (dst);
  778. clean_grub_dir (dst_platform);
  779. grub_install_copy_nls(src, dst);
  780. if (install_modules.is_default)
  781. copy_by_ext (src, dst_platform, ".mod", 1);
  782. else
  783. {
  784. struct grub_util_path_list *path_list, *p;
  785. path_list = grub_util_resolve_dependencies (src, "moddep.lst",
  786. install_modules.entries);
  787. for (p = path_list; p; p = p->next)
  788. {
  789. const char *srcf = p->name;
  790. const char *dir;
  791. char *dstf;
  792. dir = grub_strrchr (srcf, '/');
  793. if (dir)
  794. dir++;
  795. else
  796. dir = srcf;
  797. dstf = grub_util_path_concat (2, dst_platform, dir);
  798. grub_install_compress_file (srcf, dstf, 1);
  799. free (dstf);
  800. }
  801. grub_util_free_path_list (path_list);
  802. }
  803. const char *pkglib_DATA[] = {"efiemu32.o", "efiemu64.o",
  804. "moddep.lst", "command.lst",
  805. "fs.lst", "partmap.lst",
  806. "parttool.lst",
  807. "video.lst", "crypto.lst",
  808. "terminal.lst", "modinfo.sh" };
  809. size_t i;
  810. for (i = 0; i < ARRAY_SIZE (pkglib_DATA); i++)
  811. {
  812. char *srcf = grub_util_path_concat (2, src, pkglib_DATA[i]);
  813. char *dstf = grub_util_path_concat (2, dst_platform, pkglib_DATA[i]);
  814. if (i == 0 || i == 1)
  815. grub_install_compress_file (srcf, dstf, 0);
  816. else
  817. grub_install_compress_file (srcf, dstf, 1);
  818. free (srcf);
  819. free (dstf);
  820. }
  821. if (install_themes.is_default)
  822. {
  823. install_themes.is_default = 0;
  824. install_themes.n_entries = 1;
  825. install_themes.entries = xmalloc (2 * sizeof (install_themes.entries[0]));
  826. install_themes.entries[0] = xstrdup ("starfield");
  827. install_themes.entries[1] = NULL;
  828. }
  829. if (grub_install_themes_directory)
  830. themes_dir = xstrdup (grub_install_themes_directory);
  831. else
  832. themes_dir = grub_util_path_concat (2, grub_util_get_pkgdatadir (),
  833. "themes");
  834. for (i = 0; i < install_themes.n_entries; i++)
  835. {
  836. char *srcf = grub_util_path_concat (3, themes_dir,
  837. install_themes.entries[i],
  838. "theme.txt");
  839. if (grub_util_is_regular (srcf))
  840. {
  841. char *srcd = grub_util_path_concat (2, themes_dir,
  842. install_themes.entries[i]);
  843. char *dstd = grub_util_path_concat (3, dst, "themes",
  844. install_themes.entries[i]);
  845. grub_install_mkdir_p (dstd);
  846. copy_all (srcd, dstd);
  847. free (srcd);
  848. free (dstd);
  849. }
  850. free (srcf);
  851. }
  852. free (themes_dir);
  853. if (install_fonts.is_default)
  854. {
  855. install_fonts.is_default = 0;
  856. install_fonts.n_entries = 1;
  857. install_fonts.entries = xmalloc (2 * sizeof (install_fonts.entries[0]));
  858. install_fonts.entries[0] = xstrdup ("unicode");
  859. install_fonts.entries[1] = NULL;
  860. }
  861. grub_install_mkdir_p (dst_fonts);
  862. for (i = 0; i < install_fonts.n_entries; i++)
  863. {
  864. char *srcf = grub_util_path_concat_ext (2, pkgdatadir,
  865. install_fonts.entries[i],
  866. ".pf2");
  867. char *dstf = grub_util_path_concat_ext (2, dst_fonts,
  868. install_fonts.entries[i],
  869. ".pf2");
  870. grub_install_compress_file (srcf, dstf, 0);
  871. free (srcf);
  872. free (dstf);
  873. }
  874. free (dst_platform);
  875. free (dst_fonts);
  876. }
  877. enum grub_install_plat
  878. grub_install_get_target (const char *src)
  879. {
  880. char *fn;
  881. grub_util_fd_t f;
  882. char buf[8192];
  883. ssize_t r;
  884. char *c, *pl, *p;
  885. size_t i;
  886. fn = grub_util_path_concat (2, src, "modinfo.sh");
  887. f = grub_util_fd_open (fn, GRUB_UTIL_FD_O_RDONLY);
  888. if (!GRUB_UTIL_FD_IS_VALID (f))
  889. grub_util_error (_("%s doesn't exist. Please specify --target or --directory"),
  890. fn);
  891. r = grub_util_fd_read (f, buf, sizeof (buf) - 1);
  892. if (r < 0)
  893. grub_util_error (_("cannot read `%s': %s"), fn, strerror (errno));
  894. grub_util_fd_close (f);
  895. buf[r] = '\0';
  896. c = strstr (buf, "grub_modinfo_target_cpu=");
  897. if (!c || (c != buf && !grub_isspace (*(c-1))))
  898. grub_util_error (_("invalid modinfo file `%s'"), fn);
  899. pl = strstr (buf, "grub_modinfo_platform=");
  900. if (!pl || (pl != buf && !grub_isspace (*(pl-1))))
  901. grub_util_error (_("invalid modinfo file `%s'"), fn);
  902. c += sizeof ("grub_modinfo_target_cpu=") - 1;
  903. pl += sizeof ("grub_modinfo_platform=") - 1;
  904. for (p = c; *p && !grub_isspace (*p); p++);
  905. *p = '\0';
  906. for (p = pl; *p && !grub_isspace (*p); p++);
  907. *p = '\0';
  908. for (i = 0; i < ARRAY_SIZE (platforms); i++)
  909. if (strcmp (platforms[i].cpu, c) == 0
  910. && strcmp (platforms[i].platform, pl) == 0)
  911. {
  912. free (fn);
  913. return i;
  914. }
  915. grub_util_error (_("Unknown platform `%s-%s'"), c, pl);
  916. }
  917. void
  918. grub_util_unlink_recursive (const char *name)
  919. {
  920. grub_util_fd_dir_t d;
  921. grub_util_fd_dirent_t de;
  922. d = grub_util_fd_opendir (name);
  923. while ((de = grub_util_fd_readdir (d)))
  924. {
  925. char *fp;
  926. if (strcmp (de->d_name, ".") == 0)
  927. continue;
  928. if (strcmp (de->d_name, "..") == 0)
  929. continue;
  930. fp = grub_util_path_concat (2, name, de->d_name);
  931. if (grub_util_is_special_file (fp))
  932. {
  933. free (fp);
  934. continue;
  935. }
  936. if (grub_util_is_regular (fp))
  937. grub_util_unlink (fp);
  938. else if (grub_util_is_directory (fp))
  939. grub_util_unlink_recursive (fp);
  940. free (fp);
  941. }
  942. grub_util_rmdir (name);
  943. grub_util_fd_closedir (d);
  944. }