// SPDX-License-Identifier: GPL-2.0+
/*
 *  Tiny program to perform file (range) clones using raw Btrfs and CIFS ioctls.
 *  Copyright (C) 2014 SUSE Linux Products GmbH. All Rights Reserved.
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/vfs.h>
#include <stdint.h>
#include <stdbool.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <linux/magic.h>
#ifdef HAVE_BTRFS_IOCTL_H
#include <btrfs/ioctl.h>
#else

struct btrfs_ioctl_clone_range_args {
	int64_t src_fd;
	uint64_t src_offset;
	uint64_t src_length;
	uint64_t dest_offset;
};

#define BTRFS_IOCTL_MAGIC 0x94
#define BTRFS_IOC_CLONE       _IOW(BTRFS_IOCTL_MAGIC, 9, int)
#define BTRFS_IOC_CLONE_RANGE _IOW(BTRFS_IOCTL_MAGIC, 13, \
				   struct btrfs_ioctl_clone_range_args)
#endif

#ifdef HAVE_CIFS_IOCTL_H
#include <cifs/ioctl.h>
#else

#define CIFS_IOCTL_MAGIC 0xCF
#define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int)

#endif

#ifndef BTRFS_SUPER_MAGIC
#define BTRFS_SUPER_MAGIC    0x9123683E
#endif
#ifndef CIFS_MAGIC_NUMBER
#define CIFS_MAGIC_NUMBER    0xFE534D42
#endif

static void
usage(char *name, const char *msg)
{
	printf("Fatal: %s\n"
	       "Usage:\n"
	       "%s [options] <src_file> <dest_file>\n"
	       "\tA full file clone is performed by default, "
	       "unless any of the following are specified (Btrfs only):\n"
	       "\t-s <offset>:	source file offset (default = 0)\n"
	       "\t-d <offset>:	destination file offset (default = 0)\n"
	       "\t-l <length>:	length of clone (default = 0)\n\n"
	       "\tBoth Btrfs and CIFS are supported. On Btrfs, a COW clone "
	       "is attempted. On CIFS, a server-side copy is requested.\n",
	       msg, name);
	_exit(1);
}

static int
clone_file_btrfs(int src_fd, int dst_fd)
{
	int ret = ioctl(dst_fd, BTRFS_IOC_CLONE, src_fd);
	if (ret != 0)
		ret = errno;
	return ret;
}

static int
clone_file_cifs(int src_fd, int dst_fd)
{
	int ret = ioctl(dst_fd, CIFS_IOC_COPYCHUNK_FILE, src_fd);
	if (ret != 0)
		ret = errno;
	return ret;
}

static int
clone_file(unsigned int fs_type, int src_fd, int dst_fd)
{
	switch (fs_type) {
	case BTRFS_SUPER_MAGIC:
		return clone_file_btrfs(src_fd, dst_fd);
		break;
	case CIFS_MAGIC_NUMBER:
		return clone_file_cifs(src_fd, dst_fd);
		break;
	default:
		return ENOTSUP;
		break;
	}
}

static int
clone_file_range_btrfs(int src_fd, int dst_fd, uint64_t src_off,
		       uint64_t dst_off, uint64_t len)
{
	struct btrfs_ioctl_clone_range_args cr_args;
	int ret;

	memset(&cr_args, 0, sizeof(cr_args));
	cr_args.src_fd = src_fd;
	cr_args.src_offset = src_off;
	cr_args.src_length = len;
	cr_args.dest_offset = dst_off;
	ret = ioctl(dst_fd, BTRFS_IOC_CLONE_RANGE, &cr_args);
	if (ret != 0)
		ret = errno;
	return ret;
}

static int
clone_file_range(unsigned int fs_type, int src_fd, int dst_fd, uint64_t src_off,
		 uint64_t dst_off, uint64_t len)
{
	switch (fs_type) {
	case BTRFS_SUPER_MAGIC:
		return clone_file_range_btrfs(src_fd, dst_fd, src_off, dst_off,
					      len);
		break;
	case CIFS_MAGIC_NUMBER:	/* only supports full file server-side copies */
	default:
		return ENOTSUP;
		break;
	}
}

