Ported ntfsclone to Windows

This mainly means using the functions in win32_io.c instead of the
standard msvcrt.dll ones in order to be able to truncate files and
create sparse ones.
edge.strict_endians
Jean-Pierre André 2013-02-09 12:54:44 +01:00
parent 88de9987a0
commit e6eae9fa16
1 changed files with 98 additions and 12 deletions

View File

@ -95,10 +95,37 @@
#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* Get device size in bytes. */
#endif
#ifdef __sun
#if defined(linux) || defined(__uClinux__) || defined(__sun) \
|| defined(__APPLE__) || defined(__DARWIN__)
/* Make sure the presence of <windows.h> means compiling for Windows */
#undef HAVE_WINDOWS_H
#endif
#if defined(__sun) | defined(HAVE_WINDOWS_H)
#define NO_STATFS 1 /* statfs(2) and f_type are not universal */
#endif
#ifdef HAVE_WINDOWS_H
/*
* Replacements for functions which do not exist on Windows
*/
int setmode(int, int); /* from msvcrt.dll */
#define getpid() (0)
#define srandom(seed) srand(seed)
#define random() rand()
#define fsync(fd) (0)
#define ioctl(fd,code,buf) (0)
#define ftruncate(fd, size) ntfs_device_win32_ftruncate(dev_out, size)
#define BINWMODE "wb"
#else
#define BINWMODE "w"
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
static const char *EXEC_NAME = "ntfsclone";
static const char *bad_sectors_warning_msg =
@ -172,6 +199,7 @@ static struct bitmap lcn_bitmap;
static int fd_in;
static int fd_out;
static FILE *stream_out = (FILE*)NULL;
struct ntfs_device *dev_out = (struct ntfs_device*)NULL;
static FILE *msg_out = NULL;
static int wipe = 0;
@ -477,8 +505,14 @@ static void parse_options(int argc, char **argv)
if (!opt.no_action && !opt.std_out) {
struct stat st;
#ifdef HAVE_WINDOWS_H
BOOL blkdev = opt.output[0] && (opt.output[1] == ':')
&& !opt.output[2];
if (!blkdev && (stat(opt.output, &st) == -1)) {
#else
if (stat(opt.output, &st) == -1) {
#endif
if (errno != ENOENT)
perr_exit("Couldn't access '%s'", opt.output);
} else {
@ -487,7 +521,11 @@ static void parse_options(int argc, char **argv)
"Use option --overwrite if you want to"
" replace its content.\n", opt.output);
#ifdef HAVE_WINDOWS_H
if (blkdev) {
#else
if (S_ISBLK(st.st_mode)) {
#endif
opt.blkdev_out = 1;
if (opt.metadata && !opt.force)
err_exit("Cloning only metadata to a "
@ -606,6 +644,11 @@ static int io_all(void *fd, void *buf, int count, int do_write)
} else {
if (opt.save_image || opt.metadata_image)
i = fwrite(buf, 1, count, stream_out);
#ifdef HAVE_WINDOWS_H
else if (dev_out)
i = dev_out->d_ops->write(dev_out,
buf, count);
#endif
else
i = write(*(int *)fd, buf, count);
}
@ -778,6 +821,17 @@ static void copy_cluster(int rescue, u64 rescue_lcn, u64 lcn)
}
}
static s64 lseek_out(int fd, s64 pos, int mode)
{
s64 ret;
if (dev_out)
ret = (dev_out->d_ops->seek)(dev_out, pos, mode);
else
ret = lseek(fd, pos, mode);
return (ret);
}
static void lseek_to_cluster(s64 lcn)
{
off_t pos;
@ -790,8 +844,8 @@ static void lseek_to_cluster(s64 lcn)
if (opt.std_out || opt.save_image || opt.metadata_image)
return;
if (lseek(fd_out, pos, SEEK_SET) == (off_t)-1)
perr_exit("lseek output");
if (lseek_out(fd_out, pos, SEEK_SET) == (off_t)-1)
perr_exit("lseek output");
}
static void gap_to_cluster(s64 gap)
@ -975,11 +1029,12 @@ static void restore_image(void)
err_exit("restore_image: corrupt image "
"at input offset %lld\n",
(long long)tellin(fd_in) - 9);
else
else {
if (!opt.no_action
&& (lseek(fd_out, count * csize,
&& (lseek_out(fd_out, count * csize,
SEEK_CUR) == (off_t)-1))
perr_exit("restore_image: lseek");
}
}
pos += count;
} else if (cmd == CMD_NEXT) {
@ -2215,9 +2270,13 @@ static s64 open_image(void)
{
if (strcmp(opt.volume, "-") == 0) {
if ((fd_in = fileno(stdin)) == -1)
perr_exit("fileno for stdout failed");
perr_exit("fileno for stdin failed");
#ifdef HAVE_WINDOWS_H
if (setmode(fd_in,O_BINARY) == -1)
perr_exit("setting binary stdin failed");
#endif
} else {
if ((fd_in = open(opt.volume, O_RDONLY)) == -1)
if ((fd_in = open(opt.volume, O_RDONLY | O_BINARY)) == -1)
perr_exit("failed to open image");
}
if (read_all(&fd_in, &image_hdr, NTFSCLONE_IMG_HEADER_SIZE_OLD) == -1)
@ -2323,7 +2382,12 @@ static void initialise_image_hdr(s64 device_size, s64 inuse)
static void check_output_device(s64 input_size)
{
if (opt.blkdev_out) {
s64 dest_size = device_size_get(fd_out);
s64 dest_size;
if (dev_out)
dest_size = ntfs_device_size_get(dev_out, 1);
else
dest_size = device_size_get(fd_out);
if (dest_size < input_size)
err_exit("Output device is too small (%lld) to fit the "
"NTFS image (%lld).\n",
@ -2414,6 +2478,7 @@ static void ignore_bad_clusters(ntfs_walk_clusters_ctx *image)
static void check_dest_free_space(u64 src_bytes)
{
#ifndef HAVE_WINDOWS_H
u64 dest_bytes;
struct statvfs stvfs;
struct stat st;
@ -2446,6 +2511,7 @@ static void check_dest_free_space(u64 src_bytes)
"%llu MB < %llu MB\n",
(unsigned long long)rounded_up_division(dest_bytes, NTFS_MBYTE),
(unsigned long long)rounded_up_division(src_bytes, NTFS_MBYTE));
#endif
}
int main(int argc, char **argv)
@ -2486,9 +2552,13 @@ int main(int argc, char **argv)
if ((fd_out = fileno(stdout)) == -1)
perr_exit("fileno for stdout failed");
stream_out = stdout;
#ifdef HAVE_WINDOWS_H
if (setmode(fileno(stdout),O_BINARY) == -1)
perr_exit("setting binary stdout failed");
#endif
} else {
/* device_size_get() might need to read() */
int flags = O_RDWR;
int flags = O_RDWR | O_BINARY;
fd_out = 0;
if (!opt.blkdev_out) {
@ -2498,17 +2568,29 @@ int main(int argc, char **argv)
}
if (opt.save_image || opt.metadata_image) {
stream_out = fopen(opt.output,"w");
stream_out = fopen(opt.output,BINWMODE);
if (!stream_out)
perr_exit("Opening file '%s' failed",
opt.output);
fd_out = fileno(stream_out);
} else
} else {
#ifdef HAVE_WINDOWS_H
if (!opt.no_action) {
dev_out = ntfs_device_alloc(opt.output, 0,
&ntfs_device_default_io_ops, NULL);
if (!dev_out
|| (dev_out->d_ops->open)(dev_out, flags))
perr_exit("Opening volume '%s' failed",
opt.output);
}
#else
if (!opt.no_action
&& ((fd_out = open(opt.output, flags,
S_IRUSR | S_IWUSR)) == -1))
perr_exit("Opening file '%s' failed",
opt.output);
#endif
}
if (!opt.save_image && !opt.metadata_image && !opt.no_action)
check_output_device(ntfs_size);
@ -2558,7 +2640,11 @@ int main(int argc, char **argv)
initialise_image_hdr(device_size, image.inuse);
write_image_hdr();
} else {
fsync_clone(fd_out); /* sync copy before mounting */
if (dev_out) {
(dev_out->d_ops->close)(dev_out);
dev_out = NULL;
} else
fsync_clone(fd_out); /* sync copy before mounting */
opt.volume = opt.output;
/* 'force' again mount for dirty volumes (e.g. after resize).
FIXME: use mount flags to avoid potential side-effects in future */