diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2006-06-26 20:08:57 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2006-06-26 20:08:57 +0000 |
commit | beac80cd437fb383eeaccc4224a4d7faebd77a23 (patch) | |
tree | 039fce388291883e48c5d8a45a0548e54f9ad3f3 /block.c | |
parent | 3587d7e69cd25f14eccec01c547f1257171fde7b (diff) |
Windows sparse file support (Frediano Ziglio)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2027 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'block.c')
-rw-r--r-- | block.c | 46 |
1 files changed, 46 insertions, 0 deletions
@@ -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; |