be.c (73c3d60843efc6116e8dc3bbbf8c32948490d850) be.c (6d4b1d241d7b3e471c61cae3775d511e6864e3b3)
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2017 Kyle J. Kneitinger <kyle@kneit.in>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 601 unchanged lines hidden (view full) ---

610 return (set_error(lbh, BE_ERR_MOUNTED));
611
612 if (!zfs_dataset_exists(lbh->lzh, full_old, ZFS_TYPE_DATASET))
613 return (set_error(lbh, BE_ERR_NOENT));
614
615 if (zfs_dataset_exists(lbh->lzh, full_new, ZFS_TYPE_DATASET))
616 return (set_error(lbh, BE_ERR_EXISTS));
617
1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2017 Kyle J. Kneitinger <kyle@kneit.in>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 601 unchanged lines hidden (view full) ---

610 return (set_error(lbh, BE_ERR_MOUNTED));
611
612 if (!zfs_dataset_exists(lbh->lzh, full_old, ZFS_TYPE_DATASET))
613 return (set_error(lbh, BE_ERR_NOENT));
614
615 if (zfs_dataset_exists(lbh->lzh, full_new, ZFS_TYPE_DATASET))
616 return (set_error(lbh, BE_ERR_EXISTS));
617
618 /* XXX TODO
619 * - What about mounted BEs?
620 * - if mounted error out unless a force flag is set?
621 */
622 if ((zfs_hdl = zfs_open(lbh->lzh, full_old,
623 ZFS_TYPE_FILESYSTEM)) == NULL)
624 return (set_error(lbh, BE_ERR_ZFSOPEN));
625
618 if ((zfs_hdl = zfs_open(lbh->lzh, full_old,
619 ZFS_TYPE_FILESYSTEM)) == NULL)
620 return (set_error(lbh, BE_ERR_ZFSOPEN));
621
622 /* XXX TODO: Allow a force flag */
623 if (zfs_is_mounted(zfs_hdl, NULL)) {
624 zfs_close(zfs_hdl);
625 return (set_error(lbh, BE_ERR_MOUNTED));
626 }
627
626 /* recurse, nounmount, forceunmount */
627 struct renameflags flags = { 0, 0, 0 };
628
629 err = zfs_rename(zfs_hdl, NULL, full_new, flags);
630
631 zfs_close(zfs_hdl);
632
633 return (set_error(lbh, err));

--- 4 unchanged lines hidden (view full) ---

