summaryrefslogtreecommitdiffstats
path: root/hivex/hivex.c
diff options
context:
space:
mode:
authorRichard Jones <rjones@redhat.com>2010-01-18 11:08:56 +0000
committerRichard Jones <rjones@redhat.com>2010-02-04 11:06:33 +0000
commit4718aeb9f0f743a05dfa342bc797617f3b9f96b3 (patch)
tree06d2895a0973e41a877fe1edfbb733518262ae0a /hivex/hivex.c
parentdb8a46aa1165479ddf2b551e81a7e96bb06fc942 (diff)
downloadlibguestfs-4718aeb9f0f743a05dfa342bc797617f3b9f96b3.tar.gz
libguestfs-4718aeb9f0f743a05dfa342bc797617f3b9f96b3.tar.xz
libguestfs-4718aeb9f0f743a05dfa342bc797617f3b9f96b3.zip
hivex: Add HIVEX_OPEN_WRITE flag to allow hive to be opened for writing.
If this flag is omitted (as in the case for all existing callers) then the hive is still opened read-only. We add a 'writable' flag to the hive handle, and we change the way that the hive file (data) is stored. The data is still mmapped if the file is opened read-only, since that is more efficient and allows us to handle larger hives. However if we need to write to the file then we have to read it all into memory, since if we had to extend the file we need to realloc that data. Note the manpage section L</WRITING TO HIVE FILES> comes in a later commit.
Diffstat (limited to 'hivex/hivex.c')
-rw-r--r--hivex/hivex.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/hivex/hivex.c b/hivex/hivex.c
index e0118aff..44f29984 100644
--- a/hivex/hivex.c
+++ b/hivex/hivex.c
@@ -34,6 +34,12 @@
#include <sys/stat.h>
#include <assert.h>
+#include "full-read.h"
+
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
#define STREQ(a,b) (strcmp((a),(b)) == 0)
#define STRCASEEQ(a,b) (strcasecmp((a),(b)) == 0)
//#define STRNEQ(a,b) (strcmp((a),(b)) != 0)
@@ -54,8 +60,9 @@ struct hive_h {
int fd;
size_t size;
int msglvl;
+ int writable;
- /* Memory-mapped (readonly) registry file. */
+ /* Registry file, memory mapped if read-only, or malloc'd if writing. */
union {
char *addr;
struct ntreg_header *hdr;
@@ -260,11 +267,12 @@ hivex_open (const char *filename, int flags)
if (h->msglvl >= 2)
fprintf (stderr, "hivex_open: created handle %p\n", h);
+ h->writable = !!(flags & HIVEX_OPEN_WRITE);
h->filename = strdup (filename);
if (h->filename == NULL)
goto error;
- h->fd = open (filename, O_RDONLY);
+ h->fd = open (filename, O_RDONLY | O_CLOEXEC);
if (h->fd == -1)
goto error;
@@ -274,12 +282,21 @@ hivex_open (const char *filename, int flags)
h->size = statbuf.st_size;
- h->addr = mmap (NULL, h->size, PROT_READ, MAP_SHARED, h->fd, 0);
- if (h->addr == MAP_FAILED)
- goto error;
+ if (!h->writable) {
+ h->addr = mmap (NULL, h->size, PROT_READ, MAP_SHARED, h->fd, 0);
+ if (h->addr == MAP_FAILED)
+ goto error;
- if (h->msglvl >= 2)
- fprintf (stderr, "hivex_open: mapped file at %p\n", h->addr);
+ if (h->msglvl >= 2)
+ fprintf (stderr, "hivex_open: mapped file at %p\n", h->addr);
+ } else {
+ h->addr = malloc (h->size);
+ if (h->addr == NULL)
+ goto error;
+
+ if (full_read (h->fd, h->addr, h->size) < h->size)
+ goto error;
+ }
/* Check header. */
if (h->hdr->magic[0] != 'r' ||
@@ -471,8 +488,12 @@ hivex_open (const char *filename, int flags)
int err = errno;
if (h) {
free (h->bitmap);
- if (h->addr && h->size && h->addr != MAP_FAILED)
- munmap (h->addr, h->size);
+ if (h->addr && h->size && h->addr != MAP_FAILED) {
+ if (!h->writable)
+ munmap (h->addr, h->size);
+ else
+ free (h->addr);
+ }
if (h->fd >= 0)
close (h->fd);
free (h->filename);
@@ -488,7 +509,10 @@ hivex_close (hive_h *h)
int r;
free (h->bitmap);
- munmap (h->addr, h->size);
+ if (!h->writable)
+ munmap (h->addr, h->size);
+ else
+ free (h->addr);
r = close (h->fd);
free (h->filename);
free (h);