444 * Additionally while iterating through the menu, if we have an
445 * original root dataset for a BE we're cloning from, we need to keep
446 * track of that BE's menu entry. We will then use the lines from
447 * that entry to create the entry for the new BE.
448 */
449 if ((ret = be_open_menu(be_root_pool, menu_file,
450 &menu_fp, "r", B_TRUE)) != BE_SUCCESS) {
451 goto cleanup;
452 } else if (menu_fp == NULL) {
453 ret = BE_ERR_NO_MENU;
454 goto cleanup;
455 }
456
457 free(pool_mntpnt);
458 pool_mntpnt = NULL;
459
460 while (fgets(line, BUFSIZ, menu_fp)) {
461 char *tok = NULL;
462
463 (void) strlcpy(temp_line, line, BUFSIZ);
464 tok = strtok(line, BE_WHITE_SPACE);
465
466 if (tok == NULL || tok[0] == '#') {
467 continue;
468 } else if (strcmp(tok, "title") == 0) {
469 collect_lines = B_FALSE;
470 if ((tok = strtok(NULL, "\n")) == NULL)
471 (void) strlcpy(title, "", sizeof (title));
472 else
473 (void) strlcpy(title, tok, sizeof (title));
474 found_title = B_TRUE;
475
476 if (num_tmp_lines != 0) {
477 for (i = 0; i < num_tmp_lines; i++) {
478 free(tmp_entries[i]);
479 tmp_entries[i] = NULL;
480 }
481 num_tmp_lines = 0;
482 }
483 } else if (strcmp(tok, "bootfs") == 0) {
484 char *bootfs = strtok(NULL, BE_WHITE_SPACE);
485 found_title = B_FALSE;
486 if (bootfs == NULL)
487 continue;
488
489 if (strcmp(bootfs, be_root_ds) == 0) {
490 found_be = B_TRUE;
491 break;
492 }
493
494 if (be_orig_root_ds != NULL &&
495 strcmp(bootfs, be_orig_root_ds) == 0 &&
496 !found_orig_be) {
497 char str[BUFSIZ];
498 found_orig_be = B_TRUE;
499 num_lines = 0;
500 /*
501 * Store the new title line
502 */
503 (void) snprintf(str, BUFSIZ, "title %s\n",
504 description ? description : be_name);
505 entries[num_lines] = strdup(str);
506 num_lines++;
507 /*
508 * If there are any lines between the title
509 * and the bootfs line store these. Also
510 * free the temporary lines.
511 */
512 for (i = 0; i < num_tmp_lines; i++) {
513 entries[num_lines] = tmp_entries[i];
514 tmp_entries[i] = NULL;
515 num_lines++;
516 }
517 num_tmp_lines = 0;
518 /*
519 * Store the new bootfs line.
520 */
521 (void) snprintf(str, BUFSIZ, "bootfs %s\n",
522 be_root_ds);
523 entries[num_lines] = strdup(str);
524 num_lines++;
525 collect_lines = B_TRUE;
526 }
527 } else if (found_orig_be && collect_lines) {
528 /*
529 * get the rest of the lines for the original BE and
530 * store them.
531 */
532 if (strstr(line, BE_GRUB_COMMENT) != NULL ||
533 strstr(line, "BOOTADM") != NULL)
534 continue;
535 if (strcmp(tok, "splashimage") == 0) {
536 entries[num_lines] =
537 strdup("splashimage "
538 "/boot/splashimage.xpm\n");
539 } else {
540 entries[num_lines] = strdup(temp_line);
541 }
542 num_lines++;
543 } else if (found_title && !found_orig_be) {
544 tmp_entries[num_tmp_lines] = strdup(temp_line);
545 num_tmp_lines++;
546 }
547 }
548
549 (void) fclose(menu_fp);
550
551 if (found_be) {
552 /*
553 * If an entry for this BE was already in the menu, then if
554 * that entry's title matches what we would have put in
555 * return success. Otherwise return failure.
556 */
557 char *new_title = description ? description : be_name;
558
581 goto cleanup;
582 }
583
584 if (found_orig_be) {
585 /*
586 * write out all the stored lines
587 */
588 for (i = 0; i < num_lines; i++) {
589 (void) fprintf(menu_fp, "%s", entries[i]);
590 free(entries[i]);
591 }
592 num_lines = 0;
593
594 /*
595 * Check to see if this system supports grub
596 */
597 if (be_has_grub())
598 (void) fprintf(menu_fp, "%s\n", BE_GRUB_COMMENT);
599 ret = BE_SUCCESS;
600 } else {
601 (void) fprintf(menu_fp, "title %s\n",
602 description ? description : be_name);
603 (void) fprintf(menu_fp, "bootfs %s\n", be_root_ds);
604
605 /*
606 * Check to see if this system supports grub
607 */
608 if (be_has_grub()) {
609 (void) fprintf(menu_fp, "kernel$ "
610 "/platform/i86pc/kernel/$ISADIR/unix -B "
611 "$ZFS-BOOTFS\n");
612 (void) fprintf(menu_fp, "module$ "
613 "/platform/i86pc/$ISADIR/boot_archive\n");
614 (void) fprintf(menu_fp, "%s\n", BE_GRUB_COMMENT);
615 }
616 ret = BE_SUCCESS;
617 }
618 (void) fclose(menu_fp);
619 cleanup:
620 if (pool_mounted) {
621 int err = BE_SUCCESS;
622 err = be_unmount_pool(zhp, ptmp_mntpnt, orig_mntpnt);
623 if (ret == BE_SUCCESS)
624 ret = err;
625 free(orig_mntpnt);
626 free(ptmp_mntpnt);
627 }
628 ZFS_CLOSE(zhp);
629 if (num_tmp_lines > 0) {
630 for (i = 0; i < num_tmp_lines; i++) {
631 free(tmp_entries[i]);
632 tmp_entries[i] = NULL;
772 free(tmp_menu);
773 tmp_menu = NULL;
774 goto cleanup;
775 }
776 if ((tmp_menu_fp = fdopen(fd, "w")) == NULL) {
777 err = errno;
778 be_print_err(gettext("be_remove_menu: "
779 "could not open tmp file for write: %s\n"), strerror(err));
780 (void) close(fd);
781 ret = errno_to_be_err(err);
782 goto cleanup;
783 }
784
785 while (fgets(menu_buf, BUFSIZ, menu_fp)) {
786 char tline [BUFSIZ];
787 char *tok = NULL;
788
789 (void) strlcpy(tline, menu_buf, sizeof (tline));
790
791 /* Tokenize line */
792 tok = strtok(tline, BE_WHITE_SPACE);
793
794 if (tok == NULL || tok[0] == '#') {
795 /* Found empty line or comment line */
796 if (do_buffer) {
797 /* Buffer this line */
798 if ((buffer = (char **)realloc(buffer,
799 sizeof (char *)*(nlines + 1))) == NULL) {
800 ret = BE_ERR_NOMEM;
801 goto cleanup;
802 }
803 if ((buffer[nlines++] = strdup(menu_buf))
804 == NULL) {
805 ret = BE_ERR_NOMEM;
806 goto cleanup;
807 }
808
809 } else if (write || strncmp(menu_buf, BE_GRUB_COMMENT,
810 strlen(BE_GRUB_COMMENT)) != 0) {
811 /* Write this line out */
812 (void) fputs(menu_buf, tmp_menu_fp);
813 }
814 } else if (strcmp(tok, "default") == 0) {
815 /*
816 * Record what 'default' is set to because we might
817 * need to adjust this upon deleting an entry.
818 */
819 tok = strtok(NULL, BE_WHITE_SPACE);
820
821 if (tok != NULL) {
822 default_entry = atoi(tok);
823 }
824
825 (void) fputs(menu_buf, tmp_menu_fp);
826 } else if (strcmp(tok, "title") == 0) {
827 /*
828 * If we've reached a 'title' line and do_buffer is
829 * is true, that means we've just buffered an entire
830 * entry without finding a 'bootfs' directive. We
831 * need to write that entry out and keep searching.
832 */
833 if (do_buffer) {
834 for (i = 0; i < nlines; i++) {
835 (void) fputs(buffer[i], tmp_menu_fp);
836 free(buffer[i]);
837 }
838 free(buffer);
839 buffer = NULL;
840 nlines = 0;
841 }
842
843 /*
844 * Turn writing off and buffering on, and increment
845 * our entry counter.
846 */
847 write = B_FALSE;
848 do_buffer = B_TRUE;
849 entry_cnt++;
850
851 /* Buffer this 'title' line */
852 if ((buffer = (char **)realloc(buffer,
853 sizeof (char *)*(nlines + 1))) == NULL) {
854 ret = BE_ERR_NOMEM;
855 goto cleanup;
856 }
857 if ((buffer[nlines++] = strdup(menu_buf)) == NULL) {
858 ret = BE_ERR_NOMEM;
859 goto cleanup;
860 }
861
862 } else if (strcmp(tok, "bootfs") == 0) {
863 char *bootfs = NULL;
864
865 /*
866 * Found a 'bootfs' line. See if it matches the
867 * BE we're looking for.
868 */
869 if ((bootfs = strtok(NULL, BE_WHITE_SPACE)) == NULL ||
870 strcmp(bootfs, be_root_ds) != 0) {
871 /*
872 * Either there's nothing after the 'bootfs'
873 * or this is not the BE we're looking for,
874 * write out the line(s) we've buffered since
875 * finding the title.
876 */
877 for (i = 0; i < nlines; i++) {
878 (void) fputs(buffer[i], tmp_menu_fp);
879 free(buffer[i]);
880 }
881 free(buffer);
882 buffer = NULL;
1003 tmp_menu = NULL;
1004 goto cleanup;
1005 }
1006 if ((tmp_menu_fp = fdopen(fd, "w")) == NULL) {
1007 err = errno;
1008 be_print_err(gettext("be_remove_menu: "
1009 "could not open tmp file for write: %s\n"),
1010 strerror(err));
1011 (void) close(fd);
1012 ret = errno_to_be_err(err);
1013 goto cleanup;
1014 }
1015
1016 while (fgets(menu_buf, BUFSIZ, menu_fp)) {
1017 char tline [BUFSIZ];
1018 char *tok = NULL;
1019
1020 (void) strlcpy(tline, menu_buf, sizeof (tline));
1021
1022 /* Tokenize line */
1023 tok = strtok(tline, BE_WHITE_SPACE);
1024
1025 if (tok == NULL) {
1026 /* Found empty line, write it out */
1027 (void) fputs(menu_buf, tmp_menu_fp);
1028 } else if (strcmp(tok, "default") == 0) {
1029 /* Found the default line, adjust it */
1030 (void) snprintf(tline, sizeof (tline),
1031 "default %d\n", default_entry);
1032
1033 (void) fputs(tline, tmp_menu_fp);
1034 } else {
1035 /* Pass through all other lines */
1036 (void) fputs(menu_buf, tmp_menu_fp);
1037 }
1038 }
1039
1040 (void) fclose(menu_fp);
1041 menu_fp = NULL;
1042 (void) fclose(tmp_menu_fp);
1043 tmp_menu_fp = NULL;
1044
1045 /* Copy the modified menu.lst into place */
1046 if (rename(tmp_menu, menu) != 0) {
1047 err = errno;
1048 be_print_err(gettext("be_remove_menu: "
1049 "failed to rename file %s to %s: %s\n"),
1050 tmp_menu, menu, strerror(err));
1051 ret = errno_to_be_err(err);
1170 "the default BE in the grub menu.\n"));
1171 ret = BE_ERR_NO_MENU;
1172 goto cleanup;
1173 }
1174
1175 (void) snprintf(grub_file, MAXPATHLEN, "%s%s",
1176 pool_mntpnt, BE_GRUB_MENU);
1177
1178 if ((ret = be_open_menu((char *)be_root_pool, grub_file,
1179 &menu_fp, "r", B_FALSE)) != BE_SUCCESS) {
1180 goto cleanup;
1181 } else if (menu_fp == NULL) {
1182 ret = BE_ERR_NO_MENU;
1183 goto cleanup;
1184 }
1185
1186 free(pool_mntpnt);
1187 pool_mntpnt = NULL;
1188
1189 while (fgets(line, BUFSIZ, menu_fp)) {
1190 char *tok = strtok(line, BE_WHITE_SPACE);
1191
1192 if (tok != NULL && tok[0] != '#') {
1193 if (!found_default) {
1194 if (strcmp(tok, "default") == 0) {
1195 tok = strtok(NULL, BE_WHITE_SPACE);
1196 if (tok != NULL) {
1197 default_entry = atoi(tok);
1198 rewind(menu_fp);
1199 found_default = 1;
1200 }
1201 }
1202 continue;
1203 }
1204 if (strcmp(tok, "title") == 0) {
1205 entries++;
1206 } else if (default_entry == entries - 1) {
1207 if (strcmp(tok, "bootfs") == 0) {
1208 tok = strtok(NULL, BE_WHITE_SPACE);
1209 (void) fclose(menu_fp);
1210
1211 if (tok == NULL) {
1212 ret = BE_SUCCESS;
1213 goto cleanup;
1214 }
1215
1216 if ((*def_bootfs = strdup(tok)) !=
1217 NULL) {
1218 ret = BE_SUCCESS;
1219 goto cleanup;
1220 }
1221 be_print_err(gettext(
1222 "be_default_grub_bootfs: "
1223 "memory allocation failed\n"));
1224 ret = BE_ERR_NOMEM;
1225 goto cleanup;
1226 }
1227 } else if (default_entry < entries - 1) {
1370 if ((fd = mkstemp(temp_grub)) == -1) {
1371 err = errno;
1372 be_print_err(gettext("be_change_grub_default: "
1373 "mkstemp failed: %s\n"), strerror(err));
1374 ret = errno_to_be_err(err);
1375 free(temp_grub);
1376 temp_grub = NULL;
1377 goto cleanup;
1378 }
1379 if ((temp_fp = fdopen(fd, "w")) == NULL) {
1380 err = errno;
1381 be_print_err(gettext("be_change_grub_default: "
1382 "failed to open %s file: %s\n"),
1383 temp_grub, strerror(err));
1384 (void) close(fd);
1385 ret = errno_to_be_err(err);
1386 goto cleanup;
1387 }
1388
1389 while (fgets(line, BUFSIZ, grub_fp)) {
1390 char *tok = strtok(line, BE_WHITE_SPACE);
1391
1392 if (tok == NULL || tok[0] == '#') {
1393 continue;
1394 } else if (strcmp(tok, "title") == 0) {
1395 entries++;
1396 continue;
1397 } else if (strcmp(tok, "bootfs") == 0) {
1398 char *bootfs = strtok(NULL, BE_WHITE_SPACE);
1399 if (bootfs == NULL)
1400 continue;
1401
1402 if (strcmp(bootfs, be_root_ds) == 0) {
1403 found_default = B_TRUE;
1404 break;
1405 }
1406 }
1407 }
1408
1409 if (!found_default) {
1410 be_print_err(gettext("be_change_grub_default: failed "
1411 "to find entry for %s in the grub menu\n"),
1412 be_name);
1413 ret = BE_ERR_BE_NOENT;
1414 goto cleanup;
1415 }
1416
1417 rewind(grub_fp);
1418
1419 while (fgets(line, BUFSIZ, grub_fp)) {
1420 char *tok = NULL;
1421
1422 (void) strncpy(temp_line, line, BUFSIZ);
1423
1424 if ((tok = strtok(temp_line, BE_WHITE_SPACE)) != NULL &&
1425 strcmp(tok, "default") == 0) {
1426 (void) snprintf(temp_line, BUFSIZ, "default %d\n",
1427 entries - 1 >= 0 ? entries - 1 : 0);
1428 (void) fputs(temp_line, temp_fp);
1429 } else {
1430 (void) fputs(line, temp_fp);
1431 }
1432 }
1433
1434 (void) fclose(grub_fp);
1435 grub_fp = NULL;
1436 (void) fclose(temp_fp);
1437 temp_fp = NULL;
1438
1439 if (rename(temp_grub, grub_file) != 0) {
1440 err = errno;
1441 be_print_err(gettext("be_change_grub_default: "
1442 "failed to rename file %s to %s: %s\n"),
1443 temp_grub, grub_file, strerror(err));
1444 ret = errno_to_be_err(err);
1445 goto cleanup;
1446 }
1447 free(temp_grub);
1448 temp_grub = NULL;
1503 */
1504 int
1505 be_update_menu(char *be_orig_name, char *be_new_name, char *be_root_pool,
1506 char *boot_pool)
1507 {
1508 zfs_handle_t *zhp = NULL;
1509 char menu_file[MAXPATHLEN];
1510 char be_root_ds[MAXPATHLEN];
1511 char be_new_root_ds[MAXPATHLEN];
1512 char line[BUFSIZ];
1513 char *pool_mntpnt = NULL;
1514 char *ptmp_mntpnt = NULL;
1515 char *orig_mntpnt = NULL;
1516 char *temp_menu = NULL;
1517 FILE *menu_fp = NULL;
1518 FILE *new_fp = NULL;
1519 struct stat sb;
1520 int temp_menu_len = 0;
1521 int tmp_fd;
1522 int ret = BE_SUCCESS;
1523 int err = 0;
1524 boolean_t pool_mounted = B_FALSE;
1525
1526 errno = 0;
1527
1528 if (boot_pool == NULL)
1529 boot_pool = be_root_pool;
1530
1531 if ((zhp = zfs_open(g_zfs, be_root_pool, ZFS_TYPE_DATASET)) == NULL) {
1532 be_print_err(gettext("be_update_menu: failed to open "
1533 "pool dataset for %s: %s\n"), be_root_pool,
1534 libzfs_error_description(g_zfs));
1535 return (zfs_err_to_be_err(g_zfs));
1536 }
1537
1538 /*
1539 * Check to see if the pool's dataset is mounted. If it isn't we'll
1540 * attempt to mount it.
1541 */
1542 if ((ret = be_mount_pool(zhp, &ptmp_mntpnt, &orig_mntpnt,
1619 }
1620 if ((new_fp = fdopen(tmp_fd, "w")) == NULL) {
1621 err = errno;
1622 be_print_err(gettext("be_update_menu: "
1623 "fdopen failed: %s\n"), strerror(err));
1624 (void) close(tmp_fd);
1625 (void) fclose(menu_fp);
1626 free(temp_menu);
1627 ret = errno_to_be_err(err);
1628 goto cleanup;
1629 }
1630
1631 while (fgets(line, BUFSIZ, menu_fp)) {
1632 char tline[BUFSIZ];
1633 char new_line[BUFSIZ];
1634 char *c = NULL;
1635
1636 (void) strlcpy(tline, line, sizeof (tline));
1637
1638 /* Tokenize line */
1639 c = strtok(tline, BE_WHITE_SPACE);
1640
1641 if (c == NULL) {
1642 /* Found empty line, write it out. */
1643 (void) fputs(line, new_fp);
1644 } else if (c[0] == '#') {
1645 /* Found a comment line, write it out. */
1646 (void) fputs(line, new_fp);
1647 } else if (strcmp(c, "title") == 0) {
1648 char *name = NULL;
1649 char *desc = NULL;
1650
1651 /*
1652 * Found a 'title' line, parse out BE name or
1653 * the description.
1654 */
1655 name = strtok(NULL, BE_WHITE_SPACE);
1656
1657 if (name == NULL) {
1658 /*
1659 * Nothing after 'title', just push
1660 * this line through
1661 */
1662 (void) fputs(line, new_fp);
1663 } else {
1664 /*
1665 * Grab the remainder of the title which
1666 * could be a multi worded description
1667 */
1668 desc = strtok(NULL, "\n");
1669
1670 if (strcmp(name, be_orig_name) == 0) {
1671 /*
1672 * The first token of the title is
1673 * the old BE name, replace it with
1674 * the new one, and write it out
1675 * along with the remainder of
1676 * description if there is one.
1677 */
1678 if (desc) {
1679 (void) snprintf(new_line,
1680 sizeof (new_line),
1681 "title %s %s\n",
1682 be_new_name, desc);
1683 } else {
1684 (void) snprintf(new_line,
1685 sizeof (new_line),
1686 "title %s\n", be_new_name);
1687 }
1688
1689 (void) fputs(new_line, new_fp);
1690 } else {
1691 (void) fputs(line, new_fp);
1692 }
1693 }
1694 } else if (strcmp(c, "bootfs") == 0) {
1695 /*
1696 * Found a 'bootfs' line, parse out the BE root
1697 * dataset value.
1698 */
1699 char *root_ds = strtok(NULL, BE_WHITE_SPACE);
1700
1701 if (root_ds == NULL) {
1702 /*
1703 * Nothing after 'bootfs', just push
1704 * this line through
1705 */
1706 (void) fputs(line, new_fp);
1707 } else {
1708 /*
1709 * If this bootfs is the one we're renaming,
1710 * write out the new root dataset value
1711 */
1712 if (strcmp(root_ds, be_root_ds) == 0) {
1713 (void) snprintf(new_line,
1714 sizeof (new_line), "bootfs %s\n",
1715 be_new_root_ds);
1716
1717 (void) fputs(new_line, new_fp);
1718 } else {
1719 (void) fputs(line, new_fp);
1720 }
1721 }
1722 } else {
1723 /*
1724 * Found some other line we don't care
1725 * about, write it out.
1726 */
1727 (void) fputs(line, new_fp);
1728 }
1729 }
1730
1731 (void) fclose(menu_fp);
1732 (void) fclose(new_fp);
1733 (void) close(tmp_fd);
1734
1836 (void) snprintf(menu_file, MAXPATHLEN, "/%s%s",
1837 rpool_mntpnt, BE_GRUB_MENU);
1838 } else {
1839 (void) snprintf(menu_file, MAXPATHLEN, "/%s%s",
1840 rpool_mntpnt, BE_SPARC_MENU);
1841 }
1842
1843 if (be_open_menu(be_root_pool, menu_file, &menu_fp, "r",
1844 B_FALSE) != 0) {
1845 ret = B_FALSE;
1846 goto cleanup;
1847 } else if (menu_fp == NULL) {
1848 ret = B_FALSE;
1849 goto cleanup;
1850 }
1851
1852 free(rpool_mntpnt);
1853 rpool_mntpnt = NULL;
1854
1855 while (fgets(line, BUFSIZ, menu_fp)) {
1856 char *tok = strtok_r(line, BE_WHITE_SPACE, &last);
1857
1858 if (tok != NULL && tok[0] != '#') {
1859 if (strcmp(tok, "bootfs") == 0) {
1860 tok = strtok_r(last, BE_WHITE_SPACE, &last);
1861 if (tok != NULL && strcmp(tok,
1862 be_dataset) == 0) {
1863 (void) fclose(menu_fp);
1864 /*
1865 * The entry number needs to be
1866 * decremented here because the title
1867 * will always be the first line for
1868 * an entry. Because of this we'll
1869 * always be off by one entry when we
1870 * check for bootfs.
1871 */
1872 *entry = ent_num - 1;
1873 ret = B_TRUE;
1874 goto cleanup;
1875 }
1876 } else if (strcmp(tok, "title") == 0)
1877 ent_num++;
1878 }
1879 }
1880
1881 cleanup:
1882 if (pool_mounted) {
1883 (void) be_unmount_pool(zhp, ptmp_mntpnt, orig_mntpnt);
1884 free(orig_mntpnt);
1885 free(ptmp_mntpnt);
1886 }
1887 ZFS_CLOSE(zhp);
1888 (void) fclose(menu_fp);
1889 return (ret);
1890 }
1891
1892 /*
1893 * Function: be_update_vfstab
1894 * Description: This function digs into a BE's vfstab and updates all
1895 * entries with file systems listed in be_fs_list_data_t.
1896 * The entry's root container dataset and be_name will be
3622 if (be_has_grub()) {
3623 /*
3624 * The grub menu is missing so we need to create it
3625 * and fill in the first few lines.
3626 */
3627 FILE *temp_fp = fopen(menu_file, "a+");
3628 if (temp_fp == NULL) {
3629 *menu_fp = NULL;
3630 return (errno_to_be_err(errno));
3631 }
3632
3633 if ((console = be_get_console_prop()) != NULL) {
3634
3635 /*
3636 * If console is redirected to serial line,
3637 * GRUB splash screen will not be enabled.
3638 */
3639 if (strncmp(console, "text", strlen("text")) == 0 ||
3640 strncmp(console, "graphics",
3641 strlen("graphics")) == 0) {
3642
3643 (void) fprintf(temp_fp, "%s\n", BE_GRUB_SPLASH);
3644 (void) fprintf(temp_fp, "%s\n",
3645 BE_GRUB_FOREGROUND);
3646 (void) fprintf(temp_fp, "%s\n",
3647 BE_GRUB_BACKGROUND);
3648 (void) fprintf(temp_fp, "%s\n",
3649 BE_GRUB_DEFAULT);
3650 } else {
3651 be_print_err(gettext("be_create_menu: "
3652 "console on serial line, "
3653 "GRUB splash image will be disabled\n"));
3654 }
3655 }
3656
3657 (void) fprintf(temp_fp, "timeout 30\n");
3658 (void) fclose(temp_fp);
3659
3660 } else {
3661 /*
3662 * The menu file doesn't exist so we need to create a
3663 * blank file.
3664 */
3665 FILE *temp_fp = fopen(menu_file, "w+");
3666 if (temp_fp == NULL) {
3667 *menu_fp = NULL;
3668 return (errno_to_be_err(errno));
3669 }
3670 (void) fclose(temp_fp);
3671 }
3672
3673 /*
3674 * Now we need to add all the BE's back into the the file.
3675 */
3676 if (_be_list(NULL, &be_nodes) == BE_SUCCESS) {
3677 while (be_nodes != NULL) {
|
444 * Additionally while iterating through the menu, if we have an
445 * original root dataset for a BE we're cloning from, we need to keep
446 * track of that BE's menu entry. We will then use the lines from
447 * that entry to create the entry for the new BE.
448 */
449 if ((ret = be_open_menu(be_root_pool, menu_file,
450 &menu_fp, "r", B_TRUE)) != BE_SUCCESS) {
451 goto cleanup;
452 } else if (menu_fp == NULL) {
453 ret = BE_ERR_NO_MENU;
454 goto cleanup;
455 }
456
457 free(pool_mntpnt);
458 pool_mntpnt = NULL;
459
460 while (fgets(line, BUFSIZ, menu_fp)) {
461 char *tok = NULL;
462
463 (void) strlcpy(temp_line, line, BUFSIZ);
464 tok = strtok(line, "=\n");
465
466 if (tok == NULL || tok[0] == '#') {
467 continue;
468 } else if (strcmp(tok, "entry_name") == 0) {
469 collect_lines = B_FALSE;
470 if ((tok = strtok(NULL, "\n")) == NULL)
471 (void) strlcpy(title, "", sizeof (title));
472 else
473 (void) strlcpy(title, tok, sizeof (title));
474 found_title = B_TRUE;
475
476 if (num_tmp_lines != 0) {
477 for (i = 0; i < num_tmp_lines; i++) {
478 free(tmp_entries[i]);
479 tmp_entries[i] = NULL;
480 }
481 num_tmp_lines = 0;
482 }
483 } else if (strcmp(tok, "data_set") == 0) {
484 char *bootfs = strtok(NULL, BE_WHITE_SPACE);
485 found_title = B_FALSE;
486 if (bootfs == NULL)
487 continue;
488
489 if (strcmp(bootfs, be_root_ds) == 0) {
490 found_be = B_TRUE;
491 break;
492 }
493
494 if (be_orig_root_ds != NULL &&
495 strcmp(bootfs, be_orig_root_ds) == 0 &&
496 !found_orig_be) {
497 char str[BUFSIZ];
498 found_orig_be = B_TRUE;
499 num_lines = 0;
500 /*
501 * Store the new title line
502 */
503 (void) snprintf(str, BUFSIZ, "entry_name=%s\n",
504 description ? description : be_name);
505 entries[num_lines] = strdup(str);
506 num_lines++;
507 /*
508 * If there are any lines between the title
509 * and the bootfs line store these. Also
510 * free the temporary lines.
511 */
512 for (i = 0; i < num_tmp_lines; i++) {
513 entries[num_lines] = tmp_entries[i];
514 tmp_entries[i] = NULL;
515 num_lines++;
516 }
517
518 zprop_get_cbdata_t cb = { 0 };
519 zprop_source_t src;
520 char * bc = strchr(be_root_ds, '/');
521 char sguid[] = "guid";
522
523 *bc = '\0';
524 cb.cb_first = B_TRUE;
525 cb.cb_sources = ZPROP_SRC_ALL;
526 cb.cb_type = ZFS_TYPE_POOL;
527 zprop_get_list(g_zfs, sguid, &cb.cb_proplist, ZFS_TYPE_POOL);
528 zpool_handle_t * z_hndl = zpool_open(g_zfs, be_root_ds);
529 *bc = '/';
530 if (z_hndl) {
531 uint64_t guid = zpool_get_prop_int(z_hndl, cb.cb_proplist->pl_prop, &src);
532 (void) snprintf(str, BUFSIZ, "pool_uuid=%llx\n", guid);
533 entries[num_lines] = strdup(str);
534 num_lines++;
535 zpool_close(z_hndl);
536 }
537 num_tmp_lines = 0;
538 /*
539 * Store the new bootfs line.
540 */
541 (void) snprintf(str, BUFSIZ, "data_set=%s\n",
542 be_root_ds);
543 entries[num_lines] = strdup(str);
544 num_lines++;
545 collect_lines = B_TRUE;
546 }
547 } else if (found_orig_be && collect_lines) {
548 /*
549 * get the rest of the lines for the original BE and
550 * store them.
551 */
552 if (strstr(line, BE_GRUB_COMMENT) != NULL ||
553 strstr(line, "BOOTADM") != NULL)
554 continue;
555 if (strcmp(tok, "splashimage") == 0) {
556 entries[num_lines] =
557 strdup("splashimage "
558 "/boot/splashimage.xpm\n");
559 } else if ((strcmp(tok, "kernel_path") == 0) ||
560 (strcmp(tok, "module") == 0))
561 {
562 char * path;
563 char * st_path;
564
565 st_path = strtok(NULL, "\n");
566 path = (char *) malloc(512);
567 strcpy(path, tok);
568 strcat(path, "=");
569 strcat(path, st_path);
570 strcat(path, "\n");
571 entries[num_lines] = path;
572 } else {
573 entries[num_lines] = strdup(temp_line);
574 }
575 num_lines++;
576 } else if (found_title && !found_orig_be) {
577 tmp_entries[num_tmp_lines] = strdup(temp_line);
578 num_tmp_lines++;
579 }
580 }
581
582 (void) fclose(menu_fp);
583
584 if (found_be) {
585 /*
586 * If an entry for this BE was already in the menu, then if
587 * that entry's title matches what we would have put in
588 * return success. Otherwise return failure.
589 */
590 char *new_title = description ? description : be_name;
591
614 goto cleanup;
615 }
616
617 if (found_orig_be) {
618 /*
619 * write out all the stored lines
620 */
621 for (i = 0; i < num_lines; i++) {
622 (void) fprintf(menu_fp, "%s", entries[i]);
623 free(entries[i]);
624 }
625 num_lines = 0;
626
627 /*
628 * Check to see if this system supports grub
629 */
630 if (be_has_grub())
631 (void) fprintf(menu_fp, "%s\n", BE_GRUB_COMMENT);
632 ret = BE_SUCCESS;
633 } else {
634 zprop_get_cbdata_t cb = { 0 };
635 zprop_source_t src;
636 char * bc = strchr(be_root_ds, '/');
637 char sguid[] = "guid";
638
639 (void) fprintf(menu_fp, "entry_name=%s\n",
640 description ? description : be_name);
641 *bc = '\0';
642 cb.cb_first = B_TRUE;
643 cb.cb_sources = ZPROP_SRC_ALL;
644 cb.cb_type = ZFS_TYPE_POOL;
645 zprop_get_list(g_zfs, sguid, &cb.cb_proplist, ZFS_TYPE_POOL);
646 zpool_handle_t * z_hndl = zpool_open(g_zfs, be_root_ds);
647 *bc = '/';
648 if (z_hndl) {
649 uint64_t guid = zpool_get_prop_int(z_hndl, cb.cb_proplist->pl_prop, &src);
650 (void) fprintf(menu_fp, "pool_uuid=%llx\n", guid);
651 zpool_close(z_hndl);
652 }
653 (void) fprintf(menu_fp, "data_set=%s\n", be_root_ds);
654
655 /*
656 * Check to see if this system supports grub
657 */
658 if (be_has_grub()) {
659 (void) fprintf(menu_fp, "kernel_path="
660 "/platform/i86pc/kernel/$ISADIR/unix\n");
661 (void) fprintf(menu_fp, "kernel_options="
662 "-B $ZFS_BOOTFS,console=graphic\n");
663 (void) fprintf(menu_fp, "module="
664 "/platform/i86pc/$ISADIR/boot_archive\n");
665 (void) fprintf(menu_fp, "%s\n", BE_GRUB_COMMENT);
666 }
667 ret = BE_SUCCESS;
668 }
669 (void) fclose(menu_fp);
670 cleanup:
671 if (pool_mounted) {
672 int err = BE_SUCCESS;
673 err = be_unmount_pool(zhp, ptmp_mntpnt, orig_mntpnt);
674 if (ret == BE_SUCCESS)
675 ret = err;
676 free(orig_mntpnt);
677 free(ptmp_mntpnt);
678 }
679 ZFS_CLOSE(zhp);
680 if (num_tmp_lines > 0) {
681 for (i = 0; i < num_tmp_lines; i++) {
682 free(tmp_entries[i]);
683 tmp_entries[i] = NULL;
823 free(tmp_menu);
824 tmp_menu = NULL;
825 goto cleanup;
826 }
827 if ((tmp_menu_fp = fdopen(fd, "w")) == NULL) {
828 err = errno;
829 be_print_err(gettext("be_remove_menu: "
830 "could not open tmp file for write: %s\n"), strerror(err));
831 (void) close(fd);
832 ret = errno_to_be_err(err);
833 goto cleanup;
834 }
835
836 while (fgets(menu_buf, BUFSIZ, menu_fp)) {
837 char tline [BUFSIZ];
838 char *tok = NULL;
839
840 (void) strlcpy(tline, menu_buf, sizeof (tline));
841
842 /* Tokenize line */
843 tok = strtok(tline, "=\n");
844
845 if (tok == NULL || tok[0] == '#') {
846 /* Found empty line or comment line */
847 if (do_buffer) {
848 /* Buffer this line */
849 if ((buffer = (char **)realloc(buffer,
850 sizeof (char *)*(nlines + 1))) == NULL) {
851 ret = BE_ERR_NOMEM;
852 goto cleanup;
853 }
854 if ((buffer[nlines++] = strdup(menu_buf))
855 == NULL) {
856 ret = BE_ERR_NOMEM;
857 goto cleanup;
858 }
859
860 } else if (write || strncmp(menu_buf, BE_GRUB_COMMENT,
861 strlen(BE_GRUB_COMMENT)) != 0) {
862 /* Write this line out */
863 (void) fputs(menu_buf, tmp_menu_fp);
864 }
865 } else if (strcmp(tok, "default_entry") == 0) {
866 /*
867 * Record what 'default' is set to because we might
868 * need to adjust this upon deleting an entry.
869 */
870 tok = strtok(NULL, BE_WHITE_SPACE);
871
872 if (tok != NULL) {
873 default_entry = atoi(tok);
874 }
875
876 (void) fputs(menu_buf, tmp_menu_fp);
877 } else if (strcmp(tok, "entry_name") == 0) {
878 /*
879 * If we've reached a 'title' line and do_buffer is
880 * is true, that means we've just buffered an entire
881 * entry without finding a 'bootfs' directive. We
882 * need to write that entry out and keep searching.
883 */
884 if (do_buffer) {
885 for (i = 0; i < nlines; i++) {
886 (void) fputs(buffer[i], tmp_menu_fp);
887 free(buffer[i]);
888 }
889 free(buffer);
890 buffer = NULL;
891 nlines = 0;
892 }
893
894 /*
895 * Turn writing off and buffering on, and increment
896 * our entry counter.
897 */
898 write = B_FALSE;
899 do_buffer = B_TRUE;
900 entry_cnt++;
901
902 /* Buffer this 'title' line */
903 if ((buffer = (char **)realloc(buffer,
904 sizeof (char *)*(nlines + 1))) == NULL) {
905 ret = BE_ERR_NOMEM;
906 goto cleanup;
907 }
908 if ((buffer[nlines++] = strdup(menu_buf)) == NULL) {
909 ret = BE_ERR_NOMEM;
910 goto cleanup;
911 }
912
913 } else if (strcmp(tok, "data_set") == 0) {
914 char *bootfs = NULL;
915
916 /*
917 * Found a 'bootfs' line. See if it matches the
918 * BE we're looking for.
919 */
920 if ((bootfs = strtok(NULL, BE_WHITE_SPACE)) == NULL ||
921 strcmp(bootfs, be_root_ds) != 0) {
922 /*
923 * Either there's nothing after the 'bootfs'
924 * or this is not the BE we're looking for,
925 * write out the line(s) we've buffered since
926 * finding the title.
927 */
928 for (i = 0; i < nlines; i++) {
929 (void) fputs(buffer[i], tmp_menu_fp);
930 free(buffer[i]);
931 }
932 free(buffer);
933 buffer = NULL;
1054 tmp_menu = NULL;
1055 goto cleanup;
1056 }
1057 if ((tmp_menu_fp = fdopen(fd, "w")) == NULL) {
1058 err = errno;
1059 be_print_err(gettext("be_remove_menu: "
1060 "could not open tmp file for write: %s\n"),
1061 strerror(err));
1062 (void) close(fd);
1063 ret = errno_to_be_err(err);
1064 goto cleanup;
1065 }
1066
1067 while (fgets(menu_buf, BUFSIZ, menu_fp)) {
1068 char tline [BUFSIZ];
1069 char *tok = NULL;
1070
1071 (void) strlcpy(tline, menu_buf, sizeof (tline));
1072
1073 /* Tokenize line */
1074 tok = strtok(tline, "=\n");
1075
1076 if (tok == NULL) {
1077 /* Found empty line, write it out */
1078 (void) fputs(menu_buf, tmp_menu_fp);
1079 } else if (strcmp(tok, "default_entry") == 0) {
1080 /* Found the default line, adjust it */
1081 (void) snprintf(tline, sizeof (tline),
1082 "default_entry=%d\n", default_entry);
1083
1084 (void) fputs(tline, tmp_menu_fp);
1085 } else {
1086 /* Pass through all other lines */
1087 (void) fputs(menu_buf, tmp_menu_fp);
1088 }
1089 }
1090
1091 (void) fclose(menu_fp);
1092 menu_fp = NULL;
1093 (void) fclose(tmp_menu_fp);
1094 tmp_menu_fp = NULL;
1095
1096 /* Copy the modified menu.lst into place */
1097 if (rename(tmp_menu, menu) != 0) {
1098 err = errno;
1099 be_print_err(gettext("be_remove_menu: "
1100 "failed to rename file %s to %s: %s\n"),
1101 tmp_menu, menu, strerror(err));
1102 ret = errno_to_be_err(err);
1221 "the default BE in the grub menu.\n"));
1222 ret = BE_ERR_NO_MENU;
1223 goto cleanup;
1224 }
1225
1226 (void) snprintf(grub_file, MAXPATHLEN, "%s%s",
1227 pool_mntpnt, BE_GRUB_MENU);
1228
1229 if ((ret = be_open_menu((char *)be_root_pool, grub_file,
1230 &menu_fp, "r", B_FALSE)) != BE_SUCCESS) {
1231 goto cleanup;
1232 } else if (menu_fp == NULL) {
1233 ret = BE_ERR_NO_MENU;
1234 goto cleanup;
1235 }
1236
1237 free(pool_mntpnt);
1238 pool_mntpnt = NULL;
1239
1240 while (fgets(line, BUFSIZ, menu_fp)) {
1241 char *tok = strtok(line, "=\n");
1242
1243 if (tok != NULL && tok[0] != '#') {
1244 if (!found_default) {
1245 if (strcmp(tok, "default_entry") == 0) {
1246 tok = strtok(NULL, BE_WHITE_SPACE);
1247 if (tok != NULL) {
1248 default_entry = atoi(tok);
1249 rewind(menu_fp);
1250 found_default = 1;
1251 }
1252 }
1253 continue;
1254 }
1255 if (strcmp(tok, "entry_name") == 0) {
1256 entries++;
1257 } else if (default_entry == entries - 1) {
1258 if (strcmp(tok, "data_set") == 0) {
1259 tok = strtok(NULL, BE_WHITE_SPACE);
1260 (void) fclose(menu_fp);
1261
1262 if (tok == NULL) {
1263 ret = BE_SUCCESS;
1264 goto cleanup;
1265 }
1266
1267 if ((*def_bootfs = strdup(tok)) !=
1268 NULL) {
1269 ret = BE_SUCCESS;
1270 goto cleanup;
1271 }
1272 be_print_err(gettext(
1273 "be_default_grub_bootfs: "
1274 "memory allocation failed\n"));
1275 ret = BE_ERR_NOMEM;
1276 goto cleanup;
1277 }
1278 } else if (default_entry < entries - 1) {
1421 if ((fd = mkstemp(temp_grub)) == -1) {
1422 err = errno;
1423 be_print_err(gettext("be_change_grub_default: "
1424 "mkstemp failed: %s\n"), strerror(err));
1425 ret = errno_to_be_err(err);
1426 free(temp_grub);
1427 temp_grub = NULL;
1428 goto cleanup;
1429 }
1430 if ((temp_fp = fdopen(fd, "w")) == NULL) {
1431 err = errno;
1432 be_print_err(gettext("be_change_grub_default: "
1433 "failed to open %s file: %s\n"),
1434 temp_grub, strerror(err));
1435 (void) close(fd);
1436 ret = errno_to_be_err(err);
1437 goto cleanup;
1438 }
1439
1440 while (fgets(line, BUFSIZ, grub_fp)) {
1441 char *tok = strtok(line, "=\n");
1442
1443 if (tok == NULL || tok[0] == '#') {
1444 continue;
1445 } else if (strcmp(tok, "entry_name") == 0) {
1446 entries++;
1447 continue;
1448 } else if (strcmp(tok, "data_set") == 0) {
1449 char *bootfs = strtok(NULL, BE_WHITE_SPACE);
1450 if (bootfs == NULL)
1451 continue;
1452
1453 if (strcmp(bootfs, be_root_ds) == 0) {
1454 found_default = B_TRUE;
1455 break;
1456 }
1457 }
1458 }
1459
1460 if (!found_default) {
1461 be_print_err(gettext("be_change_grub_default: failed "
1462 "to find entry for %s in the grub menu\n"),
1463 be_name);
1464 ret = BE_ERR_BE_NOENT;
1465 goto cleanup;
1466 }
1467
1468 rewind(grub_fp);
1469
1470 (void) snprintf(temp_line, BUFSIZ, "default_entry=%d\n",
1471 entries - 1 >= 0 ? entries - 1 : 0);
1472 (void) fputs(temp_line, temp_fp);
1473 while (fgets(line, BUFSIZ, grub_fp)) {
1474 char *tok = NULL;
1475
1476 (void) strncpy(temp_line, line, BUFSIZ);
1477
1478 if ((tok = strtok(temp_line, "=\n")) != NULL &&
1479 strcmp(tok, "default_entry") == 0) {
1480 } else {
1481 (void) fputs(line, temp_fp);
1482 }
1483 }
1484
1485 (void) fclose(grub_fp);
1486 grub_fp = NULL;
1487 (void) fclose(temp_fp);
1488 temp_fp = NULL;
1489
1490 if (rename(temp_grub, grub_file) != 0) {
1491 err = errno;
1492 be_print_err(gettext("be_change_grub_default: "
1493 "failed to rename file %s to %s: %s\n"),
1494 temp_grub, grub_file, strerror(err));
1495 ret = errno_to_be_err(err);
1496 goto cleanup;
1497 }
1498 free(temp_grub);
1499 temp_grub = NULL;
1554 */
1555 int
1556 be_update_menu(char *be_orig_name, char *be_new_name, char *be_root_pool,
1557 char *boot_pool)
1558 {
1559 zfs_handle_t *zhp = NULL;
1560 char menu_file[MAXPATHLEN];
1561 char be_root_ds[MAXPATHLEN];
1562 char be_new_root_ds[MAXPATHLEN];
1563 char line[BUFSIZ];
1564 char *pool_mntpnt = NULL;
1565 char *ptmp_mntpnt = NULL;
1566 char *orig_mntpnt = NULL;
1567 char *temp_menu = NULL;
1568 FILE *menu_fp = NULL;
1569 FILE *new_fp = NULL;
1570 struct stat sb;
1571 int temp_menu_len = 0;
1572 int tmp_fd;
1573 int ret = BE_SUCCESS;
1574 int flag = 0;
1575 int err = 0;
1576 boolean_t pool_mounted = B_FALSE;
1577
1578 errno = 0;
1579
1580 if (boot_pool == NULL)
1581 boot_pool = be_root_pool;
1582
1583 if ((zhp = zfs_open(g_zfs, be_root_pool, ZFS_TYPE_DATASET)) == NULL) {
1584 be_print_err(gettext("be_update_menu: failed to open "
1585 "pool dataset for %s: %s\n"), be_root_pool,
1586 libzfs_error_description(g_zfs));
1587 return (zfs_err_to_be_err(g_zfs));
1588 }
1589
1590 /*
1591 * Check to see if the pool's dataset is mounted. If it isn't we'll
1592 * attempt to mount it.
1593 */
1594 if ((ret = be_mount_pool(zhp, &ptmp_mntpnt, &orig_mntpnt,
1671 }
1672 if ((new_fp = fdopen(tmp_fd, "w")) == NULL) {
1673 err = errno;
1674 be_print_err(gettext("be_update_menu: "
1675 "fdopen failed: %s\n"), strerror(err));
1676 (void) close(tmp_fd);
1677 (void) fclose(menu_fp);
1678 free(temp_menu);
1679 ret = errno_to_be_err(err);
1680 goto cleanup;
1681 }
1682
1683 while (fgets(line, BUFSIZ, menu_fp)) {
1684 char tline[BUFSIZ];
1685 char new_line[BUFSIZ];
1686 char *c = NULL;
1687
1688 (void) strlcpy(tline, line, sizeof (tline));
1689
1690 /* Tokenize line */
1691 c = strtok(tline, "=\n");
1692
1693 if (c == NULL) {
1694 /* Found empty line, write it out. */
1695 (void) fputs(line, new_fp);
1696 } else if (c[0] == '#') {
1697 /* Found a comment line, write it out. */
1698 (void) fputs(line, new_fp);
1699 } else if (strcmp(c, "entry_name") == 0) {
1700 char *name = NULL;
1701 char *desc = NULL;
1702
1703 /*
1704 * Found a 'title' line, parse out BE name or
1705 * the description.
1706 */
1707 flag = 0;
1708 name = strtok(NULL, BE_WHITE_SPACE);
1709
1710 if (name == NULL) {
1711 /*
1712 * Nothing after 'title', just push
1713 * this line through
1714 */
1715 (void) fputs(line, new_fp);
1716 } else {
1717 /*
1718 * Grab the remainder of the title which
1719 * could be a multi worded description
1720 */
1721 desc = strtok(NULL, "\n");
1722
1723 if (strcmp(name, be_orig_name) == 0) {
1724 /*
1725 * The first token of the title is
1726 * the old BE name, replace it with
1727 * the new one, and write it out
1728 * along with the remainder of
1729 * description if there is one.
1730 */
1731 ++flag;
1732 if (desc) {
1733 (void) snprintf(new_line,
1734 sizeof (new_line),
1735 "entry_name=%s %s\n",
1736 be_new_name, desc);
1737 } else {
1738 (void) snprintf(new_line,
1739 sizeof (new_line),
1740 "entry_name=%s\n", be_new_name);
1741 }
1742
1743 (void) fputs(new_line, new_fp);
1744 } else {
1745 (void) fputs(line, new_fp);
1746 }
1747 }
1748 } else if (strcmp(c, "data_set") == 0) {
1749 /*
1750 * Found a 'bootfs' line, parse out the BE root
1751 * dataset value.
1752 */
1753 char *root_ds = strtok(NULL, BE_WHITE_SPACE);
1754
1755 if (root_ds == NULL) {
1756 /*
1757 * Nothing after 'bootfs', just push
1758 * this line through
1759 */
1760 (void) fputs(line, new_fp);
1761 } else {
1762 /*
1763 * If this bootfs is the one we're renaming,
1764 * write out the new root dataset value
1765 */
1766 if (strcmp(root_ds, be_root_ds) == 0) {
1767 ++flag;
1768 (void) snprintf(new_line,
1769 sizeof (new_line), "data_set=%s\n",
1770 be_new_root_ds);
1771
1772 (void) fputs(new_line, new_fp);
1773 } else {
1774 (void) fputs(line, new_fp);
1775 }
1776 }
1777 } else {
1778 /*
1779 * Found some other line we don't care
1780 * about, write it out.
1781 */
1782 (void) fputs(line, new_fp);
1783 }
1784 }
1785
1786 (void) fclose(menu_fp);
1787 (void) fclose(new_fp);
1788 (void) close(tmp_fd);
1789
1891 (void) snprintf(menu_file, MAXPATHLEN, "/%s%s",
1892 rpool_mntpnt, BE_GRUB_MENU);
1893 } else {
1894 (void) snprintf(menu_file, MAXPATHLEN, "/%s%s",
1895 rpool_mntpnt, BE_SPARC_MENU);
1896 }
1897
1898 if (be_open_menu(be_root_pool, menu_file, &menu_fp, "r",
1899 B_FALSE) != 0) {
1900 ret = B_FALSE;
1901 goto cleanup;
1902 } else if (menu_fp == NULL) {
1903 ret = B_FALSE;
1904 goto cleanup;
1905 }
1906
1907 free(rpool_mntpnt);
1908 rpool_mntpnt = NULL;
1909
1910 while (fgets(line, BUFSIZ, menu_fp)) {
1911 char *tok = strtok_r(line, "=\n", &last);
1912
1913 if (tok != NULL && tok[0] != '#') {
1914 if (strcmp(tok, "data_set") == 0) {
1915 tok = strtok_r(last, BE_WHITE_SPACE, &last);
1916 if (tok != NULL && strcmp(tok,
1917 be_dataset) == 0) {
1918 (void) fclose(menu_fp);
1919 /*
1920 * The entry number needs to be
1921 * decremented here because the title
1922 * will always be the first line for
1923 * an entry. Because of this we'll
1924 * always be off by one entry when we
1925 * check for bootfs.
1926 */
1927 *entry = ent_num - 1;
1928 ret = B_TRUE;
1929 goto cleanup;
1930 }
1931 } else if (strcmp(tok, "entry_name") == 0)
1932 ent_num++;
1933 }
1934 }
1935
1936 cleanup:
1937 if (pool_mounted) {
1938 (void) be_unmount_pool(zhp, ptmp_mntpnt, orig_mntpnt);
1939 free(orig_mntpnt);
1940 free(ptmp_mntpnt);
1941 }
1942 ZFS_CLOSE(zhp);
1943 (void) fclose(menu_fp);
1944 return (ret);
1945 }
1946
1947 /*
1948 * Function: be_update_vfstab
1949 * Description: This function digs into a BE's vfstab and updates all
1950 * entries with file systems listed in be_fs_list_data_t.
1951 * The entry's root container dataset and be_name will be
3677 if (be_has_grub()) {
3678 /*
3679 * The grub menu is missing so we need to create it
3680 * and fill in the first few lines.
3681 */
3682 FILE *temp_fp = fopen(menu_file, "a+");
3683 if (temp_fp == NULL) {
3684 *menu_fp = NULL;
3685 return (errno_to_be_err(errno));
3686 }
3687
3688 if ((console = be_get_console_prop()) != NULL) {
3689
3690 /*
3691 * If console is redirected to serial line,
3692 * GRUB splash screen will not be enabled.
3693 */
3694 if (strncmp(console, "text", strlen("text")) == 0 ||
3695 strncmp(console, "graphics",
3696 strlen("graphics")) == 0) {
3697 /*
3698 (void) fprintf(temp_fp, "%s\n", BE_GRUB_SPLASH);
3699 (void) fprintf(temp_fp, "%s\n",
3700 BE_GRUB_FOREGROUND);
3701 (void) fprintf(temp_fp, "%s\n",
3702 BE_GRUB_BACKGROUND);
3703 (void) fprintf(temp_fp, "%s\n",
3704 BE_GRUB_DEFAULT);*/
3705 } else {
3706 be_print_err(gettext("be_create_menu: "
3707 "console on serial line, "
3708 "GRUB splash image will be disabled\n"));
3709 }
3710 }
3711
3712 (void) fprintf(temp_fp, "timeout=30\n");
3713 (void) fclose(temp_fp);
3714
3715 } else {
3716 /*
3717 * The menu file doesn't exist so we need to create a
3718 * blank file.
3719 */
3720 FILE *temp_fp = fopen(menu_file, "w+");
3721 if (temp_fp == NULL) {
3722 *menu_fp = NULL;
3723 return (errno_to_be_err(errno));
3724 }
3725 (void) fclose(temp_fp);
3726 }
3727
3728 /*
3729 * Now we need to add all the BE's back into the the file.
3730 */
3731 if (_be_list(NULL, &be_nodes) == BE_SUCCESS) {
3732 while (be_nodes != NULL) {
|