memzap

replay memory writes
git clone git://git.2f30.org/memzap
Log | Files | Refs | README | LICENSE

mdiff.c (3041B)


      1 /* See LICENSE file for copyright and license details. */
      2 
      3 #include "proto.h"
      4 
      5 int
      6 open_mdiff(const char *path)
      7 {
      8 	int fd;
      9 
     10 	fd = open(path, O_RDONLY);
     11 	if (fd < 0)
     12 		errx(1, "%s: %s", path, strerror(errno));
     13 	return fd;
     14 }
     15 
     16 int
     17 create_mdiff(const char *path)
     18 {
     19 	int fd;
     20 
     21 	fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0644);
     22 	if (fd < 0)
     23 		errx(1, "%s: %s", path, strerror(errno));
     24 	return fd;
     25 }
     26 
     27 int
     28 close_mdiff(int fd)
     29 {
     30 	int ret;
     31 
     32 	if (fd < 0)
     33 		return -EINVAL;
     34 
     35 	ret = close(fd);
     36 	if (ret < 0)
     37 		err(1, "close");
     38 	return 0;
     39 }
     40 
     41 struct mdiff_hdr *
     42 parse_mdiff_hdr(int fd)
     43 {
     44 	struct mdiff_hdr *hdr;
     45 	ssize_t ret;
     46 
     47 	if (fd < 0)
     48 		return NULL;
     49 
     50 	hdr = xmalloc(sizeof(*hdr));
     51 	ret = read(fd, hdr, sizeof(*hdr));
     52 	if (ret != sizeof(*hdr))
     53 		err(1, "read");
     54 	if (strncmp((char *)hdr->magic, "MDIFF", 5))
     55 		return NULL;
     56 	if (!hdr->nregions)
     57 		return NULL;
     58 	return hdr;
     59 }
     60 
     61 int
     62 mdiff_insert_hdr(int fd, struct mdiff_hdr *hdr)
     63 {
     64 	int ret;
     65 
     66 	if (fd < 0 || !hdr)
     67 		return -EINVAL;
     68 
     69 	ret = lseek(fd, 0, SEEK_SET);
     70 	if (ret < 0)
     71 		err(1, "lseek");
     72 	ret = write(fd, hdr, sizeof(*hdr));
     73 	if (ret != sizeof(*hdr))
     74 		err(1, "write");
     75 	return 0;
     76 }
     77 
     78 int
     79 mdiff_start_diff(int fd)
     80 {
     81 	int ret;
     82 
     83 	if (fd < 0)
     84 		return -EINVAL;
     85 
     86 	ret = lseek(fd, sizeof(struct mdiff_hdr), SEEK_SET);
     87 	if (ret < 0)
     88 		err(1, "lseek");
     89 	return 0;
     90 }
     91 
     92 struct mdiff_region *
     93 mdiff_read_diff(int fd, struct mdiff_hdr *hdr, uint32_t region)
     94 {
     95 	int ret;
     96 	off_t offset;
     97 	struct mdiff_region *mdiff;
     98 	uint32_t i;
     99 	uint32_t len;
    100 
    101 	if (fd < 0 || !hdr)
    102 		return NULL;
    103 
    104 	if (region >= hdr->nregions)
    105 		return NULL;
    106 
    107 	offset = sizeof(*hdr);
    108 	ret = lseek(fd, offset, SEEK_SET);
    109 	if (ret < 0)
    110 		err(1, "lseek");
    111 
    112 	mdiff = xmalloc(sizeof(*mdiff));
    113 	for (i = 0; i < region; i++) {
    114 		ret = read(fd, mdiff, sizeof(*mdiff));
    115 		if (ret != sizeof(*mdiff))
    116 			err(1, "read");
    117 		offset += sizeof(*mdiff);
    118 		offset += mdiff->len;
    119 		ret = lseek(fd, offset, SEEK_SET);
    120 		if (ret < 0)
    121 			err(1, "lseek");
    122 	}
    123 
    124 	ret = read(fd, mdiff, sizeof(*mdiff));
    125 	if (ret != sizeof(*mdiff))
    126 		err(1, "read");
    127 
    128 	ret = lseek(fd, offset, SEEK_SET);
    129 	if (ret < 0)
    130 		err(1, "lseek");
    131 
    132 	len = mdiff->len;
    133 	mdiff = xrealloc(mdiff, sizeof(*mdiff) + len);
    134 	ret = read(fd, mdiff, sizeof(*mdiff) + len);
    135 	if ((size_t)ret != sizeof(*mdiff) + len)
    136 		err(1, "read");
    137 	return mdiff;
    138 }
    139 
    140 int
    141 mdiff_append_rdiff(int fd, struct mem_region_diff *rdiff,
    142 		   uint64_t cycle)
    143 {
    144 	struct mem_diff *md;
    145 	struct mdiff_region mdiff;
    146 	size_t i;
    147 	ssize_t ret;
    148 
    149 	if (fd < 0 || !rdiff)
    150 		return -EINVAL;
    151 
    152 	/* If this is an empty memory region diff, just bail out */
    153 	if (!rdiff->nmrdiffs)
    154 		return -EINVAL;
    155 
    156 	for (i = 0; i < rdiff->nmrdiffs; i++) {
    157 		md = &rdiff->mrdiffs[i];
    158 		mdiff.offset = md->offset;
    159 		mdiff.len = md->len;
    160 		mdiff.cycle = cycle;
    161 		/* TODO: Handle endianness issues here */
    162 		ret = write(fd, &mdiff, sizeof(mdiff));
    163 		if (ret != sizeof(mdiff))
    164 			err(1, "write");
    165 		ret = write(fd, md->buf, md->len);
    166 		if (ret != (ssize_t)md->len)
    167 			err(1, "write");
    168 	}
    169 	return i;
    170 }
    171 
    172 void
    173 free_mdiff_region(struct mdiff_region *mdiff)
    174 {
    175 	free(mdiff);
    176 }