/*
 * kinit/initrd.c
 *
 * Handle initrd, thus putting the backwards into backwards compatible
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include "do_mounts.h"
#include "kinit.h"
#include "xpio.h"

#define BUF_SIZE	65536	/* Should be a power of 2 */

/*
 * Copy the initrd to /dev/ram0, copy from the end to the beginning
 * to avoid taking 2x the memory.
 */
static int rd_copy_uncompressed(int ffd, int dfd)
{
	char buffer[BUF_SIZE];
	off_t bytes;
	struct stat st;

	DEBUG(("kinit: uncompressed initrd\n"));

	if (ffd < 0 || fstat(ffd, &st) || !S_ISREG(st.st_mode) ||
	    (bytes = st.st_size) == 0)
		return -1;

	while (bytes) {
		ssize_t blocksize = ((bytes - 1) & (BUF_SIZE - 1)) + 1;
		off_t offset = bytes - blocksize;

		DEBUG(("kinit: copying %zd bytes at offset %llu\n",
		       blocksize, offset));

		if (xpread(ffd, buffer, blocksize, offset) != blocksize ||
		    xpwrite(dfd, buffer, blocksize, offset) != blocksize)
			return -1;

		ftruncate(ffd, offset);	/* Free up memory */
		bytes = offset;
	}
	return 0;
}

static int rd_copy_image(const char *path)
{
	int ffd = open(path, O_RDONLY);
	int rv = -1;
	unsigned char gzip_magic[2];

	if (ffd < 0)
		goto barf;

	if (xpread(ffd, gzip_magic, 2, 0) == 2 &&
	    gzip_magic[0] == 037 && gzip_magic[1] == 0213) {
		FILE *wfd = fopen("/dev/ram0", "w");
		if (!wfd)
			goto barf;
		rv = load_ramdisk_compressed(path, wfd, 0);
		fclose(wfd);
	} else {
		int dfd = open("/dev/ram0", O_WRONLY);
		if (dfd < 0)
			goto barf;
		rv = rd_copy_uncompressed(ffd, dfd);
		close(dfd);
	}

barf:
	if (ffd >= 0)
		close(ffd);
	return rv;
}

/*
 * Run /linuxrc, for emulation of old-style initrd
 */
static int run_linuxrc(int argc, char *argv[], dev_t root_dev)
{
	int root_fd, old_fd;
	pid_t pid;
	long realroot = Root_RAM0;
	const char *ramdisk_name = "/dev/ram0";
	FILE *fp;

	DEBUG(("kinit: mounting initrd\n"));
	mkdir("/root", 0700);
	if (!mount_block(ramdisk_name, "/root", NULL, MS_VERBOSE, NULL))
		return -errno;

	/* Write the current "real root device" out to procfs */
	DEBUG(("kinit: real_root_dev = %#x\n", root_dev));
	fp = fopen("/proc/sys/kernel/real-root-dev", "w");
	fprintf(fp, "%u", root_dev);
	fclose(fp);

	mkdir("/old", 0700);
	root_fd = open_cloexec("/", O_RDONLY | O_DIRECTORY, 0);
	old_fd = open_cloexec("/old", O_RDONLY | O_DIRECTORY, 0);

	if (root_fd < 0 || old_fd < 0)
		return -errno;

	if (chdir("/root") ||
	    mount(".", "/", NULL, MS_MOVE, NULL) || chroot("."))
		return -errno;

	pid = fork();
	if (pid == 0) {
		setsid();
		/* Looks like linuxrc doesn't get the init environment
		   or parameters.  Weird, but so is the whole linuxrc bit. */
		execl("/linuxrc", "linuxrc", NULL);
		_exit(255);
	} else if (pid > 0) {
		DEBUG(("kinit: Waiting for linuxrc to complete...\n"));
		while (waitpid(pid, NULL, 0) != pid) ;
		DEBUG(("kinit: linuxrc done\n"));
	} else {
		return -errno;
	}

	if (fchdir(old_fd) ||
	    mount("/", ".", NULL, MS_MOVE, NULL) ||
	    fchdir(root_fd) || chroot("."))
		return -errno;

	close(root_fd);
	close(old_fd);

	getintfile("/proc/sys/kernel/real-root-dev", &realroot);

	/* If realroot is Root_RAM0, then the initrd did any necessary work */
	if (realroot == Root_RAM0) {
		if (mount("/old", "/root", NULL, MS_MOVE, NULL))
			return -errno;
	} else {
		mount_root(argc, argv, (dev_t) realroot, NULL);

		/* If /root/initrd exists, move the initrd there, otherwise discard */
		if (!mount("/old", "/root/initrd", NULL, MS_MOVE, NULL)) {
			/* We're good */
		} else {
			int olddev = open(ramdisk_name, O_RDWR);
			umount2("/old", MNT_DETACH);
			if (olddev < 0 ||
			    ioctl(olddev, BLKFLSBUF, (long)0) ||
			    close(olddev)) {
				fprintf(stderr,
					"%s: Cannot flush initrd contents\n",
					progname);
			}
		}
	}

	rmdir("/old");
	return 0;
}

int initrd_load(int argc, char *argv[], dev_t root_dev)
{
	if (access("/initrd.image", R_OK))
		return 0;	/* No initrd */

	DEBUG(("kinit: initrd found\n"));

	create_dev("/dev/ram0", Root_RAM0);

	if (rd_copy_image("/initrd.image") || unlink("/initrd.image")) {
		fprintf(stderr, "%s: initrd installation failed (too big?)\n",
			progname);
		return 0;	/* Failed to copy initrd */
	}

	DEBUG(("kinit: initrd copied\n"));

	if (root_dev != Root_RAM0) {
		int err;
		DEBUG(("kinit: running linuxrc\n"));
		err = run_linuxrc(argc, argv, root_dev);
		if (err)
			fprintf(stderr, "%s: running linuxrc: %s\n", progname,
				strerror(-err));
		return 1;	/* initrd is root, or run_linuxrc took care of it */
	} else {
		DEBUG(("kinit: permament (or pivoting) initrd, not running linuxrc\n"));
		return 0;	/* Mounting initrd as ordinary root */
	}
}