638be_export(libbe_handle_t *lbh, const char *bootenv, int fd)
639{
640 char snap_name[BE_MAXPATHLEN];
641 char buf[BE_MAXPATHLEN];
642 zfs_handle_t *zfs;
643 int err;
644
645 if ((err = be_snapshot(lbh, bootenv, NULL, true, snap_name)) != 0)
628 /* recurse, nounmount, forceunmount */
629 struct renameflags flags = { 0, 0, 0 };
630
631 err = zfs_rename(zfs_hdl, NULL, full_new, flags);
632
633 zfs_close(zfs_hdl);
634
635 return (set_error(lbh, err));

--- 4 unchanged lines hidden (view full) ---

640be_export(libbe_handle_t *lbh, const char *bootenv, int fd)
641{
642 char snap_name[BE_MAXPATHLEN];
643 char buf[BE_MAXPATHLEN];
644 zfs_handle_t *zfs;
645 int err;
646
647 if ((err = be_snapshot(lbh, bootenv, NULL, true, snap_name)) != 0)
646 /* XXX TODO error handle */
647 return (-1);
648 /* Use the error set by be_snapshot */
649 return (err);
648
649 be_root_concat(lbh, snap_name, buf);
650
651 if ((zfs = zfs_open(lbh->lzh, buf, ZFS_TYPE_DATASET)) == NULL)
652 return (set_error(lbh, BE_ERR_ZFSOPEN));
653
654 err = zfs_send_one(zfs, NULL, fd, 0);
650
651 be_root_concat(lbh, snap_name, buf);
652
653 if ((zfs = zfs_open(lbh->lzh, buf, ZFS_TYPE_DATASET)) == NULL)
654 return (set_error(lbh, BE_ERR_ZFSOPEN));
655
656 err = zfs_send_one(zfs, NULL, fd, 0);
657 zfs_close(zfs);
658
655 return (err);
656}
657
658
659int
660be_import(libbe_handle_t *lbh, const char *bootenv, int fd)
661{
662 char buf[BE_MAXPATHLEN];

--- 46 unchanged lines hidden (view full) ---

709
710 be_root_concat(lbh, bootenv, buf);
711
712 err = zfs_clone(zfs, buf, props);
713 zfs_close(zfs);
714
715 nvlist_free(props);
716
659 return (err);
660}
661
662
663int
664be_import(libbe_handle_t *lbh, const char *bootenv, int fd)
665{
666 char buf[BE_MAXPATHLEN];

--- 46 unchanged lines hidden (view full) ---

713
714 be_root_concat(lbh, bootenv, buf);
715
716 err = zfs_clone(zfs, buf, props);
717 zfs_close(zfs);
718
719 nvlist_free(props);
720
717 /* XXX TODO: recursively delete nbuf dataset */
718 return (err);
721 return (be_destroy(lbh, nbuf, 0));
719}
720
721
722int
723be_add_child(libbe_handle_t *lbh, const char *child_path, bool cp_if_exists)
724{
725 struct stat sb;
726 char active[BE_MAXPATHLEN];
727 char buf[BE_MAXPATHLEN];
728 nvlist_t *props;
729 const char *s;
730 zfs_handle_t *zfs;
722}
723
724
725int
726be_add_child(libbe_handle_t *lbh, const char *child_path, bool cp_if_exists)
727{
728 struct stat sb;
729 char active[BE_MAXPATHLEN];
730 char buf[BE_MAXPATHLEN];
731 nvlist_t *props;
732 const char *s;
733 zfs_handle_t *zfs;
731 long snap_name;
732 int err, pos;
734 int err;
733
734 /* Require absolute paths */
735 if (*child_path != '/')
735
736 /* Require absolute paths */
737 if (*child_path != '/')
736 /* XXX TODO: create appropriate error */
737 return (-1);
738 return (set_error(lbh, BE_ERR_BADPATH));
738
739
739 strncpy(active, be_active_path(lbh), BE_MAXPATHLEN);
740 strlcpy(active, be_active_path(lbh), BE_MAXPATHLEN);
740 strcpy(buf, active);
741
742 /* Create non-mountable parent dataset(s) */
743 s = child_path;
744 for (char *p; (p = strchr(s+1, '/')) != NULL; s = p) {
745 size_t len = p - s;
746 strncat(buf, s, len);
747
748 nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP);
749 nvlist_add_string(props, "canmount", "off");
750 nvlist_add_string(props, "mountpoint", "none");
751 zfs_create(lbh->lzh, buf, ZFS_TYPE_DATASET, props);
752 nvlist_free(props);
753 }
754
755 /* Path does not exist as a descendent of / yet */
741 strcpy(buf, active);
742
743 /* Create non-mountable parent dataset(s) */
744 s = child_path;
745 for (char *p; (p = strchr(s+1, '/')) != NULL; s = p) {
746 size_t len = p - s;
747 strncat(buf, s, len);
748
749 nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP);
750 nvlist_add_string(props, "canmount", "off");
751 nvlist_add_string(props, "mountpoint", "none");
752 zfs_create(lbh->lzh, buf, ZFS_TYPE_DATASET, props);
753 nvlist_free(props);
754 }
755
756 /* Path does not exist as a descendent of / yet */
756 pos = strlen(active);
757 if (strlcat(active, child_path, BE_MAXPATHLEN) >= BE_MAXPATHLEN)
758 return (set_error(lbh, BE_ERR_PATHLEN));
757
759
758 /* XXX TODO: Verify that resulting str is less than BE_MAXPATHLEN */
759 strncpy(&active[pos], child_path, BE_MAXPATHLEN-pos);
760
761 if (stat(child_path, &sb) != 0) {
762 /* Verify that error is ENOENT */
760 if (stat(child_path, &sb) != 0) {
761 /* Verify that error is ENOENT */
763 if (errno != 2)
764 /* XXX TODO: create appropriate error */
765 return (-1);
762 if (errno != ENOENT)
763 return (set_error(lbh, BE_ERR_NOENT));
766
767 nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP);
768 nvlist_add_string(props, "canmount", "noauto");
769 nvlist_add_string(props, "mountpoint", child_path);
770
771 /* Create */
772 if ((err =
773 zfs_create(lbh->lzh, active, ZFS_TYPE_DATASET, props)) != 0)
774 /* XXX TODO handle error */
764
765 nvlist_alloc(&props, NV_UNIQUE_NAME, KM_SLEEP);
766 nvlist_add_string(props, "canmount", "noauto");
767 nvlist_add_string(props, "mountpoint", child_path);
768
769 /* Create */
770 if ((err =
771 zfs_create(lbh->lzh, active, ZFS_TYPE_DATASET, props)) != 0)
772 /* XXX TODO handle error */
775 return (-1);
773 return (set_error(lbh, BE_ERR_UNKNOWN));
776 nvlist_free(props);
777
778 if ((zfs =
779 zfs_open(lbh->lzh, active, ZFS_TYPE_DATASET)) == NULL)
774 nvlist_free(props);
775
776 if ((zfs =
777 zfs_open(lbh->lzh, active, ZFS_TYPE_DATASET)) == NULL)
780 /* XXX TODO handle error */
781 return (-1);
778 return (set_error(lbh, BE_ERR_ZFSOPEN));
782
783 /* Set props */
784 if ((err = zfs_prop_set(zfs, "canmount", "noauto")) != 0)
785 /* TODO handle error */
779
780 /* Set props */
781 if ((err = zfs_prop_set(zfs, "canmount", "noauto")) != 0)
782 /* TODO handle error */
786 return (-1);
783 return (set_error(lbh, BE_ERR_UNKNOWN));
787 } else if (cp_if_exists) {
788 /* Path is already a descendent of / and should be copied */
789
790 /* XXX TODO ? */
791
792 /*
793 * Establish if the existing path is a zfs dataset or just
794 * the subdirectory of one
795 */
784 } else if (cp_if_exists) {
785 /* Path is already a descendent of / and should be copied */
786
787 /* XXX TODO ? */
788
789 /*
790 * Establish if the existing path is a zfs dataset or just
791 * the subdirectory of one
792 */
793 strlcpy(buf, "/tmp/be_snap.XXXXX", sizeof(buf));
794 if (mktemp(buf) == NULL)
795 return (set_error(lbh, BE_ERR_UNKNOWN));
796
796
797 /* XXX TODO: use mktemp */
798 snap_name = random();
799
800 snprintf(buf, BE_MAXPATHLEN, "%s@%ld", child_path, snap_name);
801
802 if ((err = zfs_snapshot(lbh->lzh, buf, false, NULL)) != 0)
803 /* XXX TODO correct error */
797 if ((err = zfs_snapshot(lbh->lzh, buf, false, NULL)) != 0)
798 /* XXX TODO correct error */
804 return (-1);
799 return (set_error(lbh, BE_ERR_UNKNOWN));
805
806 /* Clone */
807 if ((zfs =
808 zfs_open(lbh->lzh, buf, ZFS_TYPE_SNAPSHOT)) == NULL)
800
801 /* Clone */
802 if ((zfs =
803 zfs_open(lbh->lzh, buf, ZFS_TYPE_SNAPSHOT)) == NULL)
809 /* XXX TODO correct error */
810 return (-1);
804 return (BE_ERR_ZFSOPEN);
811
812 if ((err = zfs_clone(zfs, active, NULL)) != 0)
813 /* XXX TODO correct error */
805
806 if ((err = zfs_clone(zfs, active, NULL)) != 0)
807 /* XXX TODO correct error */
814 return (-1);
808 return (set_error(lbh, BE_ERR_UNKNOWN));
815
816 /* set props */
809
810 /* set props */
811 zfs_close(zfs);
817 } else
818 /* TODO: error code for exists, but not cp? */
812 } else
813 /* TODO: error code for exists, but not cp? */
819 return (-1);
814 return (set_error(lbh, BE_ERR_EXISTS));
820
821 return (BE_ERR_SUCCESS);
822}
823
824static int
825be_set_nextboot(libbe_handle_t *lbh, nvlist_t *config, uint64_t pool_guid,
826 const char *zfsdev)
827{

--- 75 unchanged lines hidden ---
815
816 return (BE_ERR_SUCCESS);
817}
818
819static int
820be_set_nextboot(libbe_handle_t *lbh, nvlist_t *config, uint64_t pool_guid,
821 const char *zfsdev)
822{

--- 75 unchanged lines hidden ---