/*
 * Copyright (C) 2008-2013 Red Hat, Inc. All rights reserved.
 *
 * This file is part of LVM2.
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU Lesser General Public License v.2.1.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "lib.h"
#include "properties.h"
#include "lvm_misc.h"
#include "lvm2app.h"
#include "lvm_prop.h"

struct dm_list *tag_list_copy(struct dm_pool *p, struct dm_list *tag_list)
{
	struct dm_list *list;
	lvm_str_list_t *lsl;
	struct dm_str_list *sl;

	if (!(list = dm_pool_zalloc(p, sizeof(*list)))) {
		log_errno(ENOMEM, "Memory allocation fail for dm_list.");
		return NULL;
	}
	dm_list_init(list);

	dm_list_iterate_items(sl, tag_list) {
		if (!(lsl = dm_pool_zalloc(p, sizeof(*lsl)))) {
			log_errno(ENOMEM,
				"Memory allocation fail for lvm_lv_list.");
			return NULL;
		}
		if (!(lsl->str = dm_pool_strdup(p, sl->str))) {
			log_errno(ENOMEM,
				"Memory allocation fail for lvm_lv_list->str.");
			return NULL;
		}
		dm_list_add(list, &lsl->list);
	}
	return list;
}

struct lvm_property_value get_property(const pv_t pv, const vg_t vg,
				       const lv_t lv,
				       const lvseg_t lvseg,
				       const pvseg_t pvseg,
				       const struct lvcreate_params *lvcp,
				       const struct pvcreate_params *pvcp,
				       const char *name)
{
	struct lvm_property_type prop;
	struct lvm_property_value v = { 0 };

	prop.id = name;

	if (pv) {
		if (!pv_get_property(pv, &prop))
			return v;
	} else if (vg) {
		if (!vg_get_property(vg, &prop))
			return v;
	} else if (lv) {
		if (!lv_get_property(lv, &prop))
			return v;
	} else if (lvseg) {
		if (!lvseg_get_property(lvseg, &prop))
			return v;
	} else if (pvseg) {
		if (!pvseg_get_property(pvseg, &prop))
			return v;
	} else if (lvcp) {
		if (!lv_create_param_get_property(lvcp, &prop))
			return v;
	} else if (pvcp) {
		if (!pv_create_param_get_property(pvcp, &prop))
			return v;
	} else {
		log_errno(EINVAL, "Invalid NULL handle passed to library function.");
		return v;
	}

	v.is_settable = prop.is_settable;
	v.is_string = prop.is_string;
	v.is_integer = prop.is_integer;
	v.is_signed = prop.is_signed;
	if (v.is_string)
		v.value.string = prop.value.string;
	if (v.is_integer)
		v.value.integer = prop.value.integer;
	v.is_valid = 1;
	return v;
}


int set_property(const pv_t pv, const vg_t vg, const lv_t lv,
		struct lvcreate_params *lvcp,
		struct pvcreate_params *pvcp,
		const char *name,
		struct lvm_property_value *v)
{
	struct lvm_property_type prop;

	prop.id = name;
	if (v->is_string)
		prop.value.string = v->value.string;
	else
		prop.value.integer = v->value.integer;
	if (pv) {
		if (!pv_set_property(pv, &prop)) {
			v->is_valid = 0;
			return -1;
		}
	} else if (vg) {
		if (!vg_set_property(vg, &prop)) {
			v->is_valid = 0;
			return -1;
		}
	} else if (lv) {
		if (!lv_set_property(lv, &prop)) {
			v->is_valid = 0;
			return -1;
		}
	} else if (lvcp) {
		if (!lv_create_param_set_property(lvcp, &prop)) {
			v->is_valid = 0;
			return -1;
		}
	} else if (pvcp) {
		if (!pv_create_param_set_property(pvcp, &prop)) {
			v->is_valid = 0;
			return -1;
		}
	} else {
		return -1;
	}
	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);
	}
}