static int be_do_destroy(int argc, char **argv) { nvlist_t *be_attrs; boolean_t is_snap = B_FALSE; boolean_t suppress_prompt = B_FALSE; int err = 1; int c; int destroy_flags = 0; char *snap_name; char *be_name; while ((c = getopt(argc, argv, "fFsv")) != -1) { switch (c) { case 'f': destroy_flags |= BE_DESTROY_FLAG_FORCE_UNMOUNT; break; case 's': destroy_flags |= BE_DESTROY_FLAG_SNAPSHOTS; break; case 'v': libbe_print_errors(B_TRUE); break; case 'F': suppress_prompt = B_TRUE; break; default: usage(); return (1); } } argc -= optind; argv += optind; if (argc != 1) { usage(); return (1); } be_name = argv[0]; if (!suppress_prompt && !confirm_destroy(be_name)) { (void) printf(_("%s has not been destroyed.\n"), be_name); return (0); } if ((snap_name = strrchr(be_name, '@')) != NULL) { if (snap_name[1] == '\0') { usage(); return (1); } is_snap = B_TRUE; *snap_name = '\0'; snap_name++; } if (be_nvl_alloc(&be_attrs) != 0) return (1); if (be_nvl_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, be_name) != 0) goto out; if (is_snap) { if (be_nvl_add_string(be_attrs, BE_ATTR_SNAP_NAME, snap_name) != 0) goto out; err = be_destroy_snapshot(be_attrs); } else { if (be_nvl_add_uint16(be_attrs, BE_ATTR_DESTROY_FLAGS, destroy_flags) != 0) goto out; err = be_destroy(be_attrs); } switch (err) { case BE_SUCCESS: (void) printf(_("Destroyed successfully\n")); break; case BE_ERR_MOUNTED: (void) fprintf(stderr, _("Unable to destroy %s.\n"), be_name); (void) fprintf(stderr, _("It is currently mounted and must be " "unmounted before it can be destroyed.\n" "Use 'beadm " "unmount %s' to unmount the BE before destroying\nit or " "'beadm destroy -f %s'.\n"), be_name, be_name); break; case BE_ERR_DESTROY_CURR_BE: (void) fprintf(stderr, _("%s is the currently active BE and " "cannot be destroyed.\nYou must boot from another BE in " "order to destroy %s.\n"), be_name, be_name); break; case BE_ERR_ZONES_UNMOUNT: (void) fprintf(stderr, _("Unable to destroy one of " "%s's " "zone BE's.\nUse 'beadm destroy -f %s' or " "'zfs -f destroy <dataset>'.\n"), be_name, be_name); break; case BE_ERR_SS_NOENT: (void) fprintf(stderr, _("%s does not exist or appear " "to be a valid snapshot.\nPlease check that the name of " "the snapshot provided is correct.\n"), snap_name); break; case BE_ERR_PERM: case BE_ERR_ACCESS: (void) fprintf(stderr, _("Unable to destroy %s.\n"), be_name); (void) fprintf(stderr, _("You have insufficient privileges to " "execute this command.\n")); break; case BE_ERR_SS_EXISTS: (void) fprintf(stderr, _("Unable to destroy %s: " "BE has snapshots.\nUse 'beadm destroy -s %s' or " "'zfs -r destroy <dataset>'.\n"), be_name, be_name); break; default: (void) fprintf(stderr, _("Unable to destroy %s.\n"), be_name); (void) fprintf(stderr, "%s\n", be_err_to_str(err)); } out: nvlist_free(be_attrs); 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; 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_create(int argc, char **argv) { nvlist_t *be_attrs; nvlist_t *zfs_props = NULL; boolean_t activate = B_FALSE; boolean_t is_snap = B_FALSE; int c; int err = 1; char *obe_name = NULL; char *snap_name = NULL; char *nbe_zpool = NULL; char *nbe_name = NULL; char *nbe_desc = NULL; char *propname = NULL; char *propval = NULL; char *strval = NULL; while ((c = getopt(argc, argv, "ad:e:io:p:v")) != -1) { switch (c) { case 'a': activate = B_TRUE; break; case 'd': nbe_desc = optarg; break; case 'e': obe_name = optarg; break; case 'o': if (zfs_props == NULL && be_nvl_alloc(&zfs_props) != 0) return (1); propname = optarg; if ((propval = strchr(propname, '=')) == NULL) { (void) fprintf(stderr, _("missing " "'=' for -o option\n")); goto out2; } *propval = '\0'; propval++; if (nvlist_lookup_string(zfs_props, propname, &strval) == 0) { (void) fprintf(stderr, _("property '%s' " "specified multiple times\n"), propname); goto out2; } if (be_nvl_add_string(zfs_props, propname, propval) != 0) goto out2; break; case 'p': nbe_zpool = optarg; break; case 'v': libbe_print_errors(B_TRUE); break; default: usage(); goto out2; } } argc -= optind; argv += optind; if (argc != 1) { usage(); goto out2; } nbe_name = argv[0]; if ((snap_name = strrchr(nbe_name, '@')) != NULL) { if (snap_name[1] == '\0') { usage(); goto out2; } snap_name[0] = '\0'; snap_name++; is_snap = B_TRUE; } if (obe_name) { if (is_snap) { usage(); goto out2; } /* * Check if obe_name is really a snapshot name. * If so, split it out. */ if ((snap_name = strrchr(obe_name, '@')) != NULL) { if (snap_name[1] == '\0') { usage(); goto out2; } snap_name[0] = '\0'; snap_name++; } } else if (is_snap) { obe_name = nbe_name; nbe_name = NULL; } if (be_nvl_alloc(&be_attrs) != 0) goto out2; if (zfs_props != NULL && be_nvl_add_nvlist(be_attrs, BE_ATTR_ORIG_BE_NAME, zfs_props) != 0) goto out; if (obe_name != NULL && be_nvl_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name) != 0) goto out; if (snap_name != NULL && be_nvl_add_string(be_attrs, BE_ATTR_SNAP_NAME, snap_name) != 0) goto out; if (nbe_zpool != NULL && be_nvl_add_string(be_attrs, BE_ATTR_NEW_BE_POOL, nbe_zpool) != 0) goto out; if (nbe_name != NULL && be_nvl_add_string(be_attrs, BE_ATTR_NEW_BE_NAME, nbe_name) != 0) goto out; if (nbe_desc != NULL && be_nvl_add_string(be_attrs, BE_ATTR_NEW_BE_DESC, nbe_desc) != 0) goto out; if (is_snap) err = be_create_snapshot(be_attrs); else err = be_copy(be_attrs); switch (err) { case BE_SUCCESS: if (!is_snap && !nbe_name) { /* * We requested an auto named BE; find out the * name of the BE that was created for us and * the auto snapshot created from the original BE. */ if (nvlist_lookup_string(be_attrs, BE_ATTR_NEW_BE_NAME, &nbe_name) != 0) { (void) fprintf(stderr, _("failed to get %s " "attribute\n"), BE_ATTR_NEW_BE_NAME); break; } else (void) printf(_("Auto named BE: %s\n"), nbe_name); if (nvlist_lookup_string(be_attrs, BE_ATTR_SNAP_NAME, &snap_name) != 0) { (void) fprintf(stderr, _("failed to get %s " "attribute\n"), BE_ATTR_SNAP_NAME); break; } else (void) printf(_("Auto named snapshot: %s\n"), snap_name); } if (!is_snap && activate) { char *args[] = { "activate", "", NULL }; args[1] = nbe_name; optind = 1; err = be_do_activate(2, args); goto out; } (void) printf(_("Created successfully\n")); break; case BE_ERR_BE_EXISTS: (void) fprintf(stderr, _("BE %s already exists\n." "Please choose a different BE name.\n"), nbe_name); break; case BE_ERR_SS_EXISTS: (void) fprintf(stderr, _("BE %s snapshot %s already exists.\n" "Please choose a different snapshot name.\n"), obe_name, snap_name); break; case BE_ERR_PERM: case BE_ERR_ACCESS: if (is_snap) (void) fprintf(stderr, _("Unable to create snapshot " "%s.\n"), snap_name); else (void) fprintf(stderr, _("Unable to create %s.\n"), nbe_name); (void) fprintf(stderr, _("You have insufficient privileges to " "execute this command.\n")); break; default: if (is_snap) (void) fprintf(stderr, _("Unable to create snapshot " "%s.\n"), snap_name); else (void) fprintf(stderr, _("Unable to create %s.\n"), nbe_name); (void) fprintf(stderr, "%s\n", be_err_to_str(err)); } out: nvlist_free(be_attrs); out2: if (zfs_props != NULL) nvlist_free(zfs_props); return (err); }
static int be_do_activate(int argc, char **argv) { nvlist_t *be_attrs; int err = 1; int c; char *obe_name; while ((c = getopt(argc, argv, "v")) != -1) { switch (c) { case 'v': libbe_print_errors(B_TRUE); break; default: usage(); return (1); } } argc -= optind; argv += optind; if (argc != 1) { usage(); return (1); } obe_name = argv[0]; if (be_nvl_alloc(&be_attrs) != 0) return (1); if (be_nvl_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name) != 0) goto out; err = be_activate(be_attrs); switch (err) { case BE_SUCCESS: (void) printf(_("Activated successfully\n")); break; case BE_ERR_BE_NOENT: (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"), obe_name); break; case BE_ERR_PERM: case BE_ERR_ACCESS: (void) fprintf(stderr, _("Unable to activate %s.\n"), obe_name); (void) fprintf(stderr, _("You have insufficient privileges to " "execute this command.\n")); break; case BE_ERR_ACTIVATE_CURR: default: (void) fprintf(stderr, _("Unable to activate %s.\n"), obe_name); (void) fprintf(stderr, "%s\n", be_err_to_str(err)); } out: nvlist_free(be_attrs); return (err); }
static int be_do_rollback(int argc, char **argv) { nvlist_t *be_attrs; char *obe_name; char *snap_name; int err = 1; int c; while ((c = getopt(argc, argv, "v")) != -1) { switch (c) { case 'v': libbe_print_errors(B_TRUE); break; default: usage(); return (1); } } argc -= optind; argv += optind; if (argc < 1 || argc > 2) { usage(); return (1); } obe_name = argv[0]; if (argc == 2) snap_name = argv[1]; else { /* argc == 1 */ if ((snap_name = strrchr(obe_name, '@')) != NULL) { if (snap_name[1] == '\0') { usage(); return (1); } snap_name[0] = '\0'; snap_name++; } else { usage(); return (1); } } if (be_nvl_alloc(&be_attrs) != 0) return (1); if (be_nvl_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name) != 0) goto out; if (be_nvl_add_string(be_attrs, BE_ATTR_SNAP_NAME, snap_name) != 0) goto out; err = be_rollback(be_attrs); switch (err) { case BE_SUCCESS: (void) printf(_("Rolled back successfully\n")); break; case BE_ERR_BE_NOENT: (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"), obe_name); break; case BE_ERR_SS_NOENT: (void) fprintf(stderr, _("%s does not exist or appear " "to be a valid snapshot.\nPlease check that the name of " "the snapshot provided is correct.\n"), snap_name); break; case BE_ERR_PERM: case BE_ERR_ACCESS: (void) fprintf(stderr, _("Rollback of BE %s snapshot %s " "failed.\n"), obe_name, snap_name); (void) fprintf(stderr, _("You have insufficient privileges to " "execute this command.\n")); break; default: (void) fprintf(stderr, _("Rollback of BE %s snapshot %s " "failed.\n"), obe_name, snap_name); (void) fprintf(stderr, "%s\n", be_err_to_str(err)); } out: nvlist_free(be_attrs); return (err); }
static int be_do_unmount(int argc, char **argv) { nvlist_t *be_attrs; char *obe_name; int err = 1; int c; int unmount_flags = 0; while ((c = getopt(argc, argv, "fv")) != -1) { switch (c) { case 'f': unmount_flags |= BE_UNMOUNT_FLAG_FORCE; break; case 'v': libbe_print_errors(B_TRUE); break; default: usage(); return (1); } } argc -= optind; argv += optind; if (argc != 1) { usage(); return (1); } obe_name = argv[0]; if (be_nvl_alloc(&be_attrs) != 0) return (1); if (be_nvl_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name) != 0) goto out; if (be_nvl_add_uint16(be_attrs, BE_ATTR_UNMOUNT_FLAGS, unmount_flags) != 0) goto out; err = be_unmount(be_attrs); switch (err) { case BE_SUCCESS: (void) printf(_("Unmounted successfully\n")); break; case BE_ERR_BE_NOENT: (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"), obe_name); break; case BE_ERR_UMOUNT_CURR_BE: (void) fprintf(stderr, _("%s is the currently active BE.\n" "It cannot be unmounted unless another BE is the " "currently active BE.\n"), obe_name); break; case BE_ERR_UMOUNT_SHARED: (void) fprintf(stderr, _("%s is a shared file system and it " "cannot be unmounted.\n"), obe_name); break; case BE_ERR_PERM: case BE_ERR_ACCESS: (void) fprintf(stderr, _("Unable to unmount %s.\n"), obe_name); (void) fprintf(stderr, _("You have insufficient privileges to " "execute this command.\n")); break; default: (void) fprintf(stderr, _("Unable to unmount %s.\n"), obe_name); (void) fprintf(stderr, "%s\n", be_err_to_str(err)); } out: nvlist_free(be_attrs); return (err); }
static int be_do_mount(int argc, char **argv) { nvlist_t *be_attrs; boolean_t shared_fs = B_FALSE; int err = 1; int c; int mount_flags = 0; char *obe_name; char *mountpoint; char *tmp_mp = NULL; while ((c = getopt(argc, argv, "s:v")) != -1) { switch (c) { case 's': shared_fs = B_TRUE; mount_flags |= BE_MOUNT_FLAG_SHARED_FS; if (strcmp(optarg, "rw") == 0) { mount_flags |= BE_MOUNT_FLAG_SHARED_RW; } else if (strcmp(optarg, "ro") != 0) { (void) fprintf(stderr, _("The -s flag " "requires an argument [ rw | ro ]\n")); usage(); return (1); } break; case 'v': libbe_print_errors(B_TRUE); break; default: usage(); return (1); } } argc -= optind; argv += optind; if (argc < 1 || argc > 2) { usage(); return (1); } obe_name = argv[0]; if (argc == 2) { mountpoint = argv[1]; if (mountpoint[0] != '/') { (void) fprintf(stderr, _("Invalid mount point %s. " "Mount point must start with a /.\n"), mountpoint); return (1); } } else { const char *tmpdir = getenv("TMPDIR"); const char *tmpname = "tmp.XXXXXX"; int sz; if (tmpdir == NULL) tmpdir = "/tmp"; sz = asprintf(&tmp_mp, "%s/%s", tmpdir, tmpname); if (sz < 0) { (void) fprintf(stderr, _("internal error: " "out of memory\n")); return (1); } mountpoint = mkdtemp(tmp_mp); } if (be_nvl_alloc(&be_attrs) != 0) return (1); if (be_nvl_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name) != 0) goto out; if (be_nvl_add_string(be_attrs, BE_ATTR_MOUNTPOINT, mountpoint) != 0) goto out; if (shared_fs && be_nvl_add_uint16(be_attrs, BE_ATTR_MOUNT_FLAGS, mount_flags) != 0) goto out; err = be_mount(be_attrs); switch (err) { case BE_SUCCESS: (void) printf(_("Mounted successfully on: '%s'\n"), mountpoint); break; case BE_ERR_BE_NOENT: (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"), obe_name); break; case BE_ERR_MOUNTED: (void) fprintf(stderr, _("%s is already mounted.\n" "Please unmount the BE before mounting it again.\n"), obe_name); break; case BE_ERR_PERM: case BE_ERR_ACCESS: (void) fprintf(stderr, _("Unable to mount %s.\n"), obe_name); (void) fprintf(stderr, _("You have insufficient privileges to " "execute this command.\n")); break; case BE_ERR_NO_MOUNTED_ZONE: (void) fprintf(stderr, _("Mounted on '%s'.\nUnable to mount " "one of %s's zone BE's.\n"), mountpoint, obe_name); break; default: (void) fprintf(stderr, _("Unable to mount %s.\n"), obe_name); (void) fprintf(stderr, "%s\n", be_err_to_str(err)); } out: if (tmp_mp != NULL) free(tmp_mp); nvlist_free(be_attrs); return (err); }