Blob Blame History Raw
 liblvm/lvm_base.c |  75 ++++++++++++---
 liblvm/lvm_lv.c   | 199 ++++++++++++++++++++++++++++++---------
 liblvm/lvm_misc.c |  25 +++++
 liblvm/lvm_misc.h |  12 +++
 liblvm/lvm_pv.c   |  93 ++++++++++++++++---
 liblvm/lvm_vg.c   | 271 ++++++++++++++++++++++++++++++++++++++++--------------
 6 files changed, 538 insertions(+), 137 deletions(-)

diff --git a/liblvm/lvm_base.c b/liblvm/lvm_base.c
index 01ea0d7..7327a1d 100644
--- a/liblvm/lvm_base.c
+++ b/liblvm/lvm_base.c
@@ -18,13 +18,14 @@
 #include "lvm-version.h"
 #include "metadata-exported.h"
 #include "lvm2app.h"
+#include "lvm_misc.h"
 
 const char *lvm_library_get_version(void)
 {
 	return LVM_VERSION;
 }
 
-lvm_t lvm_init(const char *system_dir)
+static lvm_t _lvm_init(const char *system_dir)
 {
 	struct cmd_context *cmd;
 
@@ -69,18 +70,34 @@ lvm_t lvm_init(const char *system_dir)
 	return (lvm_t) cmd;
 }
 
