* Merge two diff files into one single file * Note: It does not do the merging work if * either of the source diff files is stripped, * since which complicates the process and is * rarely used */
| 155 | * rarely used |
| 156 | */ |
| 157 | static int do_merge_diff(const char *first, const char *second, |
| 158 | const char *path, bool no_progress) |
| 159 | { |
| 160 | utils::ProgressContext pc("Merging image diff", no_progress); |
| 161 | int fd = -1, sd = -1, pd = -1, r; |
| 162 | |
| 163 | string f_from, f_to; |
| 164 | string s_from, s_to; |
| 165 | uint64_t f_size = 0; |
| 166 | uint64_t s_size = 0; |
| 167 | uint64_t pc_size; |
| 168 | |
| 169 | __u8 f_tag = 0, s_tag = 0; |
| 170 | uint64_t f_off = 0, f_len = 0; |
| 171 | uint64_t s_off = 0, s_len = 0; |
| 172 | bool f_end = false, s_end = false; |
| 173 | |
| 174 | bool first_stdin = !strcmp(first, "-"); |
| 175 | if (first_stdin) { |
| 176 | fd = STDIN_FILENO; |
| 177 | } else { |
| 178 | fd = open(first, O_RDONLY|O_BINARY); |
| 179 | if (fd < 0) { |
| 180 | r = -errno; |
| 181 | std::cerr << "rbd: error opening " << first << std::endl; |
| 182 | goto done; |
| 183 | } |
| 184 | } |
| 185 | |
| 186 | sd = open(second, O_RDONLY|O_BINARY); |
| 187 | if (sd < 0) { |
| 188 | r = -errno; |
| 189 | std::cerr << "rbd: error opening " << second << std::endl; |
| 190 | goto done; |
| 191 | } |
| 192 | |
| 193 | if (strcmp(path, "-") == 0) { |
| 194 | pd = 1; |
| 195 | } else { |
| 196 | pd = open(path, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0644); |
| 197 | if (pd < 0) { |
| 198 | r = -errno; |
| 199 | std::cerr << "rbd: error create " << path << std::endl; |
| 200 | goto done; |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | //We just handle the case like 'banner, [ftag], [ttag], stag, [wztag]*,etag', |
| 205 | // and the (offset,length) in wztag must be ascending order. |
| 206 | r = parse_diff_header(fd, &f_tag, &f_from, &f_to, &f_size); |
| 207 | if (r < 0) { |
| 208 | std::cerr << "rbd: failed to parse first diff header" << std::endl; |
| 209 | goto done; |
| 210 | } |
| 211 | |
| 212 | r = parse_diff_header(sd, &s_tag, &s_from, &s_to, &s_size); |
| 213 | if (r < 0) { |
| 214 | std::cerr << "rbd: failed to parse second diff header" << std::endl; |
no test coverage detected