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 }