/*
 * Copyright (c) 2016 Jeff Mahoney <jeffm@suse.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "defs.h"
#include <linux/ioctl.h>
#include <linux/fs.h>

#ifdef HAVE_LINUX_FIEMAP_H
# include <linux/fiemap.h>
# include "xlat/fiemap_flags.h"
# include "xlat/fiemap_extent_flags.h"
#endif

#ifndef FICLONE
# define FICLONE         _IOW(0x94, 9, int)
#endif

#ifndef FICLONERANGE
# define FICLONERANGE    _IOW(0x94, 13, struct file_clone_range)
struct file_clone_range {
	int64_t src_fd;
	uint64_t src_offset;
	uint64_t src_length;
	uint64_t dest_offset;
};
#endif

#ifndef FIDEDUPERANGE
# define FIDEDUPERANGE   _IOWR(0x94, 54, struct file_dedupe_range)
struct file_dedupe_range_info {
	int64_t dest_fd;	/* in - destination file */
	uint64_t dest_offset;	/* in - start of extent in destination */
	uint64_t bytes_deduped;	/* out - total # of bytes we were able
				 * to dedupe from this file. */
	/* status of this dedupe operation:
	 * < 0 for error
	 * == FILE_DEDUPE_RANGE_SAME if dedupe succeeds
	 * == FILE_DEDUPE_RANGE_DIFFERS if data differs
	 */
	int32_t status;		/* out - see above description */
	uint32_t reserved;	/* must be zero */
};

struct file_dedupe_range {
	uint64_t src_offset;	/* in - start of extent in source */
	uint64_t src_length;	/* in - length of extent */
	uint16_t dest_count;	/* in - total elements in info array */
	uint16_t reserved1;	/* must be zero */
	uint32_t reserved2;	/* must be zero */
	struct file_dedupe_range_info info[0];
};
#endif

static bool
print_file_dedupe_range_info(struct tcb *tcp, void *elem_buf,
			     size_t elem_size, void *data)
{
	const struct file_dedupe_range_info *info = elem_buf;

	if (entering(tcp)) {
		tprintf("{dest_fd=%" PRIi64
			", dest_offset=%" PRIu64 "}",
			(int64_t) info->dest_fd,
			(uint64_t) info->dest_offset);
	} else {
		tprintf("{bytes_deduped=%" PRIu64 ", status=%d}",
			(uint64_t) info->bytes_deduped, info->status);
	}

	return true;
}

#ifdef HAVE_LINUX_FIEMAP_H
static bool
print_fiemap_extent(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
{
	const struct fiemap_extent *fe = elem_buf;

	tprintf("{fe_logical=%" PRI__u64
		", fe_physical=%" PRI__u64
		", fe_length=%" PRI__u64 ", ",
		fe->fe_logical, fe->fe_physical, fe->fe_length);

	printflags64(fiemap_extent_flags, fe->fe_flags,
		     "FIEMAP_EXTENT_???");
	tprints("}");

	return true;
}
#endif /* HAVE_LINUX_FIEMAP_H */

int
file_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
{
	switch (code) {
	case FICLONE:	/* W */
		tprintf(", %d", (int) arg);
		break;

	case FICLONERANGE: { /* W */
		struct file_clone_range args;

		tprints(", ");
		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprintf("{src_fd=%" PRIi64
			", src_offset=%" PRIu64
			", src_length=%" PRIu64
			", dest_offset=%" PRIu64 "}",
			(int64_t) args.src_fd,
			(uint64_t) args.src_offset,
			(uint64_t) args.src_length,
			(uint64_t) args.dest_offset);
		break;
	}

	case FIDEDUPERANGE: { /* RW */
		struct file_dedupe_range args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		tprints("{");
		if (entering(tcp)) {
			tprintf("src_offset=%" PRIu64
				", src_length=%" PRIu64
				", dest_count=%hu, ",
				(uint64_t) args.src_offset,
				(uint64_t) args.src_length,
				(uint16_t) args.dest_count);
		}

		bool rc = false;
		tprints("info=");
		if (abbrev(tcp)) {
			tprints("...");
		} else {
			struct file_dedupe_range_info info;
			rc = print_array(tcp,
					 arg + offsetof(typeof(args), info),
					 args.dest_count,
					 &info, sizeof(info),
					 umoven_or_printaddr,
					 print_file_dedupe_range_info, 0);
		}

		tprints("}");
		if (!rc || exiting(tcp))
			break;

		return 0;
	}

#ifdef HAVE_LINUX_FIEMAP_H
	case FS_IOC_FIEMAP: {
		struct fiemap args;

		if (entering(tcp))
			tprints(", ");
		else if (syserror(tcp))
			break;
		else
			tprints(" => ");

		if (umove_or_printaddr(tcp, arg, &args))
			break;

		if (entering(tcp)) {
			tprintf("{fm_start=%" PRI__u64 ", "
				"fm_length=%" PRI__u64 ", "
				"fm_flags=",
				args.fm_start, args.fm_length);
			printflags64(fiemap_flags, args.fm_flags,
				     "FIEMAP_FLAG_???");
			tprintf(", fm_extent_count=%u}", args.fm_extent_count);
			return 0;
		}

		tprints("{fm_flags=");
		printflags64(fiemap_flags, args.fm_flags,
			     "FIEMAP_FLAG_???");
		tprintf(", fm_mapped_extents=%u",
			args.fm_mapped_extents);
		tprints(", fm_extents=");
		if (abbrev(tcp)) {
			tprints("...");
		} else {
			struct fiemap_extent fe;
			print_array(tcp,
				    arg + offsetof(typeof(args), fm_extents),
				    args.fm_mapped_extents, &fe, sizeof(fe),
				    umoven_or_printaddr,
				    print_fiemap_extent, 0);
		}
		tprints("}");

		break;
	}
#endif /* HAVE_LINUX_FIEMAP_H */

	default:
		return RVAL_DECODED;
	};

	return RVAL_DECODED | 1;
}
