[Libguestfs] Patch to build hivex lib on Windows

Jim Meyering jim at meyering.net
Sat Sep 3 18:01:03 UTC 2011


Richard W.M. Jones wrote:
> On Sat, Sep 03, 2011 at 04:45:28PM +0200, Gillen Daniel wrote:
>> 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;
>>  }

Thanks for the patch, Gillen, but as Rich says, parts look unnecessary.
In particular, why do you ifdef the uses of full_read and full_write?

I've Cc'd bug-gnulib.




More information about the Libguestfs mailing list