static int
cloner_check_fs_support(int src_fd, int dest_fd, unsigned int *fs_type)
{
	int ret;
	struct statfs sfs;

	ret = fstatfs(src_fd, &sfs);
	if (ret != 0) {
		printf("failed to stat source FS\n");
		return errno;
	}

	if ((sfs.f_type != BTRFS_SUPER_MAGIC)
	 && (sfs.f_type != CIFS_MAGIC_NUMBER)) {
		printf("unsupported source FS 0x%x\n",
		       (unsigned int)sfs.f_type);
		return ENOTSUP;
	}

	*fs_type = (unsigned int)sfs.f_type;

	ret = fstatfs(dest_fd, &sfs);
	if (ret != 0) {
		printf("failed to stat destination FS\n");
		return errno;
	}

	if (sfs.f_type != *fs_type) {
		printf("dest FS type 0x%x does not match source 0x%x\n",
		       (unsigned int)sfs.f_type, *fs_type);
		return ENOTSUP;
	}

	return 0;
}

int
main(int argc, char **argv)
{
	bool full_file = true;
	uint64_t src_off = 0;
	uint64_t dst_off = 0;
	uint64_t len = 0;
	char *src_file;
	int src_fd;
	char *dst_file;
	int dst_fd;
	int ret;
	int opt;
	unsigned int fs_type = 0;

	while ((opt = getopt(argc, argv, "s:d:l:")) != -1) {
		char *sval_end;
		switch (opt) {
		case 's':
			errno = 0;
			src_off = strtoull(optarg, &sval_end, 10);
			if ((errno) || (*sval_end != '\0'))
				usage(argv[0], "invalid source offset");
			full_file = false;
			break;
		case 'd':
			errno = 0;
			dst_off = strtoull(optarg, &sval_end, 10);
			if ((errno) || (*sval_end != '\0'))
				usage(argv[0], "invalid destination offset");
			full_file = false;
			break;
		case 'l':
			errno = 0;
			len = strtoull(optarg, &sval_end, 10);
			if ((errno) || (*sval_end != '\0'))
				usage(argv[0], "invalid length");
			full_file = false;
			break;
		default:
			usage(argv[0], "invalid argument");
		}
	}

	/* should be exactly two args left */
	if (optind != argc - 2)
		usage(argv[0], "src_file and dst_file arguments are madatory");

	src_file = (char *)strdup(argv[optind++]);
	if (src_file == NULL) {
		ret = ENOMEM;
		printf("no memory\n");
		goto err_out;
	}
	dst_file = (char *)strdup(argv[optind++]);
	if (dst_file == NULL) {
		ret = ENOMEM;
		printf("no memory\n");
		goto err_src_free;
	}

	src_fd = open(src_file, O_RDONLY);
	if (src_fd == -1) {
		ret = errno;
		printf("failed to open %s: %s\n", src_file, strerror(errno));
		goto err_dst_free;
	}
	dst_fd = open(dst_file, O_CREAT | O_WRONLY, 0644);
	if (dst_fd == -1) {
		ret = errno;
		printf("failed to open %s: %s\n", dst_file, strerror(errno));
		goto err_src_close;
	}

	ret = cloner_check_fs_support(src_fd, dst_fd, &fs_type);
	if (ret != 0) {
		goto err_dst_close;
	}

	if (full_file) {
		ret = clone_file(fs_type, src_fd, dst_fd);
	} else {
		ret = clone_file_range(fs_type, src_fd, dst_fd, src_off,
				       dst_off, len);
	}
	if (ret != 0) {
		printf("clone failed: %s\n", strerror(ret));
		goto err_dst_close;
	}

	ret = 0;
err_dst_close:
	if (close(dst_fd)) {
		ret |= errno;
		printf("failed to close dst file: %s\n", strerror(errno));
	}
err_src_close:
	if (close(src_fd)) {
		ret |= errno;
		printf("failed to close src file: %s\n", strerror(errno));
	}
err_dst_free:
	free(dst_file);
err_src_free:
	free(src_file);
err_out:
	return ret;
}
