/* See LICENSE file for copyright and license details. */
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "util.h"

enum { SWAP_UUID_LENGTH = 16, SWAP_LABEL_LENGTH = 16 };
enum { SWAP_MIN_PAGES = 10 };

struct swap_hdr {
	char	      bootbits[1024];
	unsigned int  version;
	unsigned int  last_page;
	unsigned int  nr_badpages;
	unsigned char uuid[SWAP_UUID_LENGTH];
	char	      volume_name[SWAP_LABEL_LENGTH];
	unsigned int  padding[117];
	unsigned int  badpages[1];
};

static void
usage(void)
{
	eprintf("usage: %s device\n", argv0);
}

int
main(int argc, char *argv[])
{
	int fd;
	unsigned int pages;
	long pagesize;
	struct stat sb;
	char *buf;
	struct swap_hdr *hdr;

	ARGBEGIN {
	default:
		usage();
	} ARGEND;

	if (argc < 1)
		usage();

	pagesize = sysconf(_SC_PAGE_SIZE);

	fd = open(argv[0], O_RDWR);
	if (fd < 0)
		eprintf("open %s:", argv[0]);
	if (fstat(fd, &sb) < 0)
		eprintf("stat %s:", argv[0]);

	buf = calloc(1, pagesize);
	if (!buf)
		eprintf("malloc:");

	pages = sb.st_size / pagesize;
	if (pages < SWAP_MIN_PAGES)
		enprintf(EXIT_FAILURE, "swap space needs to be at least %ldKiB\n",
			 SWAP_MIN_PAGES * pagesize / 1024);

	/* Fill up the swap header */
	hdr = (struct swap_hdr *)buf;
	hdr->version = 1;
	hdr->last_page = pages - 1;
	strncpy(buf + pagesize - 10, "SWAPSPACE2", 10);

	printf("Setting up swapspace version 1, size = %luKiB\n",
	       (pages - 1) * pagesize / 1024);

	/* Write out the signature page */
	if (write(fd, buf, pagesize) != pagesize)
		enprintf(EXIT_FAILURE, "unable to write signature page\n");

	fsync(fd);
	close(fd);
	free(buf);

	return EXIT_SUCCESS;
}