10d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o/*
20d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o * copy_sparse.c -- copy a very large sparse files efficiently
30d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o * 	(requires root privileges)
4efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
50d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o * Copyright 2003, 2004 by Theodore Ts'o.
60d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o *
70d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o * %Begin-Header%
80d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o * This file may be redistributed under the terms of the GNU Public
90d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o * License.
100d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o * %End-Header%
110d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o */
120d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
130d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#ifndef __linux__
140d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#include <stdio.h>
150d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#include <stdlib.h>
160d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
170d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'oint main(void) {
180d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o    fputs("This program is only supported on Linux!\n", stderr);
190d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o    exit(EXIT_FAILURE);
200d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o}
210d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#else
220d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#define _LARGEFILE64_SOURCE
230d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
240d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#include <stdio.h>
250d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#include <stdlib.h>
260d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#include <unistd.h>
270d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#include <string.h>
280d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#include <time.h>
290d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#include <fcntl.h>
300d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#include <errno.h>
310d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#ifdef HAVE_GETOPT_H
320d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#include <getopt.h>
330d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#else
340d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'oextern char *optarg;
350d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'oextern int optind;
360d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#endif
370d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#include <sys/types.h>
380d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#include <sys/stat.h>
390d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#include <sys/vfs.h>
400d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#include <sys/ioctl.h>
410d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#include <linux/fd.h>
420d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
430d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'oint verbose = 0;
440d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
450d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#define FIBMAP	   _IO(0x00,1)	/* bmap access */
460d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#define FIGETBSZ   _IO(0x00,2)	/* get the block size used for bmap */
470d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
480d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'ostatic unsigned long get_bmap(int fd, unsigned long block)
490d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o{
500d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	int	ret;
510d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	unsigned long b;
520d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
530d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	b = block;
540d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	ret = ioctl(fd, FIBMAP, &b);
550d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	if (ret < 0) {
560d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		if (errno == EPERM) {
570d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			fprintf(stderr, "No permission to use FIBMAP ioctl; must have root privileges\n");
580d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			exit(1);
590d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		}
600d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		perror("FIBMAP");
610d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	}
620d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	return b;
630d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o}
640d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
650d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'ostatic int full_read(int fd, char *buf, size_t count)
660d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o{
670d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	int got, total = 0;
680d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	int pass = 0;
690d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
700d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	while (count > 0) {
710d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		got = read(fd, buf, count);
720d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		if (got == -1) {
73efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			if ((errno == EINTR) || (errno == EAGAIN))
740d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o				continue;
750d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			return total ? total : -1;
760d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		}
770d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		if (got == 0) {
780d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			if (pass++ >= 3)
790d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o				return total;
800d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			continue;
810d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		}
820d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		pass = 0;
830d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		buf += got;
840d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		total += got;
850d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		count -= got;
860d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	}
870d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	return total;
880d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o}
890d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
900d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'ostatic void copy_sparse_file(const char *src, const char *dest)
910d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o{
920d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	struct stat64	fileinfo;
930d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	long		lb, i, fd, ofd, bs, block, numblocks;
940d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	ssize_t		got, got2;
950d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	off64_t		offset = 0, should_be;
960d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	char		*buf;
970d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
980d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	if (verbose)
990d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		printf("Copying sparse file from %s to %s\n", src, dest);
100efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1010d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	if (strcmp(src, "-")) {
1020d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		if (stat64(src, &fileinfo) < 0) {
1030d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			perror("stat");
1040d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			exit(1);
1050d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		}
1060d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		if (!S_ISREG(fileinfo.st_mode)) {
1070d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			printf("%s: Not a regular file\n", src);
1080d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			exit(1);
1090d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		}
1100d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		fd = open(src, O_RDONLY | O_LARGEFILE);
1110d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		if (fd < 0) {
1120d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			perror("open");
1130d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			exit(1);
1140d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		}
1150d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		if (ioctl(fd, FIGETBSZ, &bs) < 0) {
1160d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			perror("FIGETBSZ");
1170d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			close(fd);
1180d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			exit(1);
1190d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		}
1200d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		if (bs < 0) {
1210d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			printf("%s: Invalid block size: %ld\n", src, bs);
1220d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			exit(1);
1230d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		}
1240d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		if (verbose)
1250d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			printf("Blocksize of file %s is %ld\n", src, bs);
1260d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		numblocks = (fileinfo.st_size + (bs-1)) / bs;
1270d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		if (verbose)
128efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			printf("File size of %s is %lld (%ld blocks)\n", src,
1290d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			       (long long) fileinfo.st_size, numblocks);
1300d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	} else {
1310d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		fd = 0;
1320d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		bs = 1024;
1330d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	}
134efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1350d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	ofd = open(dest, O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, 0777);
1360d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	if (ofd < 0) {
1370d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		perror(dest);
1380d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		exit(1);
1390d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	}
1400d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
1410d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	buf = malloc(bs);
1420d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	if (!buf) {
1430d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		fprintf(stderr, "Couldn't allocate buffer");
1440d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		exit(1);
1450d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	}
146efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1470d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	for (lb = 0; !fd || lb < numblocks; lb++) {
1480d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		if (fd) {
1490d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			block = get_bmap(fd, lb);
1500d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			if (!block)
1510d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o				continue;
1520d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			should_be = ((off64_t) lb) * bs;
1530d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			if (offset != should_be) {
1540d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o				if (verbose)
1550d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o					printf("Seeking to %lld\n", should_be);
1560d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o				if (lseek64(fd, should_be, SEEK_SET) == (off_t) -1) {
1570d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o					perror("lseek src");
1580d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o					exit(1);
1590d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o				}
1600d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o				if (lseek64(ofd, should_be, SEEK_SET) == (off_t) -1) {
1610d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o					perror("lseek dest");
1620d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o					exit(1);
1630d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o				}
1640d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o				offset = should_be;
1650d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			}
1660d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		}
1670d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		got = full_read(fd, buf, bs);
1680d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
1690d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		if (fd == 0 && got == 0)
1700d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			break;
1710d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
1720d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		if (got == bs) {
173efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			for (i=0; i < bs; i++)
1740d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o				if (buf[i])
1750d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o					break;
1760d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			if (i == bs) {
1770d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o				lseek(ofd, bs, SEEK_CUR);
1780d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o				offset += bs;
1790d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o				continue;
1800d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			}
1810d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		}
1820d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		got2 = write(ofd, buf, got);
1830d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		if (got != got2) {
1840d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			printf("short write\n");
1850d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			exit(1);
1860d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		}
1870d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		offset += got;
1880d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	}
1890d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	offset = fileinfo.st_size;
1900d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	if (fstat64(ofd, &fileinfo) < 0) {
1910d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		perror("fstat");
1920d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		exit(1);
1930d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	}
1940d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	if (fileinfo.st_size != offset) {
1950d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		lseek64(ofd, offset-1, SEEK_CUR);
1960d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		buf[0] = 0;
1970d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		write(ofd, buf, 1);
1980d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	}
1990d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	close(fd);
2000d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	close(ofd);
2010d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o}
2020d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
2030d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'ostatic void usage(const char *progname)
2040d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o{
2050d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	fprintf(stderr, "Usage: %s [-v] source_file destination_file\n", progname);
2060d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	exit(1);
2070d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o}
2080d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
2090d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'oint main(int argc, char**argv)
2100d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o{
2110d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	int c;
2120d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
2130d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	while ((c = getopt(argc, argv, "v")) != EOF)
2140d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		switch (c) {
2150d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		case 'v':
2160d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			verbose++;
2170d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			break;
2180d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		default:
2190d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			usage(argv[0]);
2200d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o			break;
2210d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		}
2220d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	if (optind+2 != argc)
2230d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o		usage(argv[0]);
2240d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	copy_sparse_file(argv[optind], argv[optind+1]);
2250d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o
2260d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o	return 0;
2270d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o}
2280d2993dbab9f8365c85d5f476f28ffd44ca99896Theodore Ts'o#endif
229