Print this page
libbe patch


 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) {