/*
 * Copyright (C) 2012 Red Hat, Inc. All rights reserved.
 *
 * This file is part of the device-mapper userspace tools.
 *
 * 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 General Public License v.2.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdarg.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>		/* For PATH_MAX for musl libc */
#include "lvm2app.h"
#include "configure.h"		/* for LVM_PATH */

#define KMSG_DEV_PATH		"/dev/kmsg"
#define LVM_CONF_USE_LVMETAD	"global/use_lvmetad"
#define LVM_CONF_USE_LVMPOLLD	"global/use_lvmpolld"

#define UNIT_TARGET_LOCAL_FS  "local-fs.target"
#define UNIT_TARGET_REMOTE_FS "remote-fs.target"

static char unit_path[PATH_MAX];
static char target_path[PATH_MAX];
static char message[PATH_MAX + 3]; /* +3 for '<n>' where n is the log level */
static int kmsg_fd = -1;

enum {
	UNIT_EARLY,
	UNIT_MAIN,
	UNIT_NET
};

static const char *unit_names[] = {
	[UNIT_EARLY] = "lvm2-activation-early.service",
	[UNIT_MAIN] = "lvm2-activation.service",
	[UNIT_NET] = "lvm2-activation-net.service"
};

__attribute__ ((format(printf, 2, 3)))
static void kmsg(int log_level, const char *format, ...)
{
	va_list ap;
	int n;

	snprintf(message, 4, "<%d>", log_level);

	va_start(ap, format);
	n = vsnprintf(message + 3, PATH_MAX, format, ap);
	va_end(ap);

	if (kmsg_fd < 0 || (n < 0 || ((unsigned) n + 1 > PATH_MAX)))
		return;

	/* The n+4: +3 for "<n>" prefix and +1 for '\0' suffix */
	if (write(kmsg_fd, message, n + 4)) { /* Ignore result code */; }
}

static void lvm_get_use_lvmetad_and_lvmpolld(int *use_lvmetad, int *use_lvmpolld)
{
	lvm_t lvm;

	*use_lvmetad = *use_lvmpolld = 0;
	if (!(lvm = lvm_init(NULL))) {
		kmsg(LOG_ERR, "LVM: Failed to initialize library context for activation generator.\n");
		return;
	}
	*use_lvmetad = lvm_config_find_bool(lvm, LVM_CONF_USE_LVMETAD, 0);
	*use_lvmpolld = lvm_config_find_bool(lvm, LVM_CONF_USE_LVMPOLLD, 0);
	lvm_quit(lvm);
}

static int register_unit_with_target(const char *dir, const char *unit, const char *target)
{
	int r = 1;

	if (dm_snprintf(target_path, PATH_MAX, "%s/%s.wants", dir, target) < 0) {
		r = 0; goto out;
	}
	(void) dm_prepare_selinux_context(target_path, S_IFDIR);
	if (mkdir(target_path, 0755) < 0 && errno != EEXIST) {
		kmsg(LOG_ERR, "LVM: Failed to create target directory %s: %m.\n", target_path);
		r = 0; goto out;
	}

	if (dm_snprintf(target_path, PATH_MAX, "%s/%s.wants/%s", dir, target, unit) < 0) {
		r = 0; goto out;
	}
	(void) dm_prepare_selinux_context(target_path, S_IFLNK);
	if (symlink(unit_path, target_path) < 0) {
		kmsg(LOG_ERR, "LVM: Failed to create symlink for unit %s: %m.\n", unit);
		r = 0;
	}
out:
	dm_prepare_selinux_context(NULL, 0);
	return r;
}

static int generate_unit(const char *dir, int unit, int sysinit_needed)
{
	FILE *f;
	const char *unit_name = unit_names[unit];
	const char *target_name = unit == UNIT_NET ? UNIT_TARGET_REMOTE_FS : UNIT_TARGET_LOCAL_FS;

	if (dm_snprintf(unit_path, PATH_MAX, "%s/%s", dir, unit_name) < 0)
		return 0;

	if (!(f = fopen(unit_path, "wxe"))) {
		kmsg(LOG_ERR, "LVM: Failed to create unit file %s: %m.\n", unit_name);
		return 0;
	}

	fputs("# Automatically generated by lvm2-activation-generator.\n"
	      "#\n"
	      "# This unit is responsible for direct activation of LVM2 logical volumes\n"
	      "# if lvmetad daemon is not used (global/use_lvmetad=0 lvm.conf setting),\n"
	      "# hence volume autoactivation is not applicable.\n"
	      "# Direct LVM2 activation requires udev to be settled!\n\n"
	      "[Unit]\n"
	      "Description=Activation of LVM2 logical volumes\n"
	      "Documentation=man:lvm2-activation-generator(8)\n"
	      "SourcePath=/etc/lvm/lvm.conf\n"
	      "DefaultDependencies=no\n", f);

	if (unit == UNIT_NET) {
		fprintf(f, "After=%s iscsi.service fcoe.service\n"
			"Before=remote-fs.target shutdown.target\n\n"
			"[Service]\n"
			"ExecStartPre=/usr/bin/udevadm settle\n", unit_names[UNIT_MAIN]);
	} else {
		if (unit == UNIT_EARLY) {
			fputs("After=systemd-udev-settle.service\n"
			      "Before=cryptsetup.target\n", f);
		} else
			fprintf(f, "After= %s cryptsetup.target\n", unit_names[UNIT_EARLY]);

		fputs("Before=local-fs.target shutdown.target\n"
		      "Wants=systemd-udev-settle.service\n\n"
		      "[Service]\n", f);
	}

	fputs("ExecStart=" LVM_PATH " vgchange -aay --ignoreskippedcluster", f);
	if (sysinit_needed)
		fputs (" --sysinit", f);
	fputs("\nType=oneshot\n", f);

	if (fclose(f) < 0) {
		kmsg(LOG_ERR, "LVM: Failed to write unit file %s: %m.\n", unit_name);
		return 0;
	}

	if (!register_unit_with_target(dir, unit_name, target_name)) {
		kmsg(LOG_ERR, "LVM: Failed to register unit %s with target %s.\n", unit_name, target_name);
		return 0;
	}

	return 1;
}

int main(int argc, char *argv[])
{
	int use_lvmetad, use_lvmpolld, sysinit_needed;
	const char *dir;
	int r = EXIT_SUCCESS;
	mode_t old_mask;

	kmsg_fd = open(KMSG_DEV_PATH, O_WRONLY|O_NOCTTY);

	if (argc != 4) {
		kmsg(LOG_ERR, "LVM: Incorrect number of arguments for activation generator.\n");
		r = EXIT_FAILURE; goto out;
	}

	/* If lvmetad used, rely on autoactivation instead of direct activation. */
	lvm_get_use_lvmetad_and_lvmpolld(&use_lvmetad, &use_lvmpolld);
	if (use_lvmetad)
		goto out;

	dir = argv[1];

	/* mark lvm2-activation.*.service as world-accessible */
	old_mask = umask(0022);

	sysinit_needed = !use_lvmpolld;

	if (!generate_unit(dir, UNIT_EARLY, sysinit_needed) ||
	    !generate_unit(dir, UNIT_MAIN, sysinit_needed) ||
	    !generate_unit(dir, UNIT_NET, sysinit_needed))
		r = EXIT_FAILURE;
	umask(old_mask);
out:
	if (r)
		kmsg(LOG_ERR, "LVM: Activation generator failed.\n");
	if (kmsg_fd != -1)
		(void) close(kmsg_fd);
	return r;
}