+
+lvm_t lvm_init(const char *system_dir)
+{
+	lvm_t h = NULL;
+	struct saved_env e = store_user_env(NULL);
+	h = _lvm_init(system_dir);
+	restore_user_env(&e);
+	return h;
+}
+
 void lvm_quit(lvm_t libh)
 {
+	struct saved_env e = store_user_env((struct cmd_context *)libh);
 	destroy_toolcontext((struct cmd_context *)libh);
 	udev_fin_library_context();
+	restore_user_env(&e);
 }
 
 int lvm_config_reload(lvm_t libh)
 {
+	int rc = 0;
+
 	/* FIXME: re-init locking needed here? */
+	struct saved_env e = store_user_env((struct cmd_context *)libh);
 	if (!refresh_toolcontext((struct cmd_context *)libh))
-		return -1;
-	return 0;
+		rc = -1;
+	restore_user_env(&e);
+	return rc;
 }
 
 /*
@@ -88,45 +105,79 @@ int lvm_config_reload(lvm_t libh)
  */
 int lvm_config_override(lvm_t libh, const char *config_settings)
 {
+	int rc = 0;
 	struct cmd_context *cmd = (struct cmd_context *)libh;
+	struct saved_env e = store_user_env((struct cmd_context *)libh);
+
 	if (override_config_tree_from_string(cmd, config_settings))
-		return -1;
-	return 0;
+		rc = -1;
+	restore_user_env(&e);
+	return rc;
 }
 
 int lvm_config_find_bool(lvm_t libh, const char *config_path, int fail)
 {
-	return find_config_tree_bool((struct cmd_context *)libh, config_path, fail);
+	int rc = 0;
+	struct cmd_context *cmd = (struct cmd_context *)libh;
+	struct saved_env e = store_user_env(cmd);
+
+	rc = find_config_tree_bool(cmd, config_path, fail);
+	restore_user_env(&e);
+	return rc;
 }
 
 int lvm_errno(lvm_t libh)
 {
-	return stored_errno();
+	int rc;
+	struct saved_env e = store_user_env((struct cmd_context *)libh);
+
+	rc = stored_errno();
+	restore_user_env(&e);
+	return rc;
 }
 
 const char *lvm_errmsg(lvm_t libh)
 {
-	return stored_errmsg();
+	const char *rc = NULL;
+	struct saved_env e = store_user_env((struct cmd_context *)libh);
+
+	rc = stored_errmsg();
+	restore_user_env(&e);
+	return rc;
 }
 
 const char *lvm_vgname_from_pvid(lvm_t libh, const char *pvid)
 {
+	const char *rc = NULL;
 	struct cmd_context *cmd = (struct cmd_context *)libh;
 	struct id id;
+	struct saved_env e = store_user_env((struct cmd_context *)libh);
 
-	if (!id_read_format(&id, pvid)) {
+	if (id_read_format(&id, pvid)) {
+		rc = find_vgname_from_pvid(cmd, (char *)id.uuid);
+	} else {
 		log_error(INTERNAL_ERROR "Unable to convert uuid");
-		return NULL;
 	}
-	return find_vgname_from_pvid(cmd, (char *)id.uuid);
+	restore_user_env(&e);
+	return rc;
 }
 
 const char *lvm_vgname_from_device(lvm_t libh, const char *device)
 {
+	const char *rc = NULL;
 	struct cmd_context *cmd = (struct cmd_context *)libh;
-	return find_vgname_from_pvname(cmd, device);
+	struct saved_env e = store_user_env(cmd);
+
+	rc = find_vgname_from_pvname(cmd, device);
+	restore_user_env(&e);
+	return rc;
 }
 
+
+/*
+ * No context to work with, so no ability to save off and restore env is not
+ * available and is not needed.
+ */
 float lvm_percent_to_float(percent_t v)
 {
 	return percent_to_float(v);
diff --git a/liblvm/lvm_lv.c b/liblvm/lvm_lv.c
index b2a604d..b648378 100644
--- a/liblvm/lvm_lv.c
+++ b/liblvm/lvm_lv.c
@@ -34,50 +34,114 @@ static int _lv_check_handle(const lv_t lv, const int vg_writeable)
 /* FIXME: have lib/report/report.c _disp function call lv_size()? */
 uint64_t lvm_lv_get_size(const lv_t lv)
 {
-	return SECTOR_SIZE * lv_size(lv);
+	uint64_t rc;
+	struct saved_env e = store_user_env(lv->vg->cmd);
+	rc = SECTOR_SIZE * lv_size(lv);
+	restore_user_env(&e);
+	return rc;
 }
 
 const char *lvm_lv_get_uuid(const lv_t lv)
 {
-	return lv_uuid_dup(lv);
+	const char *rc;
+	struct saved_env e = store_user_env(lv->vg->cmd);
+	rc = lv_uuid_dup(lv);
+	restore_user_env(&e);
+	return rc;
 }
 
 const char *lvm_lv_get_name(const lv_t lv)
 {
 	return dm_pool_strndup(lv->vg->vgmem, (const char *)lv->name,
 			       NAME_LEN+1);
+
+	const char *rc;
+	struct saved_env e = store_user_env(lv->vg->cmd);
+	rc = dm_pool_strndup(lv->vg->vgmem, (const char *)lv->name,
+				NAME_LEN+1);
+	restore_user_env(&e);
+	return rc;
 }
 
 struct lvm_property_value lvm_lv_get_property(const lv_t lv, const char *name)
 {
-	return get_property(NULL, NULL, lv, NULL, NULL, name);
+	struct lvm_property_value rc;
+	struct saved_env e = store_user_env(lv->vg->cmd);
+	rc = get_property(NULL, NULL, lv, NULL, NULL, name);
+	restore_user_env(&e);
+	return rc;
 }
 
 struct lvm_property_value lvm_lvseg_get_property(const lvseg_t lvseg,
 						 const char *name)
 {
-	return get_property(NULL, NULL, NULL, lvseg, NULL, name);
+	struct lvm_property_value rc;
+	struct saved_env e = store_user_env(lvseg->lv->vg->cmd);
+	rc = get_property(NULL, NULL, NULL, lvseg, NULL, name);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_lv_is_active(const lv_t lv)
 {
+	uint64_t rc = 0;
 	struct lvinfo info;
+	struct saved_env e = store_user_env(lv->vg->cmd);
+
 	if (lv_info(lv->vg->cmd, lv, 0, &info, 0, 0) &&
 	    info.exists && info.live_table)
-		return 1;
-	return 0;
+		rc = 1;
+
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_lv_is_suspended(const lv_t lv)
 {
+	uint64_t rc = 0;
 	struct lvinfo info;
+	struct saved_env e = store_user_env(lv->vg->cmd);
+
 	if (lv_info(lv->vg->cmd, lv, 0, &info, 0, 0) &&
 	    info.exists && info.suspended)
-		return 1;
-	return 0;
+		rc = 1;
+	restore_user_env(&e);
+	return rc;
 }
 
-int lvm_lv_add_tag(lv_t lv, const char *tag)
+static lv_t _lvm_lv_from_uuid(vg_t vg, const char *uuid)
+{
+	struct lv_list *lvl;
+	struct id id;
+
+	if (strlen(uuid) < ID_LEN) {
+		log_errno (EINVAL, "Invalid UUID string length");
+		return NULL;
+	}
+
+	if (!id_read_format(&id, uuid)) {
+		log_errno(EINVAL, "Invalid UUID format.");
+		return NULL;
+	}
+
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		if (id_equal(&vg->id, &lvl->lv->lvid.id[0]) &&
+		    id_equal(&id, &lvl->lv->lvid.id[1]))
+			return lvl->lv;
+	}
+	return NULL;
+}
+
+lv_t lvm_lv_from_uuid(vg_t vg, const char *uuid)
+{
+	lv_t rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = _lvm_lv_from_uuid(vg, uuid);
+	restore_user_env(&e);
+	return rc;
+}
+
+static int _lvm_lv_add_tag(lv_t lv, const char *tag)
 {
 	if (_lv_check_handle(lv, 1))
 		return -1;
@@ -86,8 +150,16 @@ int lvm_lv_add_tag(lv_t lv, const char *tag)
 	return 0;
 }
 
+int lvm_lv_add_tag(lv_t lv, const char *tag)
+{
+	int rc;
+	struct saved_env e = store_user_env(lv->vg->cmd);
+	rc = _lvm_lv_add_tag(lv, tag);
+	restore_user_env(&e);
+	return rc;
+}
 
-int lvm_lv_remove_tag(lv_t lv, const char *tag)
+static int _lvm_lv_remove_tag(lv_t lv, const char *tag)
 {
 	if (_lv_check_handle(lv, 1))
 		return -1;
@@ -96,10 +168,23 @@ int lvm_lv_remove_tag(lv_t lv, const char *tag)
 	return 0;
 }
 
+int lvm_lv_remove_tag(lv_t lv, const char *tag)
+{
+	int rc;
+	struct saved_env e = store_user_env(lv->vg->cmd);
+	rc = _lvm_lv_remove_tag(lv, tag);
+	restore_user_env(&e);
+	return rc;
+}
+
 
 struct dm_list *lvm_lv_get_tags(const lv_t lv)
 {
-	return tag_list_copy(lv->vg->vgmem, &lv->tags);
+	struct dm_list *rc;
+	struct saved_env e = store_user_env(lv->vg->cmd);
+	rc = tag_list_copy(lv->vg->vgmem, &lv->tags);
+	restore_user_env(&e);
+	return rc;
 }
 
 /* Set defaults for non-segment specific LV parameters */
@@ -142,7 +227,7 @@ static int _lv_set_default_linear_params(struct cmd_context *cmd,
  * lvm_vg_write.  However, this appears to be non-trivial change until
  * lv_create_single is refactored by segtype.
  */
-lv_t lvm_vg_create_lv_linear(vg_t vg, const char *name, uint64_t size)
+static lv_t _lvm_vg_create_lv_linear(vg_t vg, const char *name, uint64_t size)
 {
 	struct lvcreate_params lp = { 0 };
 	uint64_t extents;
@@ -167,11 +252,20 @@ lv_t lvm_vg_create_lv_linear(vg_t vg, const char *name, uint64_t size)
 	return (lv_t) lv;
 }
 
+lv_t lvm_vg_create_lv_linear(vg_t vg, const char *name, uint64_t size)
+{
+	lv_t rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = _lvm_vg_create_lv_linear(vg, name, size);
+	restore_user_env(&e);
+	return rc;
+}
+
 /*
  * FIXME: This function should probably not commit to disk but require calling
  * lvm_vg_write.
  */
-int lvm_vg_remove_lv(lv_t lv)
+static int _lvm_vg_remove_lv(lv_t lv)
 {
 	if (!lv || !lv->vg || vg_read_error(lv->vg))
 		return -1;
@@ -182,7 +276,16 @@ int lvm_vg_remove_lv(lv_t lv)
 	return 0;
 }
 
-int lvm_lv_activate(lv_t lv)
+int lvm_vg_remove_lv(lv_t lv)
+{
+	int rc;
+	struct saved_env e = store_user_env(lv->vg->cmd);
+	rc = _lvm_vg_remove_lv(lv);
+	restore_user_env(&e);
+	return rc;
+}
+
+static int _lvm_lv_activate(lv_t lv)
 {
 	if (!lv || !lv->vg || vg_read_error(lv->vg) || !lv->vg->cmd)
 		return -1;
@@ -217,7 +320,16 @@ int lvm_lv_activate(lv_t lv)
 	return 0;
 }
 
-int lvm_lv_deactivate(lv_t lv)
+int lvm_lv_activate(lv_t lv)
+{
+	int rc;
+	struct saved_env e = store_user_env(lv->vg->cmd);
+	rc = _lvm_lv_activate(lv);
+	restore_user_env(&e);
+	return rc;
+}
+
+static int _lvm_lv_deactivate(lv_t lv)
 {
 	if (!lv || !lv->vg || vg_read_error(lv->vg) || !lv->vg->cmd)
 		return -1;
@@ -230,7 +342,16 @@ int lvm_lv_deactivate(lv_t lv)
 	return 0;
 }
 
-struct dm_list *lvm_lv_list_lvsegs(lv_t lv)
+int lvm_lv_deactivate(lv_t lv)
+{
+	int rc;
+	struct saved_env e = store_user_env(lv->vg->cmd);
+	rc = _lvm_lv_deactivate(lv);
+	restore_user_env(&e);
+	return rc;
+}
+
+static struct dm_list *_lvm_lv_list_lvsegs(lv_t lv)
 {
 	struct dm_list *list;
 	lvseg_list_t *lvseg;
@@ -257,47 +378,41 @@ struct dm_list *lvm_lv_list_lvsegs(lv_t lv)
 	return list;
 }
 
-lv_t lvm_lv_from_name(vg_t vg, const char *name)
+struct dm_list *lvm_lv_list_lvsegs(lv_t lv)
 {
-	struct lv_list *lvl;
-
-	dm_list_iterate_items(lvl, &vg->lvs) {
-		if (!strcmp(name, lvl->lv->name))
-			return lvl->lv;
-	}
-	return NULL;
+	struct dm_list *rc;
+	struct saved_env e = store_user_env(lv->vg->cmd);
+	rc = _lvm_lv_list_lvsegs(lv);
+	restore_user_env(&e);
+	return rc;
 }
 
-lv_t lvm_lv_from_uuid(vg_t vg, const char *uuid)
+lv_t lvm_lv_from_name(vg_t vg, const char *name)
 {
+	lv_t rc = NULL;
 	struct lv_list *lvl;
-	struct id id;
-
-	if (strlen(uuid) < ID_LEN) {
-		log_errno (EINVAL, "Invalid UUID string length");
-		return NULL;
-	}
-
-	if (!id_read_format(&id, uuid)) {
-		log_errno(EINVAL, "Invalid UUID format.");
-		return NULL;
-	}
 
+	struct saved_env e = store_user_env(vg->cmd);
 	dm_list_iterate_items(lvl, &vg->lvs) {
-		if (id_equal(&vg->id, &lvl->lv->lvid.id[0]) &&
-		    id_equal(&id, &lvl->lv->lvid.id[1]))
-			return lvl->lv;
+		if (!strcmp(name, lvl->lv->name)) {
+			rc = lvl->lv;
+			break;
+		}
 	}
-	return NULL;
+	restore_user_env(&e);
+	return rc;
 }
 
 int lvm_lv_rename(lv_t lv, const char *new_name)
 {
+	int rc = 0;
+	struct saved_env e = store_user_env(lv->vg->cmd);
 	if (!lv_rename(lv->vg->cmd, lv, new_name)) {
 		log_verbose("LV Rename failed.");
-		return -1;
+		rc = -1;
 	}
-	return 0;
+	restore_user_env(&e);
+	return rc;
 }
 
 int lvm_lv_resize(const lv_t lv, uint64_t new_size)
diff --git a/liblvm/lvm_misc.c b/liblvm/lvm_misc.c
index 0a0ea12..8c30781 100644
--- a/liblvm/lvm_misc.c
+++ b/liblvm/lvm_misc.c
@@ -114,3 +114,28 @@ int set_property(const pv_t pv, const vg_t vg, const lv_t lv,
 	}
 	return 0;
 }
+
+/*
+ * Store anything that may need to be restored back to the user on library
+ * call exit.  Currently the only thing we are preserving is the users umask.
+ */
+struct saved_env store_user_env(struct cmd_context *cmd)
+{
+	struct saved_env env = {0};
+
+	if (cmd) {
+		env.user_umask = umask(cmd->default_settings.umask);
+	} else {
+		env.user_umask = umask(0);
+		umask(env.user_umask);
+	}
+
+	return env;
+}
+
+void restore_user_env(const struct saved_env *env)
+{
+	if (env) {
+		umask(env->user_umask);
+	}
+}
diff --git a/liblvm/lvm_misc.h b/liblvm/lvm_misc.h
index a0324b8..1b9a546 100644
--- a/liblvm/lvm_misc.h
+++ b/liblvm/lvm_misc.h
@@ -16,6 +16,18 @@
 
 #include "libdevmapper.h"
 #include "lvm2app.h"
+#include "toolcontext.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+struct saved_env
+{
+	mode_t user_umask;
+};
+
+struct saved_env store_user_env(struct cmd_context *cmd);
+void restore_user_env(const struct saved_env *env);
 
 struct dm_list *tag_list_copy(struct dm_pool *p, struct dm_list *tag_list);
 struct lvm_property_value get_property(const pv_t pv, const vg_t vg,
diff --git a/liblvm/lvm_pv.c b/liblvm/lvm_pv.c
index 90edaed..245ea22 100644
--- a/liblvm/lvm_pv.c
+++ b/liblvm/lvm_pv.c
@@ -20,47 +20,78 @@
 
 const char *lvm_pv_get_uuid(const pv_t pv)
 {
-	return pv_uuid_dup(pv);
+	const char *rc;
+	struct saved_env e = store_user_env(pv->vg->cmd);
+	rc = pv_uuid_dup(pv);
+	restore_user_env(&e);
+	return rc;
 }
 
 const char *lvm_pv_get_name(const pv_t pv)
 {
-	return dm_pool_strndup(pv->vg->vgmem,
-			       (const char *)pv_dev_name(pv), NAME_LEN + 1);
+	const char *rc;
+	struct saved_env e = store_user_env(pv->vg->cmd);
+	rc = dm_pool_strndup(pv->vg->vgmem, pv_dev_name(pv), NAME_LEN);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_pv_get_mda_count(const pv_t pv)
 {
-	return (uint64_t) pv_mda_count(pv);
+	uint64_t rc;
+	struct saved_env e = store_user_env(pv->vg->cmd);
+	rc = (uint64_t) pv_mda_count(pv);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_pv_get_dev_size(const pv_t pv)
 {
-	return (uint64_t) SECTOR_SIZE * pv_dev_size(pv);
+	uint64_t rc;
+	struct saved_env e = store_user_env(pv->vg->cmd);
+	rc = SECTOR_SIZE * pv_dev_size(pv);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_pv_get_size(const pv_t pv)
 {
-	return (uint64_t) SECTOR_SIZE * pv_size_field(pv);
+	uint64_t rc;
+	struct saved_env e = store_user_env(pv->vg->cmd);
+	rc = SECTOR_SIZE * pv_size_field(pv);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_pv_get_free(const pv_t pv)
 {
-	return (uint64_t) SECTOR_SIZE * pv_free(pv);
+	uint64_t rc;
+	struct saved_env e = store_user_env(pv->vg->cmd);
+	rc = SECTOR_SIZE * pv_free(pv);
+	restore_user_env(&e);
+	return rc;
 }
 
 struct lvm_property_value lvm_pv_get_property(const pv_t pv, const char *name)
 {
-	return get_property(pv, NULL, NULL, NULL, NULL, name);
+	struct lvm_property_value rc;
+	struct saved_env e = store_user_env(pv->vg->cmd);
+	rc = get_property(pv, NULL, NULL, NULL, NULL, name);
+	restore_user_env(&e);
+	return rc;
 }
 
 struct lvm_property_value lvm_pvseg_get_property(const pvseg_t pvseg,
 						 const char *name)
 {
-	return get_property(NULL, NULL, NULL, NULL, pvseg, name);
+	struct lvm_property_value rc;
+	struct saved_env e = store_user_env(pvseg->pv->vg->cmd);
+	rc = get_property(NULL, NULL, NULL, NULL, pvseg, name);
+	restore_user_env(&e);
+	return rc;
 }
 
-struct dm_list *lvm_pv_list_pvsegs(pv_t pv)
+static struct dm_list *_lvm_pv_list_pvsegs(pv_t pv)
 {
 	struct dm_list *list;
 	pvseg_list_t *pvseg;
@@ -87,18 +118,32 @@ struct dm_list *lvm_pv_list_pvsegs(pv_t pv)
 	return list;
 }
 
+struct dm_list *lvm_pv_list_pvsegs(pv_t pv)
+{
+	struct dm_list *rc;
+	struct saved_env e = store_user_env(pv->vg->cmd);
+	rc = _lvm_pv_list_pvsegs(pv);
+	restore_user_env(&e);
+	return rc;
+}
+
 pv_t lvm_pv_from_name(vg_t vg, const char *name)
 {
+	pv_t rc = NULL;
 	struct pv_list *pvl;
+	struct saved_env e = store_user_env(vg->cmd);
 
 	dm_list_iterate_items(pvl, &vg->pvs) {
-		if (!strcmp(name, pv_dev_name(pvl->pv)))
-			return pvl->pv;
+		if (!strcmp(name, pv_dev_name(pvl->pv))) {
+			rc = pvl->pv;
+			break;
+		}
 	}
-	return NULL;
+	restore_user_env(&e);
+	return rc;
 }
 
-pv_t lvm_pv_from_uuid(vg_t vg, const char *uuid)
+static pv_t _lvm_pv_from_uuid(vg_t vg, const char *uuid)
 {
 	struct pv_list *pvl;
 	struct id id;
@@ -121,9 +166,27 @@ pv_t lvm_pv_from_uuid(vg_t vg, const char *uuid)
 }
 
 
-int lvm_pv_resize(const pv_t pv, uint64_t new_size)
+pv_t lvm_pv_from_uuid(vg_t vg, const char *uuid)
+{
+	pv_t rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = _lvm_pv_from_uuid(vg, uuid);
+	restore_user_env(&e);
+	return rc;
+}
+
+static int _lvm_pv_resize(const pv_t pv, uint64_t new_size)
 {
 	/* FIXME: add pv resize code here */
 	log_error("NOT IMPLEMENTED YET");
 	return -1;
 }
+
+int lvm_pv_resize(const pv_t pv, uint64_t new_size)
+{
+	int rc;
+	struct saved_env e = store_user_env(pv->vg->cmd);
+	rc = _lvm_pv_resize(pv, new_size);
+	restore_user_env(&e);
+	return rc;
+}
diff --git a/liblvm/lvm_vg.c b/liblvm/lvm_vg.c
index 405a91a..26e6395 100644
--- a/liblvm/lvm_vg.c
+++ b/liblvm/lvm_vg.c
@@ -23,47 +23,49 @@
 
 int lvm_vg_add_tag(vg_t vg, const char *tag)
 {
-	if (vg_read_error(vg))
-		return -1;
-
-	if (!vg_check_write_mode(vg))
-		return -1;
+	int rc = -1;
+	struct saved_env e = store_user_env(vg->cmd);
 
-	if (!vg_change_tag(vg, tag, 1))
-		return -1;
-	return 0;
+	if (!vg_read_error(vg) && vg_check_write_mode(vg) &&
+		vg_change_tag(vg, tag, 1))
+		rc = 0;
+	restore_user_env(&e);
+	return rc;
 }
 
 
 int lvm_vg_remove_tag(vg_t vg, const char *tag)
 {
-	if (vg_read_error(vg))
-		return -1;
+	int rc = -1;
+	struct saved_env e = store_user_env(vg->cmd);
 
-	if (!vg_check_write_mode(vg))
-		return -1;
-
-	if (!vg_change_tag(vg, tag, 0))
-		return -1;
-	return 0;
+	if (!vg_read_error(vg) && vg_check_write_mode(vg) &&
+		vg_change_tag(vg, tag, 0))
+		rc = 0;
+	restore_user_env(&e);
+	return rc;
 }
 
 
 vg_t lvm_vg_create(lvm_t libh, const char *vg_name)
 {
-	struct volume_group *vg;
+	struct volume_group *vg = NULL;
+	struct saved_env e = store_user_env((struct cmd_context *)libh);
 
 	vg = vg_create((struct cmd_context *)libh, vg_name);
 	/* FIXME: error handling is still TBD */
 	if (vg_read_error(vg)) {
 		release_vg(vg);
-		return NULL;
+		vg = NULL;
+	} else {
+		vg->open_mode = 'w';
 	}
-	vg->open_mode = 'w';
+
+	restore_user_env(&e);
 	return (vg_t) vg;
 }
 
-int lvm_vg_extend(vg_t vg, const char *device)
+static int _lvm_vg_extend(vg_t vg, const char *device)
 {
 	struct pvcreate_params pp;
 
@@ -91,31 +93,41 @@ int lvm_vg_extend(vg_t vg, const char *device)
 	return 0;
 }
 
+int lvm_vg_extend(vg_t vg, const char *device)
+{
+	int rc = 0;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = _lvm_vg_extend(vg, device);
+	restore_user_env(&e);
+	return rc;
+}
+
 int lvm_vg_reduce(vg_t vg, const char *device)
 {
-	if (vg_read_error(vg))
-		return -1;
-	if (!vg_check_write_mode(vg))
-		return -1;
+	int rc = -1;
+	struct saved_env e = store_user_env(vg->cmd);
 
-	if (!vg_reduce(vg, device))
-		return -1;
-	return 0;
+	if (!vg_read_error(vg) && vg_check_write_mode(vg) && vg_reduce(vg, device))
+		rc = 0;
+
+	restore_user_env(&e);
+	return rc;
 }
 
 int lvm_vg_set_extent_size(vg_t vg, uint32_t new_size)
 {
-	if (vg_read_error(vg))
-		return -1;
-	if (!vg_check_write_mode(vg))
-		return -1;
+	int rc = -1;
+	struct saved_env e = store_user_env(vg->cmd);
 
-	if (!vg_set_extent_size(vg, new_size / SECTOR_SIZE))
-		return -1;
-	return 0;
+	if (!vg_read_error(vg) && vg_check_write_mode(vg) &&
+		vg_set_extent_size(vg, new_size / SECTOR_SIZE))
+		rc = 0;
+
+	restore_user_env(&e);
+	return rc;
 }
 
-int lvm_vg_write(vg_t vg)
+static int _lvm_vg_write(vg_t vg)
 {
 	struct pv_list *pvl;
 
@@ -157,31 +169,41 @@ int lvm_vg_write(vg_t vg)
 	return 0;
 }
 
+int lvm_vg_write(vg_t vg)
+{
+	int rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = _lvm_vg_write(vg);
+	restore_user_env(&e);
+	return rc;
+}
+
 int lvm_vg_close(vg_t vg)
 {
+	struct saved_env e = store_user_env(vg->cmd);
 	if (vg_read_error(vg) == FAILED_LOCKING)
 		release_vg(vg);
 	else
 		unlock_and_release_vg(vg->cmd, vg, vg->name);
+	restore_user_env(&e);
 	return 0;
 }
 
 int lvm_vg_remove(vg_t vg)
 {
-	if (vg_read_error(vg))
-		return -1;
-	if (!vg_check_write_mode(vg))
-		return -1;
-
-	if (!vg_remove_check(vg))
-		return -1;
+	int rc = -1;
+	struct saved_env e = store_user_env(vg->cmd);
 
-	vg_remove_pvs(vg);
+	if (!vg_read_error(vg) && vg_check_write_mode(vg) && vg_remove_check(vg)) {
+		vg_remove_pvs(vg);
+		rc = 0;
+	}
 
-	return 0;
+	restore_user_env(&e);
+	return rc;
 }
 
-vg_t lvm_vg_open(lvm_t libh, const char *vgname, const char *mode,
+static vg_t _lvm_vg_open(lvm_t libh, const char *vgname, const char *mode,
 		  uint32_t flags)
 {
 	uint32_t internal_flags = 0;
@@ -206,7 +228,17 @@ vg_t lvm_vg_open(lvm_t libh, const char *vgname, const char *mode,
 	return (vg_t) vg;
 }
 
-struct dm_list *lvm_vg_list_pvs(vg_t vg)
+vg_t lvm_vg_open(lvm_t libh, const char *vgname, const char *mode,
+		  uint32_t flags)
+{
+	vg_t rc;
+	struct saved_env e = store_user_env((struct cmd_context*)libh);
+	rc = _lvm_vg_open(libh, vgname, mode, flags);
+	restore_user_env(&e);
+	return rc;
+}
+
+static struct dm_list *_lvm_vg_list_pvs(vg_t vg)
 {
 	struct dm_list *list;
 	pv_list_t *pvs;
@@ -233,7 +265,16 @@ struct dm_list *lvm_vg_list_pvs(vg_t vg)
 	return list;
 }
 
-struct dm_list *lvm_vg_list_lvs(vg_t vg)
+struct dm_list *lvm_vg_list_pvs(vg_t vg)
+{
+	struct dm_list *rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = _lvm_vg_list_pvs(vg);
+	restore_user_env(&e);
+	return rc;
+}
+
+static struct dm_list *_lvm_vg_list_lvs(vg_t vg)
 {
 	struct dm_list *list;
 	lv_list_t *lvs;
@@ -260,102 +301,191 @@ struct dm_list *lvm_vg_list_lvs(vg_t vg)
 	return list;
 }
 
+struct dm_list *lvm_vg_list_lvs(vg_t vg)
+{
+	struct dm_list *rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = _lvm_vg_list_lvs(vg);
+	restore_user_env(&e);
+	return rc;
+}
+
 struct dm_list *lvm_vg_get_tags(const vg_t vg)
 {
-	return tag_list_copy(vg->vgmem, &vg->tags);
+	struct dm_list *rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = tag_list_copy(vg->vgmem, &vg->tags);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_vg_get_seqno(const vg_t vg)
 {
-	return vg_seqno(vg);
+	uint64_t rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = vg_seqno(vg);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_vg_is_clustered(const vg_t vg)
 {
-	return vg_is_clustered(vg);
+	uint64_t rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = vg_is_clustered(vg);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_vg_is_exported(const vg_t vg)
 {
-	return vg_is_exported(vg);
+	uint64_t rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = vg_is_exported(vg);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_vg_is_partial(const vg_t vg)
 {
-	return (vg_missing_pv_count(vg) != 0);
+	uint64_t rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = (vg_missing_pv_count(vg) != 0);
+	restore_user_env(&e);
+	return rc;
 }
 
 /* FIXME: invalid handle? return INTMAX? */
 uint64_t lvm_vg_get_size(const vg_t vg)
 {
-	return SECTOR_SIZE * vg_size(vg);
+	uint64_t rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = SECTOR_SIZE * vg_size(vg);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_vg_get_free_size(const vg_t vg)
 {
-	return SECTOR_SIZE * vg_free(vg);
+	uint64_t rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = SECTOR_SIZE * vg_free(vg);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_vg_get_extent_size(const vg_t vg)
 {
-	return SECTOR_SIZE * vg_extent_size(vg);
+	uint64_t rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = SECTOR_SIZE * vg_extent_size(vg);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_vg_get_extent_count(const vg_t vg)
 {
-	return vg_extent_count(vg);
+	uint64_t rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = vg_extent_count(vg);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_vg_get_free_extent_count(const vg_t vg)
 {
-	return vg_free_count(vg);
+	uint64_t rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = vg_free_count(vg);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_vg_get_pv_count(const vg_t vg)
 {
-	return vg_pv_count(vg);
+	uint64_t rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = vg_pv_count(vg);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_vg_get_max_pv(const vg_t vg)
 {
-	return vg_max_pv(vg);
+	uint64_t rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = vg_max_pv(vg);
+	restore_user_env(&e);
+	return rc;
 }
 
 uint64_t lvm_vg_get_max_lv(const vg_t vg)
 {
-	return vg_max_lv(vg);
+	uint64_t rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = vg_max_lv(vg);
+	restore_user_env(&e);
+	return rc;
 }
 
 const char *lvm_vg_get_uuid(const vg_t vg)
 {
-	return vg_uuid_dup(vg);
+	const char *rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = vg_uuid_dup(vg);
+	restore_user_env(&e);
+	return rc;
 }
 
 const char *lvm_vg_get_name(const vg_t vg)
 {
-	return dm_pool_strndup(vg->vgmem, (const char *)vg->name, NAME_LEN+1);
+	const char *rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = dm_pool_strndup(vg->vgmem, (const char *)vg->name, NAME_LEN+1);
+	restore_user_env(&e);
+	return rc;
 }
 
 
 struct lvm_property_value lvm_vg_get_property(const vg_t vg, const char *name)
 {
-	return get_property(NULL, vg, NULL, NULL, NULL, name);
+	struct lvm_property_value rc;
+	struct saved_env e = store_user_env(vg->cmd);
+	rc = get_property(NULL, vg, NULL, NULL, NULL, name);
+	restore_user_env(&e);
+	return rc;
 }
 
 int lvm_vg_set_property(const vg_t vg, const char *name,
 			struct lvm_property_value *value)
 {
-	return set_property(NULL, vg, NULL, name, value);
+	int rc;
+	struct saved_env e = store_user_env(vg->cmd);
+
+	rc = set_property(NULL, vg, NULL, name, value);
+	restore_user_env(&e);
+	return rc;
 }
 
 struct dm_list *lvm_list_vg_names(lvm_t libh)
 {
-	return get_vgnames((struct cmd_context *)libh, 0);
+	struct dm_list *rc = NULL;
+	struct saved_env e = store_user_env((struct cmd_context *)libh);
+
+	rc = get_vgnames((struct cmd_context *)libh, 0);
+	restore_user_env(&e);
+	return rc;
 }
 
 struct dm_list *lvm_list_vg_uuids(lvm_t libh)
 {
-	return get_vgids((struct cmd_context *)libh, 0);
+	struct dm_list *rc = NULL;
+	struct saved_env e = store_user_env((struct cmd_context *)libh);
+
+	rc = get_vgids((struct cmd_context *)libh, 0);
+
+	restore_user_env(&e);
+	return rc;
 }
 
 /*
@@ -363,7 +493,12 @@ struct dm_list *lvm_list_vg_uuids(lvm_t libh)
  */
 int lvm_scan(lvm_t libh)
 {
+	int rc = 0;
+	struct saved_env e = store_user_env((struct cmd_context *)libh);
+
 	if (!lvmcache_label_scan((struct cmd_context *)libh, 2))
-		return -1;
-	return 0;
+		rc = -1;
+
+	restore_user_env(&e);
+	return rc;
 }