/*
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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-pre.target"
#define UNIT_TARGET_REMOTE_FS "remote-fs-pre.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)
{
	*use_lvmetad = *use_lvmpolld = 0;

	*use_lvmetad = lvm_config_find_bool(NULL, LVM_CONF_USE_LVMETAD, 0);
	*use_lvmpolld = lvm_config_find_bool(NULL, LVM_CONF_USE_LVMPOLLD, 0);
}

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-pre.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-pre.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;
}
