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