commit e654163a70de4946608ce436cb170e3549bdcfd5
parent d373a2f9a9542fa8b6b25be16c70eff6d03bccf7
Author: sin <sin@2f30.org>
Date: Sun, 3 Mar 2013 00:43:45 +0000
mdiff: Initial commit
Implement the file parsing routines for the mdiff file format.
This code has *not* been tested at all so far.
Diffstat:
5 files changed, 132 insertions(+), 3 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,6 +1,6 @@
BIN = memzap
VER = 0.1
-SRC = memzap.c mem.c utils.c md5.c linux_ops.c
+SRC = memzap.c mem.c utils.c md5.c mdiff.c linux_ops.c
OBJ = ${SRC:.c=.o}
PREFIX = /usr
diff --git a/Makefile.linux b/Makefile.linux
@@ -1,6 +1,6 @@
BIN = memzap
VER = 0.1
-SRC = memzap.c mem.c utils.c md5.c linux_ops.c
+SRC = memzap.c mem.c utils.c md5.c mdiff.c linux_ops.c
OBJ = ${SRC:.c=.o}
PREFIX = /usr
diff --git a/Makefile.openbsd b/Makefile.openbsd
@@ -1,6 +1,6 @@
BIN = memzap
VER = 0.1
-SRC = memzap.c mem.c utils.c md5.c openbsd_ops.c
+SRC = memzap.c mem.c utils.c md5.c mdiff.c openbsd_ops.c
OBJ = ${SRC:.c=.o}
PREFIX = /usr
diff --git a/mdiff.c b/mdiff.c
@@ -0,0 +1,104 @@
+#include "proto.h"
+
+int
+open_mdiff(const char *path)
+{
+ int fd;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ errx(1, "%s: %s", path, strerror(errno));
+ return fd;
+}
+
+int
+create_mdiff(const char *path)
+{
+ int fd;
+
+ fd = open(path, O_RDWR);
+ if (fd < 0)
+ errx(1, "%s: %s", path, strerror(errno));
+ return fd;
+}
+
+int
+close_mdiff(int fd)
+{
+ int ret;
+
+ if (fd < 0)
+ return -EINVAL;
+
+ ret = close(fd);
+ if (ret < 0)
+ err(1, "close");
+ return 0;
+}
+
+int
+parse_mdiff_hdr(int fd)
+{
+ struct mdiff_hdr hdr;
+ ssize_t ret;
+
+ if (fd < 0)
+ return -EINVAL;
+
+ ret = read(fd, &hdr, sizeof(hdr));
+ if (ret != sizeof(hdr))
+ err(1, "read");
+ if (memcmp(hdr.magic, "MDIFF", sizeof(hdr.magic)))
+ return -EINVAL;
+ if (!hdr.nregions)
+ return -EINVAL;
+ return 0;
+}
+
+int
+mdiff_insert_hdr(int fd, struct mdiff_hdr *hdr)
+{
+ int ret;
+
+ if (fd < 0 || !hdr)
+ return -EINVAL;
+
+ ret = lseek(fd, 0, SEEK_SET);
+ if (ret < 0)
+ err(1, "lseek");
+ ret = write(fd, hdr, sizeof(*hdr));
+ if (ret != sizeof(*hdr))
+ err(1, "write");
+ return 0;
+}
+
+int
+mdiff_append_rdiff(int fd, struct mem_region_diff *rdiff)
+{
+ struct mem_diff *md;
+ struct mdiff_region mdiff;
+ size_t i;
+ ssize_t ret;
+
+ if (fd < 0 || !rdiff)
+ return -EINVAL;
+
+ /* If this is an empty memory region diff, just bail out */
+ if (!rdiff->nmrdiffs)
+ return 0;
+
+ for (i = 0; i < rdiff->nmrdiffs; i++) {
+ md = &rdiff->mrdiffs[i];
+ mdiff.offset = md->offset;
+ mdiff.len = md->len;
+ /* TODO: Handle endianness issues here */
+ ret = write(fd, &mdiff, sizeof(mdiff));
+ if (ret != sizeof(mdiff))
+ err(1, "write");
+ ret = write(fd, md->buf, md->len);
+ if (ret != (ssize_t)md->len)
+ err(1, "write");
+ }
+
+ return 0;
+}
diff --git a/proto.h b/proto.h
@@ -100,6 +100,23 @@ struct mem_tree_entry {
};
RB_HEAD(mem_tree, mem_tree_entry);
+struct mdiff_hdr {
+ /* MDIFF\0 */
+ char magic[6];
+ /* Number of memory diff regions */
+ uint32_t nregions;
+};
+
+struct mdiff_region {
+ /* Offset into memory where this region should
+ * be written to */
+ uint32_t offset;
+ /* Length of this memory diff region */
+ uint32_t len;
+ /* Actual data */
+ char buf[];
+};
+
/* Return the number of blocks in a buffer of `len' bytes */
static inline size_t
num_blocks(size_t len)
@@ -138,4 +155,12 @@ int traceme(void);
int single_step(pid_t pid);
void readmem(pid_t pid, void *buf, void *offset, size_t size);
+/* mdiff.c */
+int open_mdiff(const char *path);
+int create_mdiff(const char *path);
+int close_mdiff(int fd);
+int parse_mdiff_hdr(int fd);
+int mdiff_insert_hdr(int fd, struct mdiff_hdr *hdr);
+int mdiff_append_rdiff(int fd, struct mem_region_diff *rdiff);
+
#endif