Date: Thu, 6 Jul 2017 04:03:26 GMT From: kneitinger@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r324318 - soc2017/kneitinger/libbe-head/lib/libbe Message-ID: <201707060403.v6643Qow073327@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kneitinger Date: Thu Jul 6 04:03:25 2017 New Revision: 324318 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=324318 Log: libbe(3): add function to create boot env from exising snapshot Modified: soc2017/kneitinger/libbe-head/lib/libbe/be.c soc2017/kneitinger/libbe-head/lib/libbe/be.h soc2017/kneitinger/libbe-head/lib/libbe/be_error.c soc2017/kneitinger/libbe-head/lib/libbe/be_info.c Modified: soc2017/kneitinger/libbe-head/lib/libbe/be.c ============================================================================== --- soc2017/kneitinger/libbe-head/lib/libbe/be.c Thu Jul 6 00:53:12 2017 (r324317) +++ soc2017/kneitinger/libbe-head/lib/libbe/be.c Thu Jul 6 04:03:25 2017 (r324318) @@ -169,7 +169,7 @@ time_t rawtime; zfs_handle_t *snap_hdl; - if (!(be_valid_name(lbh, name))) { + if (be_validate_name(lbh, name)) { err = set_error(lbh, BE_ERR_INVALIDNAME); return (err); } @@ -215,9 +215,114 @@ /* + * Create the boot environment from pre-existing snapshot + */ +int +be_create_from_existing(libbe_handle_t *lbh, char *name, char *snap) +{ + int err, pos; + char be_path[MAXPATHLEN]; + char snap_name[MAXPATHLEN]; + time_t rawtime; + zfs_handle_t *snap_hdl; + + + if (be_validate_name(lbh, name)) { + err = set_error(lbh, BE_ERR_INVALIDNAME); + return (err); + } + + + /* Ensure snap exists and it's parent dataset has mountpoint of '/' */ + if (err = be_validate_snap(lbh, snap)) { + // set correct errs + return (-1); + } + + + if (err = be_root_concat(lbh, name, be_path)) { + return (err); + } + + pos = snprintf(be_path, MAXPATHLEN, "%s/%s", be_root_path(lbh), name); + + if ((pos < 0) || (pos >= MAXPATHLEN)) { + err = set_error(lbh, BE_ERR_PATHLEN); + } + + if (zfs_dataset_exists(lbh->lzh, be_path, ZFS_TYPE_DATASET)) { + err = set_error(lbh, BE_ERR_EXISTS); + return (err); + } + + + snap_hdl = zfs_open(lbh->lzh, snap, ZFS_TYPE_SNAPSHOT); + + // TODO: should any props be in the last arg (nvlist)? + if (err = zfs_clone(snap_hdl, be_path, NULL)) { + // TODO: switch on err to determine correct BE_ERR_* to return + return (-1); + } + + zfs_close(snap_hdl); + + return (err); +} + + +/* Verifies that a snapshot has a valid name, exists, and has a mountpoint of + * '/'. Returns BE_ERR_SUCCESS (0), upon success, or the relevant BE_ERR_* upon + * failure. Does not set the internal library error state. + */ +int +be_validate_snap(libbe_handle_t *lbh, char *snap_name) +{ + zfs_handle_t *zfs_hdl; + char buf[MAXPATHLEN]; + char *snap_delim; + char *mountpoint; + int err = 0; + + if (strlen(snap_name) >= MAXPATHLEN) { + return (BE_ERR_PATHLEN); + } + + if (!zfs_dataset_exists(lbh->lzh, snap_name, ZFS_TYPE_SNAPSHOT)) { + return (BE_ERR_NOENT); + } + + strncpy(buf, snap_name, MAXPATHLEN); + + if ((snap_delim = strchr(buf, '@')) == NULL) { + return (BE_ERR_INVALIDNAME); + } + + *snap_delim = '\0'; + + if ((zfs_hdl = zfs_open(lbh->lzh, buf, ZFS_TYPE_DATASET)) == NULL) { + return (BE_ERR_NOORIGIN); + } + + if (err = zfs_prop_get(zfs_hdl, ZFS_PROP_MOUNTPOINT, buf, MAXPATHLEN, + NULL, NULL, 0, 1)) { + err = BE_ERR_INVORIGIN; + } + + if ((err != 0) && (strncmp(buf, "/", MAXPATHLEN) != 0)) { + err = BE_ERR_INVORIGIN; + } + + zfs_close(zfs_hdl); + + return (BE_ERR_SUCCESS); +} + + +/* * Appends the name argument on the root boot environment path and copies the * resulting string into the result buffer. Returns 0 upon success and - * BE_ERR_PATHLEN if the resulting path is longer than MAXPATHLEN + * BE_ERR_PATHLEN if the resulting path is longer than MAXPATHLEN. Does not set + * internal library error state. */ int be_root_concat(libbe_handle_t *lbh, char *name, char *result) @@ -229,28 +334,23 @@ return (BE_ERR_SUCCESS); } - // TODO: reconsider if this, or the caller, should set_error. - return (set_error(lbh, BE_ERR_PATHLEN)); + return (BE_ERR_PATHLEN); } /* * Verifies the validity of a boot environment name (A-Za-z0-9-_.,). Returns 0 * if the name is valid, otherwise, returns the position of the first offending - * character + * character. Does not set internal library error state. */ int -be_valid_name(libbe_handle_t *lbh, char *name) +be_validate_name(libbe_handle_t *lbh, char *name) { for (int i = 0; *name; i++) { char c = *(name++); // TODO: beadm allows commas...they seem like a bad idea though if (isalnum(c) || (c == '-') || (c == '_') || (c == '.') || (c == ',')) { - // if lbh is not null, the offending char could be - // logged into some field for helpful error reporting - // also, should the set_error happen here, or in the - // caller (probably caller)?? return (i); } } Modified: soc2017/kneitinger/libbe-head/lib/libbe/be.h ============================================================================== --- soc2017/kneitinger/libbe-head/lib/libbe/be.h Thu Jul 6 00:53:12 2017 (r324317) +++ soc2017/kneitinger/libbe-head/lib/libbe/be.h Thu Jul 6 04:03:25 2017 (r324318) @@ -43,6 +43,8 @@ BE_ERR_DESTROYACT, /* cannot destroy active boot env */ BE_ERR_DESTROYMNT, /* destroying a mounted be requires force */ BE_ERR_PATHLEN, /* provided name exceeds maximum length limit */ + BE_ERR_INVORIGIN, /* snapshot origin's mountpoint is not '/' */ + BE_ERR_NOORIGIN, /* could not open snapshot's origin */ BE_ERR_UNKNOWN, /* unknown error */ } be_error_t; @@ -84,6 +86,7 @@ /* Utility Functions */ int be_root_concat(libbe_handle_t *, char *, char *); -int be_valid_name(libbe_handle_t *, char *); +int be_validate_name(libbe_handle_t *, char *); +int be_validate_snap(libbe_handle_t *, char *); #endif /* _LIBBE_H */ Modified: soc2017/kneitinger/libbe-head/lib/libbe/be_error.c ============================================================================== --- soc2017/kneitinger/libbe-head/lib/libbe/be_error.c Thu Jul 6 00:53:12 2017 (r324317) +++ soc2017/kneitinger/libbe-head/lib/libbe/be_error.c Thu Jul 6 04:03:25 2017 (r324318) @@ -64,6 +64,12 @@ case BE_ERR_PATHLEN: return ("provided path name exceeds maximum length limit"); + case BE_ERR_INVORIGIN: + return ("snapshot origin's mountpoint is not \"/\""); + + case BE_ERR_NOORIGIN: + return ("could not open snapshot's origin"); + case BE_ERR_UNKNOWN: return ("unknown error"); Modified: soc2017/kneitinger/libbe-head/lib/libbe/be_info.c ============================================================================== --- soc2017/kneitinger/libbe-head/lib/libbe/be_info.c Thu Jul 6 00:53:12 2017 (r324317) +++ soc2017/kneitinger/libbe-head/lib/libbe/be_info.c Thu Jul 6 04:03:25 2017 (r324318) @@ -117,41 +117,41 @@ nvlist_add_string(props, "mountpoint", buf); } - if ((zfs_prop_get(zfs_hdl, ZFS_PROP_ORIGIN, buf, 512, - NULL, NULL, 0, 1)) == 0) { + if (zfs_prop_get(zfs_hdl, ZFS_PROP_ORIGIN, buf, 512, + NULL, NULL, 0, 1)) { nvlist_add_string(props, "origin", buf); } - if ((zfs_prop_get(zfs_hdl, ZFS_PROP_CREATION, buf, 512, - NULL, NULL, 0, 1)) == 0) { + if (zfs_prop_get(zfs_hdl, ZFS_PROP_CREATION, buf, 512, + NULL, NULL, 0, 1)) { nvlist_add_string(props, "creation", buf); } nvlist_add_boolean_value(props, "active", (strcmp(be_active_path(lbh), dataset) == 0)); - if ((zfs_prop_get(zfs_hdl, ZFS_PROP_USED, buf, 512, - NULL, NULL, 0, 1)) == 0) { + if (zfs_prop_get(zfs_hdl, ZFS_PROP_USED, buf, 512, + NULL, NULL, 0, 1)) { nvlist_add_string(props, "used", buf); } - if ((zfs_prop_get(zfs_hdl, ZFS_PROP_USEDDS, buf, 512, - NULL, NULL, 0, 1)) == 0) { + if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDDS, buf, 512, + NULL, NULL, 0, 1)) { nvlist_add_string(props, "usedds", buf); } - if ((zfs_prop_get(zfs_hdl, ZFS_PROP_USEDSNAP, buf, 512, - NULL, NULL, 0, 1)) == 0) { + if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDSNAP, buf, 512, + NULL, NULL, 0, 1)) { nvlist_add_string(props, "usedsnap", buf); } - if ((zfs_prop_get(zfs_hdl, ZFS_PROP_USEDREFRESERV, buf, 512, - NULL, NULL, 0, 1)) == 0) { + if (zfs_prop_get(zfs_hdl, ZFS_PROP_USEDREFRESERV, buf, 512, + NULL, NULL, 0, 1)) { nvlist_add_string(props, "usedrefreserv", buf); } - if ((zfs_prop_get(zfs_hdl, ZFS_PROP_REFERENCED, buf, 512, - NULL, NULL, 0, 1)) == 0) { + if (zfs_prop_get(zfs_hdl, ZFS_PROP_REFERENCED, buf, 512, + NULL, NULL, 0, 1)) { nvlist_add_string(props, "referenced", buf); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201707060403.v6643Qow073327>