/*
 * 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 = vfork();
	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));
	} else {
		DEBUG(("kinit: permament (or pivoting) initrd, not running linuxrc\n"));
	}

	return 1;		/* initrd is root, or run_linuxrc took care of it */
}
