/* * Function: be_is_active_on_boot * Description: Checks if the BE name passed in has the "active on boot" * property set to B_TRUE. * Paramters: * be_name - the name of the BE to check * Returns: * B_TRUE - if active on boot. * B_FALSE - if not active on boot. * Scope: * Semi-private (library wide use only) */ boolean_t be_is_active_on_boot(char *be_name) { be_node_list_t *be_node = NULL; if (be_name == NULL) { be_print_err(gettext("be_is_active_on_boot: " "be_name must not be NULL\n")); return (B_FALSE); } if (_be_list(be_name, &be_node) != BE_SUCCESS) { return (B_FALSE); } if (be_node == NULL) { return (B_FALSE); } if (be_node->be_active_on_boot) { be_free_list(be_node); return (B_TRUE); } else { be_free_list(be_node); return (B_FALSE); } }
static int be_do_list(int argc, char **argv) { be_node_list_t *be_nodes = NULL; boolean_t all = B_FALSE; boolean_t dsets = B_FALSE; boolean_t snaps = B_FALSE; boolean_t parsable = B_FALSE; int err = 1; int c = 0; char *be_name = NULL; be_sort_t order = BE_SORT_UNSPECIFIED; while ((c = getopt(argc, argv, "adk:svHK:")) != -1) { switch (c) { case 'a': all = B_TRUE; break; case 'd': dsets = B_TRUE; break; case 'k': case 'K': if (order != BE_SORT_UNSPECIFIED) { (void) fprintf(stderr, _("Sort key can be " "specified only once.\n")); usage(); return (1); } if (strcmp(optarg, "date") == 0) { if (c == 'k') order = BE_SORT_DATE; else order = BE_SORT_DATE_REV; break; } if (strcmp(optarg, "name") == 0) { if (c == 'k') order = BE_SORT_NAME; else order = BE_SORT_NAME_REV; break; } if (strcmp(optarg, "space") == 0) { if (c == 'k') order = BE_SORT_SPACE; else order = BE_SORT_SPACE_REV; break; } (void) fprintf(stderr, _("Unknown sort key: %s\n"), optarg); usage(); return (1); case 's': snaps = B_TRUE; break; case 'v': libbe_print_errors(B_TRUE); break; case 'H': parsable = B_TRUE; break; default: usage(); return (1); } } if (all) { if (dsets) { (void) fprintf(stderr, _("Invalid options: -a and %s " "are mutually exclusive.\n"), "-d"); usage(); return (1); } if (snaps) { (void) fprintf(stderr, _("Invalid options: -a and %s " "are mutually exclusive.\n"), "-s"); usage(); return (1); } dsets = B_TRUE; snaps = B_TRUE; } argc -= optind; argv += optind; if (argc == 1) be_name = argv[0]; err = be_list(be_name, &be_nodes); switch (err) { case BE_SUCCESS: /* the default sort is ascending date, no need to sort twice */ if (order == BE_SORT_UNSPECIFIED) order = BE_SORT_DATE; if (order != BE_SORT_DATE) { err = be_sort(&be_nodes, order); if (err != BE_SUCCESS) { (void) fprintf(stderr, _("Unable to sort Boot " "Environment\n")); (void) fprintf(stderr, "%s\n", be_err_to_str(err)); break; } } print_nodes(be_name, dsets, snaps, parsable, be_nodes); break; case BE_ERR_BE_NOENT: if (be_name == NULL) (void) fprintf(stderr, _("No boot environments found " "on this system.\n")); else { (void) fprintf(stderr, _("%s does not exist or appear " "to be a valid BE.\nPlease check that the name of " "the BE provided is correct.\n"), be_name); } break; default: (void) fprintf(stderr, _("Unable to display Boot " "Environment\n")); (void) fprintf(stderr, "%s\n", be_err_to_str(err)); } if (be_nodes != NULL) be_free_list(be_nodes); return (err); }
static int be_do_list(int argc, char **argv) { be_node_list_t *be_nodes = NULL; boolean_t all = B_FALSE; boolean_t dsets = B_FALSE; boolean_t snaps = B_FALSE; boolean_t parsable = B_FALSE; int err = 1; int c = 0; char *be_name = NULL; while ((c = getopt(argc, argv, "nadsH")) != -1) { switch (c) { case 'a': all = B_TRUE; break; case 'd': dsets = B_TRUE; break; case 's': snaps = B_TRUE; break; case 'H': parsable = B_TRUE; break; default: usage(); return (1); } } if (all) { if (dsets) { (void) fprintf(stderr, _("Invalid options: -a and %s " "are mutually exclusive.\n"), "-d"); usage(); return (1); } if (snaps) { (void) fprintf(stderr, _("Invalid options: -a and %s " "are mutually exclusive.\n"), "-s"); usage(); return (1); } dsets = B_TRUE; snaps = B_TRUE; } argc -= optind; argv += optind; if (argc == 1) be_name = argv[0]; err = be_list(be_name, &be_nodes); switch (err) { case BE_SUCCESS: print_nodes(be_name, dsets, snaps, parsable, be_nodes); break; case BE_ERR_BE_NOENT: if (be_name == NULL) (void) fprintf(stderr, _("No boot environments found " "on this system.\n")); else { (void) fprintf(stderr, _("%s does not exist or appear " "to be a valid BE.\nPlease check that the name of " "the BE provided is correct.\n"), be_name); } break; default: (void) fprintf(stderr, _("Unable to display Boot " "Environment\n")); (void) fprintf(stderr, "%s\n", be_err_to_str(err)); } if (be_nodes != NULL) be_free_list(be_nodes); return (err); }
/* * Function: _be_list * Description: This does the actual work described in be_list. * Parameters: * be_name - The name of the BE to look up. * If NULL a list of all BEs will be returned. * be_nodes - A reference pointer to the list of BEs. The list * structure will be allocated here and must * be freed by a call to be_free_list. If there are no * BEs found on the system this reference will be * set to NULL. * Return: * BE_SUCCESS - Success * be_errno_t - Failure * Scope: * Semi-private (library wide use only) */ int _be_list(char *be_name, be_node_list_t **be_nodes) { list_callback_data_t cb = { 0 }; be_transaction_data_t bt = { 0 }; int ret = BE_SUCCESS; zpool_handle_t *zphp; char *rpool = NULL; struct be_defaults be_defaults; if (be_nodes == NULL) return (BE_ERR_INVAL); be_get_defaults(&be_defaults); if (be_find_current_be(&bt) != BE_SUCCESS) { /* * We were unable to find a currently booted BE which * probably means that we're not booted in a BE envoronment. * None of the BE's will be marked as the active BE. */ (void) strcpy(cb.current_be, "-"); } else { (void) strncpy(cb.current_be, bt.obe_name, sizeof (cb.current_be)); rpool = bt.obe_zpool; } /* * If be_name is NULL we'll look for all BE's on the system. * If not then we will only return data for the specified BE. */ if (be_name != NULL) cb.be_name = strdup(be_name); if (be_defaults.be_deflt_rpool_container && rpool != NULL) { if ((zphp = zpool_open(g_zfs, rpool)) == NULL) { be_print_err(gettext("be_list: failed to " "open rpool (%s): %s\n"), rpool, libzfs_error_description(g_zfs)); free(cb.be_name); return (zfs_err_to_be_err(g_zfs)); } ret = be_get_list_callback(zphp, &cb); } else { if ((zpool_iter(g_zfs, be_get_list_callback, &cb)) != 0) { if (cb.be_nodes_head != NULL) { be_free_list(cb.be_nodes_head); cb.be_nodes_head = NULL; cb.be_nodes = NULL; } ret = BE_ERR_BE_NOENT; } } if (cb.be_nodes_head == NULL) { if (be_name != NULL) be_print_err(gettext("be_list: BE (%s) does not " "exist\n"), be_name); else be_print_err(gettext("be_list: No BE's found\n")); ret = BE_ERR_BE_NOENT; } *be_nodes = cb.be_nodes_head; free(cb.be_name); be_sort_list(be_nodes); return (ret); }
/* * Function: _be_activate * Description: This does the actual work described in be_activate. * Parameters: * be_name - pointer to the name of BE to activate. * * Return: * BE_SUCCESS - Success * be_errnot_t - Failure * Scope: * Public */ int _be_activate(char *be_name) { be_transaction_data_t cb = { 0 }; zfs_handle_t *zhp = NULL; char root_ds[MAXPATHLEN]; char *cur_vers = NULL, *new_vers = NULL; be_node_list_t *be_nodes = NULL; uuid_t uu = {0}; int entry, ret = BE_SUCCESS; int zret = 0; /* * TODO: The BE needs to be validated to make sure that it is actually * a bootable BE. */ if (be_name == NULL) return (BE_ERR_INVAL); /* Set obe_name to be_name in the cb structure */ cb.obe_name = be_name; /* find which zpool the be is in */ if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &cb)) == 0) { be_print_err(gettext("be_activate: failed to " "find zpool for BE (%s)\n"), cb.obe_name); return (BE_ERR_BE_NOENT); } else if (zret < 0) { be_print_err(gettext("be_activate: " "zpool_iter failed: %s\n"), libzfs_error_description(g_zfs)); ret = zfs_err_to_be_err(g_zfs); return (ret); } be_make_root_ds(cb.obe_zpool, cb.obe_name, root_ds, sizeof (root_ds)); cb.obe_root_ds = strdup(root_ds); if (getzoneid() == GLOBAL_ZONEID) { if (be_has_grub() && (ret = be_get_grub_vers(&cb, &cur_vers, &new_vers)) != BE_SUCCESS) { be_print_err(gettext("be_activate: failed to get grub " "versions from capability files.\n")); return (ret); } if (cur_vers != NULL) { /* * We need to check to see if the version number from * the BE being activated is greater than the current * one. */ if (new_vers != NULL && atof(cur_vers) < atof(new_vers)) { if ((ret = be_do_installgrub(&cb)) != BE_SUCCESS) { free(new_vers); free(cur_vers); return (ret); } free(new_vers); } free(cur_vers); } else if (new_vers != NULL) { if ((ret = be_do_installgrub(&cb)) != BE_SUCCESS) { free(new_vers); return (ret); } free(new_vers); } if (!be_has_menu_entry(root_ds, cb.obe_zpool, &entry)) { if ((ret = be_append_menu(cb.obe_name, cb.obe_zpool, NULL, NULL, NULL)) != BE_SUCCESS) { be_print_err(gettext("be_activate: Failed to " "add BE (%s) to the GRUB menu\n"), cb.obe_name); goto done; } } if (be_has_grub()) { if ((ret = be_change_grub_default(cb.obe_name, cb.obe_zpool)) != BE_SUCCESS) { be_print_err(gettext("be_activate: failed to " "change the default entry in menu.lst\n")); goto done; } } } if ((ret = _be_list(cb.obe_name, &be_nodes)) != BE_SUCCESS) { return (ret); } if ((ret = set_canmount(be_nodes, "noauto")) != BE_SUCCESS) { be_print_err(gettext("be_activate: failed to set " "canmount dataset property\n")); goto done; } if ((ret = set_bootfs(be_nodes->be_rpool, root_ds)) != BE_SUCCESS) { be_print_err(gettext("be_activate: failed to set " "bootfs pool property for %s\n"), root_ds); goto done; } if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) != NULL) { /* * We don't need to close the zfs handle at this * point because The callback funtion * be_promote_ds_callback() will close it for us. */ if (be_promote_ds_callback(zhp, NULL) != 0) { be_print_err(gettext("be_activate: " "failed to activate the " "datasets for %s: %s\n"), root_ds, libzfs_error_description(g_zfs)); ret = BE_ERR_PROMOTE; goto done; } } else { be_print_err(gettext("be_activate:: failed to open " "dataset (%s): %s\n"), root_ds, libzfs_error_description(g_zfs)); ret = zfs_err_to_be_err(g_zfs); goto done; } if (getzoneid() == GLOBAL_ZONEID && be_get_uuid(cb.obe_root_ds, &uu) == BE_SUCCESS && (ret = be_promote_zone_ds(cb.obe_name, cb.obe_root_ds)) != BE_SUCCESS) { be_print_err(gettext("be_activate: failed to promote " "the active zonepath datasets for zones in BE %s\n"), cb.obe_name); } done: be_free_list(be_nodes); return (ret); }