aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog1
-rw-r--r--block.c46
-rw-r--r--vl.h5
3 files changed, 50 insertions, 2 deletions
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 <windows.h>
+#include <winioctl.h>
+
+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)
{