On Sat, Sep 03, 2011 at 04:45:28PM +0200, Gillen Daniel wrote:
Hi
I'm just posting this here in case someone is interested in building
hivex on Windows (mingw32). The attached patch allows building the
lib but not the tools (hivexsh etc..) as there are some more
problems to solve.
In short terms, this patch replaces file i/o functions and mmap(),
munmap() with their win32api pendants.
NACK ... This patch is too invasive.
We are already linking with gnulib, which ought to provide a degree of
platform independence. By adding the right gnulib modules (see the
file 'bootstrap' in the toplevel directory) it should be possible to
make hivex compile directly on Windows, while requiring fewer source
code changes.
gnulib can almost certainly do all the file things. I don't see a
gnulib module for mmap, which could be a problem, but a less invasive
change should still be possible for that.
Rich.
diff --git a/lib/hivex.c b/lib/hivex.c
index 4b9fcf0..986bdeb 100644
--- a/lib/hivex.c
+++ b/lib/hivex.c
@@ -30,13 +30,19 @@
#include <unistd.h>
#include <errno.h>
#include <iconv.h>
-#include <sys/mman.h>
+#ifndef __MINGW32__
+ #include <sys/mman.h>
+#else
+ #include <windows.h>
+#endif
#include <sys/stat.h>
#include <assert.h>
#include "c-ctype.h"
-#include "full-read.h"
-#include "full-write.h"
+#ifndef __MINGW32__
+ #include "full-read.h"
+ #include "full-write.h"
+#endif
#define STREQ(a,b) (strcmp((a),(b)) == 0)
#define STRCASEEQ(a,b) (strcasecmp((a),(b)) == 0)
@@ -62,7 +68,13 @@ static size_t utf16_string_len_in_bytes_max (const char *str, size_t
len);
struct hive_h {
char *filename;
+#ifndef __MINGW32__
int fd;
+#else
+ HANDLE fd;
+ HANDLE winmap;
+#endif
+
size_t size;
int msglvl;
int writable;
@@ -294,28 +306,48 @@ hivex_open (const char *filename, int flags)
if (h->filename == NULL)
goto error;
-#ifdef O_CLOEXEC
- h->fd = open (filename, O_RDONLY | O_CLOEXEC);
-#else
- h->fd = open (filename, O_RDONLY);
-#endif
- if (h->fd == -1)
- goto error;
-#ifndef O_CLOEXEC
- fcntl (h->fd, F_SETFD, FD_CLOEXEC);
-#endif
-
+#ifndef __MINGW32__
+ #ifdef O_CLOEXEC
+ h->fd = open (filename, O_RDONLY | O_CLOEXEC);
+ #else
+ h->fd = open (filename, O_RDONLY);
+ #endif
+ if (h->fd == -1)
+ goto error;
+ #ifndef O_CLOEXEC
+ fcntl (h->fd, F_SETFD, FD_CLOEXEC);
+ #endif
+
struct stat statbuf;
if (fstat (h->fd, &statbuf) == -1)
goto error;
h->size = statbuf.st_size;
+#else
+ h->fd = CreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h->fd == INVALID_HANDLE_VALUE)
+ goto error;
+
+ // XXX: There might be a problem if hive > 2^32 bytes
+ h->size = GetFileSize (h->fd, NULL);
+#endif
if (!h->writable) {
+#ifndef __MINGW32__
h->addr = mmap (NULL, h->size, PROT_READ, MAP_SHARED, h->fd, 0);
if (h->addr == MAP_FAILED)
goto error;
-
+#else
+ // Mingw does not support mmap, we have to use native API
+ // Create file mapping
+ h->winmap = CreateFileMapping (h->fd, NULL, PAGE_READONLY, 0, 0, NULL);
+ if (h->winmap == NULL)
+ goto error;
+ // Create map view
+ h->addr = MapViewOfFile (h->winmap, FILE_MAP_READ, 0, 0, h->size);
+ if (h->addr == NULL)
+ goto error;
+#endif
if (h->msglvl >= 2)
fprintf (stderr, "hivex_open: mapped file at %p\n", h->addr);
} else {
@@ -323,15 +355,29 @@ hivex_open (const char *filename, int flags)
if (h->addr == NULL)
goto error;
+#ifndef __MINGW32__
if (full_read (h->fd, h->addr, h->size) < h->size)
goto error;
+#else
+ DWORD bytes_read=0;
+ if (!ReadFile (h->fd, h->addr, h->size, &bytes_read, NULL))
+ goto error;
+ if (bytes_read != h->size)
+ goto error;
+#endif
/* We don't need the file descriptor along this path, since we
* have read all the data.
*/
+#ifndef __MINGW32__
if (close (h->fd) == -1)
goto error;
h->fd = -1;
+#else
+ if (!CloseHandle (h->fd))
+ goto error;
+ h->fd = INVALID_HANDLE_VALUE;
+#endif
}
/* Check header. */
@@ -532,14 +578,28 @@ hivex_open (const char *filename, int flags)
int err = errno;
if (h) {
free (h->bitmap);
+#ifndef __MINGW32__
if (h->addr && h->size && h->addr != MAP_FAILED) {
- if (!h->writable)
+#else
+ if (h->addr && h->size && h->addr != NULL) {
+#endif
+ if (!h->writable) {
+#ifndef __MINGW32__
munmap (h->addr, h->size);
- else
+#else
+ UnmapViewOfFile (h->addr);
+ CloseHandle (h->winmap);
+#endif
+ } else
free (h->addr);
}
+#ifndef __MINGW32__
if (h->fd >= 0)
close (h->fd);
+#else
+ if (h->fd != INVALID_HANDLE_VALUE)
+ CloseHandle (h->fd);
+#endif
free (h->filename);
free (h);
}
@@ -556,12 +616,22 @@ hivex_close (hive_h *h)
fprintf (stderr, "hivex_close\n");
free (h->bitmap);
- if (!h->writable)
+ if (!h->writable) {
+#ifndef __MINGW32__
munmap (h->addr, h->size);
- else
+#else
+ UnmapViewOfFile (h->addr);
+ CloseHandle (h->winmap);
+#endif
+ } else
free (h->addr);
+#ifndef __MINGW32__
if (h->fd >= 0)
r = close (h->fd);
+#else
+ if (h->fd != INVALID_HANDLE_VALUE)
+ r = CloseHandle (h->fd) ? 0 : 1;
+#endif
else
r = 0;
free (h->filename);
@@ -2100,9 +2170,15 @@ hivex_commit (hive_h *h, const char *filename, int flags)
}
filename = filename ? : h->filename;
+#ifndef __MINGW32__
int fd = open (filename, O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0666);
if (fd == -1)
return -1;
+#else
+ HANDLE fd = CreateFile (filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
+ if (fd == INVALID_HANDLE_VALUE)
+ return -1;
+#endif
/* Update the header fields. */
uint32_t sequence = le32toh (h->hdr->sequence1);
@@ -2119,6 +2195,7 @@ hivex_commit (hive_h *h, const char *filename, int flags)
if (h->msglvl >= 2)
fprintf (stderr, "hivex_commit: new header checksum: 0x%x\n", sum);
+#ifndef __MINGW32__
if (full_write (fd, h->addr, h->size) != h->size) {
int err = errno;
close (fd);
@@ -2128,6 +2205,20 @@ hivex_commit (hive_h *h, const char *filename, int flags)
if (close (fd) == -1)
return -1;
+#else
+ DWORD bytes_written;
+ if (!WriteFile (fd, h->addr, h->size, &bytes_written, NULL)) {
+ CloseHandle (fd);
+ return -1;
+ }
+ if (bytes_written != h->size) {
+ CloseHandle (fd);
+ return -1;
+ }
+
+ if (!CloseHandle (fd))
+ return -1;
+#endif
return 0;
}
_______________________________________________
Libguestfs mailing list
Libguestfs(a)redhat.com
https://www.redhat.com/mailman/listinfo/libguestfs
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
virt-df lists disk usage of guests without needing to install any
software inside the virtual machine. Supports Linux and Windows.
http://et.redhat.com/~rjones/virt-df/