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.