diff --git a/Changelog b/Changelog index 0b0d2a45f0..df487a54e6 100644 --- a/Changelog +++ b/Changelog @@ -10,6 +10,7 @@ version 0.8.2: - USB updates (Paul Brook) - UDP character devices (Jason Wessel) - TCP character devices + - Windows sparse file support (Frediano Ziglio) version 0.8.1: diff --git a/block.c b/block.c index c25c6869a6..ceb0532bd0 100644 --- a/block.c +++ b/block.c @@ -761,6 +761,51 @@ static void raw_close(BlockDriverState *bs) close(s->fd); } +#ifdef _WIN32 +#include +#include + +int qemu_ftruncate64(int fd, int64_t length) +{ + LARGE_INTEGER li; + LONG high; + HANDLE h; + BOOL res; + + if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0) + return -1; + + h = (HANDLE)_get_osfhandle(fd); + + /* get current position, ftruncate do not change position */ + li.HighPart = 0; + li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT); + if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR) + return -1; + + high = length >> 32; + if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN)) + return -1; + res = SetEndOfFile(h); + + /* back to old position */ + SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN); + return res ? 0 : -1; +} + +static int set_sparse(int fd) +{ + DWORD returned; + return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE, + NULL, 0, NULL, 0, &returned, NULL); +} +#else +static inline int set_sparse(int fd) +{ + return 1; +} +#endif + static int raw_create(const char *filename, int64_t total_size, const char *backing_file, int flags) { @@ -773,6 +818,7 @@ static int raw_create(const char *filename, int64_t total_size, 0644); if (fd < 0) return -EIO; + set_sparse(fd); ftruncate(fd, total_size * 512); close(fd); return 0; diff --git a/vl.h b/vl.h index fb72dd55e7..244310fee1 100644 --- a/vl.h +++ b/vl.h @@ -51,8 +51,9 @@ #define fsync _commit #define lseek _lseeki64 #define ENOTSUP 4096 -/* XXX: find 64 bit version */ -#define ftruncate chsize +extern int qemu_ftruncate64(int, int64_t); +#define ftruncate qemu_ftruncate64 + static inline char *realpath(const char *path, char *resolved_path) {