Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2017, Citrix Systems, Inc.
3 : : *
4 : : * All rights reserved.
5 : : *
6 : : * Redistribution and use in source and binary forms, with or without
7 : : * modification, are permitted provided that the following conditions are met:
8 : : *
9 : : * 1. Redistributions of source code must retain the above copyright
10 : : * notice, this list of conditions and the following disclaimer.
11 : : * 2. Redistributions in binary form must reproduce the above copyright
12 : : * notice, this list of conditions and the following disclaimer in the
13 : : * documentation and/or other materials provided with the distribution.
14 : : * 3. Neither the name of the copyright holder nor the names of its
15 : : * contributors may be used to endorse or promote products derived from
16 : : * this software without specific prior written permission.
17 : : *
18 : : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 : : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 : : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 : : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
22 : : * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 : : * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 : : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 : : * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 : : * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 : : * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 : : * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 : : */
30 : :
31 : : #ifdef HAVE_CONFIG_H
32 : : #include "config.h"
33 : : #endif
34 : :
35 : : #include <errno.h>
36 : : #include <stdio.h>
37 : : #include <stdlib.h>
38 : : #include <string.h>
39 : : #include <unistd.h>
40 : : #include <stdint.h>
41 : : #include <inttypes.h>
42 : :
43 : : #include "cbt-util.h"
44 : : #include "cbt-util-priv.h"
45 : :
46 : : int cbt_util_create(int , char **);
47 : : int cbt_util_set(int , char **);
48 : : int cbt_util_get(int , char **);
49 : : int cbt_util_coalesce(int , char **);
50 : :
51 : : struct command commands[] = {
52 : : { .name = "create", .func = cbt_util_create},
53 : : { .name = "set", .func = cbt_util_set},
54 : : { .name = "get", .func = cbt_util_get},
55 : : { .name = "coalesce", .func = cbt_util_coalesce},
56 : : };
57 : :
58 : : #define print_commands() \
59 : : do { \
60 : : int i, n; \
61 : : n = sizeof(commands) / sizeof(struct command); \
62 : : printf("COMMAND := { "); \
63 : : printf("%s", commands[0].name); \
64 : : for (i = 1; i < n; i++) \
65 : : printf(" | %s", commands[i].name); \
66 : : printf(" }\n"); \
67 : : } while (0)
68 : :
69 : : int
70 : 23 : malloc_cbt_log_data(struct cbt_log_data **log_data)
71 : : {
72 : 23 : int err = 0;
73 : :
74 : 23 : *log_data = malloc(sizeof(struct cbt_log_data));
75 [ + + ]: 23 : if (!*log_data) {
76 : 2 : fprintf(stderr, "Failed to allocate memory for CBT log\n");
77 : 2 : err = -ENOMEM;
78 : : }
79 : : else
80 : 21 : (*log_data)->bitmap = NULL;
81 : :
82 : 23 : return err;
83 : : }
84 : :
85 : : int
86 : 25 : file_open(FILE **f, char * name, char *mode)
87 : : {
88 : 25 : int err = 0;
89 : :
90 : 25 : *f = fopen(name, mode);
91 [ + + ]: 25 : if (*f == NULL) {
92 : 2 : fprintf(stderr, "Failed to open log file %s. %s\n",
93 : 2 : name, strerror(errno));
94 : 2 : err = -errno;
95 : : }
96 : :
97 : 25 : return err;
98 : : }
99 : :
100 : : int
101 : 21 : read_cbt_metadata(char *name, FILE *f, struct cbt_log_metadata *log_meta)
102 : : {
103 : 21 : int err = 0, ret;
104 : :
105 : 21 : ret = fread(log_meta, sizeof(struct cbt_log_metadata), 1, f);
106 : :
107 [ + + ]: 21 : if (!ret) {
108 : 2 : fprintf(stderr, "Failed to read CBT metadata from file %s, error %s\n", name, strerror(ferror(f)));
109 : 2 : err = -EIO;
110 : : }
111 : :
112 : 21 : return err;
113 : : }
114 : :
115 : : int
116 : 12 : allocate_cbt_bitmap(struct cbt_log_data *log_data)
117 : : {
118 : 12 : int err = 0;
119 : :
120 : 24 : uint64_t bmsize = bitmap_size(log_data->metadata.size);
121 : 12 : log_data->bitmap = malloc(bmsize);
122 [ + + ]: 12 : if (!log_data->bitmap) {
123 : 2 : fprintf(stderr, "Failed to allocate memory for bitmap buffer\n");
124 : 2 : err = -ENOMEM;
125 : : }
126 : :
127 : 12 : return err;
128 : : }
129 : :
130 : : int
131 : 10 : read_cbt_bitmap(FILE *f, struct cbt_log_data *log_data)
132 : : {
133 : 10 : int err = 0, ret;
134 : 20 : uint64_t bmsize = bitmap_size(log_data->metadata.size);
135 : :
136 : 20 : ret = fread(log_data->bitmap, bmsize, 1, f);
137 : :
138 [ + + ]: 10 : if (!ret) {
139 : 2 : fprintf(stderr, "Failed to read bitmap\n");
140 : 2 : err = -EIO;
141 : : }
142 : :
143 : 10 : return err;
144 : : }
145 : :
146 : : int
147 : 13 : cbt_util_get(int argc, char **argv)
148 : : {
149 : : char *name, uuid_str[37], *buf;
150 : : int err, c, ret;
151 : : int parent, child, flag, size, bitmap;
152 : 13 : FILE *f = NULL;
153 : :
154 : 13 : err = 0;
155 : 13 : name = NULL;
156 : 13 : parent = 0;
157 : 13 : child = 0;
158 : 13 : flag = 0;
159 : 13 : size = 0;
160 : 13 : buf = NULL;
161 : 13 : bitmap = 0;
162 : :
163 [ + - ]: 13 : if (!argc || !argv)
164 : : goto usage;
165 : :
166 : : /* Make sure we start from the start of the args */
167 : 13 : optind = 1;
168 : :
169 [ + + ]: 36 : while ((c = getopt(argc, argv, "n:pcfsbh")) != -1) {
170 [ + + + + : 23 : switch (c) {
+ + - ]
171 : : case 'n':
172 : 12 : name = optarg;
173 : 12 : break;
174 : : case 'p':
175 : : parent = 1;
176 : : break;
177 : : case 'c':
178 : 5 : child = 1;
179 : 5 : break;
180 : : case 'f':
181 : 1 : flag = 1;
182 : 1 : break;
183 : : case 's':
184 : 1 : size = 1;
185 : 1 : break;
186 : : case 'b':
187 : 3 : bitmap = 1;
188 : 23 : break;
189 : : case 'h':
190 : : default:
191 : : goto usage;
192 : : }
193 : : }
194 : :
195 : : // Exactly one of p, c, f or b must be queried for
196 [ + + ][ + + ]: 13 : if (!name || (parent + child + flag + size + bitmap != 1))
197 : : goto usage;
198 : :
199 : 10 : struct cbt_log_metadata *log_meta = malloc(sizeof(struct cbt_log_metadata));
200 [ + + ]: 10 : if (!log_meta) {
201 : 1 : fprintf(stderr, "Failed to allocate memory for CBT log metadata\n");
202 : : err = -ENOMEM;
203 : : goto error;
204 : : }
205 : :
206 : 9 : f = fopen(name, "r");
207 [ + + ]: 9 : if (f == NULL) {
208 : 1 : fprintf(stderr, "Failed to open log file %s. %s\n",
209 : 1 : name, strerror(errno));
210 : 1 : err = -errno;
211 : 1 : goto error;
212 : : }
213 : :
214 : 8 : ret = fread(log_meta, sizeof(struct cbt_log_metadata), 1, f);
215 : :
216 [ + + ]: 8 : if (!ret) {
217 : 1 : fprintf(stderr, "Failed to read CBT metadata from file %s\n", name);
218 : : err = -EIO;
219 : : goto error;
220 : : }
221 : :
222 [ + + ]: 7 : if (parent) {
223 : 1 : uuid_unparse(log_meta->parent, uuid_str);
224 : : printf("%s\n", uuid_str);
225 : : }
226 [ + + ]: 6 : else if (child) {
227 : 1 : uuid_unparse(log_meta->child, uuid_str);
228 : : printf("%s\n", uuid_str);
229 [ + + ]: 5 : } else if(flag) {
230 : 1 : printf("%d\n", log_meta->consistent);
231 [ + + ]: 4 : } else if(size) {
232 : 1 : printf("%"PRIu64"\n", log_meta->size);
233 : : }
234 : : else {
235 : 6 : uint64_t bmsize = bitmap_size(log_meta->size);
236 : 3 : buf = malloc(bmsize);
237 [ + + ]: 3 : if (!buf) {
238 : 1 : fprintf(stderr, "Failed to allocate memory for bitmap buffer\n");
239 : : err = -ENOMEM;
240 : : goto error;
241 : : }
242 : :
243 : 2 : ret = fread(buf, bmsize, 1, f);
244 : :
245 [ + + ]: 2 : if (!ret) {
246 : 1 : fprintf(stderr, "Failed to read bitmap from file %s\n", name);
247 : : err = -EIO;
248 : : goto error;
249 : : }
250 : : else {
251 : : DPRINTF("Read %"PRIu64" bytes from bitmap region for file %s\n",
252 : : bmsize, name);
253 : : }
254 : :
255 : 1 : fwrite(buf, bmsize, 1, stdout);
256 : : }
257 : :
258 : : error:
259 [ + + ]: 10 : if(log_meta)
260 : 9 : free(log_meta);
261 [ + + ]: 10 : if(buf)
262 : 2 : free(buf);
263 [ + + ]: 10 : if(f)
264 : 8 : fclose(f);
265 : 10 : return err;
266 : :
267 : : usage:
268 : : printf("cbt-util get: Read field from log file\n\n");
269 : : printf("Options:\n");
270 : : printf(" -n name\tName of log file\n");
271 : : printf("[-p]\t\tPrint parent log file UUID\n");
272 : : printf("[-c]\t\tPrint child log file UUID\n");
273 : : printf("[-f]\t\tPrint consistency flag\n");
274 : : printf("[-s]\t\tPrint size of disk in bytes\n");
275 : : printf("[-b]\t\tPrint bitmap contents\n");
276 : : printf("[-h]\t\thelp\n");
277 : :
278 : : return -EINVAL;
279 : : }
280 : :
281 : :
282 : : int
283 : 14 : cbt_util_set(int argc, char **argv)
284 : : {
285 : : char *name, *parent, *child, *buf;
286 : 14 : int err, c, consistent = 0, flag = 0, ret;
287 : 14 : FILE *f = NULL;
288 : : uint64_t size, bmsize, old_bmsize;
289 : :
290 : 14 : err = 0;
291 : 14 : name = NULL;
292 : 14 : parent = NULL;
293 : 14 : child = NULL;
294 : 14 : buf = NULL;
295 : 14 : size = 0;
296 : 14 : bmsize = 0;
297 : 14 : old_bmsize = 0;
298 : :
299 [ + - ]: 14 : if (!argc || !argv)
300 : : goto usage;
301 : :
302 : : /* Make sure we start from the start of the args */
303 : 14 : optind = 1;
304 : :
305 [ + + ]: 39 : while ((c = getopt(argc, argv, "n:p:c:f:s:h")) != -1) {
306 [ + + + + : 26 : switch (c) {
+ + ]
307 : : case 'n':
308 : 13 : name = optarg;
309 : 13 : break;
310 : : case 'p':
311 : 4 : parent = optarg;
312 : 4 : break;
313 : : case 'c':
314 : 1 : child = optarg;
315 : 1 : break;
316 : : case 'f':
317 : 1 : flag = 1;
318 : 2 : consistent = atoi(optarg);
319 : 1 : break;
320 : : case 's':
321 : 6 : size = strtoull(optarg, NULL, 10);
322 : 25 : break;
323 : : case 'h':
324 : : default:
325 : : goto usage;
326 : : }
327 : : }
328 : :
329 [ + - ][ + + ]: 13 : if (!name || !(parent || child || flag || size))
[ + + ]
330 : : goto usage;
331 : :
332 : 12 : struct cbt_log_metadata *log_meta = malloc(sizeof(struct cbt_log_metadata));
333 [ + + ]: 12 : if (!log_meta) {
334 : 1 : fprintf(stderr, "Failed to allocate memory for CBT log metadata\n");
335 : 1 : err = -ENOMEM;
336 : 1 : goto error;
337 : : }
338 : :
339 : 11 : f = fopen(name, "r+");
340 [ + + ]: 11 : if (f == NULL) {
341 : 1 : fprintf(stderr, "Failed to open log file %s. %s\n",
342 : 1 : name, strerror(errno));
343 : 1 : err = -errno;
344 : 1 : goto error;
345 : : }
346 : :
347 : 10 : ret = fread(log_meta, sizeof(struct cbt_log_metadata), 1, f);
348 : :
349 [ + + ]: 10 : if (!ret) {
350 : 1 : fprintf(stderr, "Failed to read CBT metadata from file %s\n", name);
351 : 1 : err = -EIO;
352 : 1 : goto error;
353 : : }
354 : :
355 [ + + ]: 9 : if (parent) {
356 : 1 : uuid_parse(parent, log_meta->parent);
357 : : }
358 : :
359 [ + + ]: 9 : if (child) {
360 : 1 : uuid_parse(child, log_meta->child);
361 : : }
362 : :
363 [ + + ]: 9 : if (flag) {
364 : 1 : log_meta->consistent = consistent;
365 : : }
366 : :
367 [ + + ]: 9 : if (size) {
368 [ + + ]: 6 : if (size < log_meta->size) {
369 : 1 : fprintf(stderr, "Size smaller than current file size (%"PRIu64")\n",
370 : : log_meta->size);
371 : 1 : err = -EINVAL;
372 : 1 : goto error;
373 : : }
374 : :
375 : 5 : bmsize = bitmap_size(size);
376 : 10 : old_bmsize = bitmap_size(log_meta->size);
377 : 5 : buf = malloc(bmsize);
378 [ + + ]: 5 : if (!buf) {
379 : 1 : fprintf(stderr, "Failed to allocate memory for bitmap buffer\n");
380 : 1 : err = -ENOMEM;
381 : 1 : goto error;
382 : : }
383 : :
384 : 4 : ret = fread(buf, old_bmsize, 1, f);
385 [ + + ]: 4 : if (!ret) {
386 : 1 : fprintf(stderr, "Failed to read bitmap from file %s\n", name);
387 : 1 : err = -EIO;
388 : 1 : goto error;
389 : : }
390 : :
391 : 3 : memset(buf + old_bmsize, 0, bmsize - old_bmsize);
392 : : // Set file pointer to start of bitmap area
393 : 3 : ret = fseek(f, sizeof(struct cbt_log_metadata), SEEK_SET);
394 [ + + ]: 3 : if(ret < 0) {
395 : 1 : fprintf(stderr, "Failed to seek to start of bitmap in file %s. %s\n",
396 : 1 : name, strerror(errno));
397 : 1 : err = -errno;
398 : 1 : goto error;
399 : : }
400 : :
401 : 2 : ret = fwrite(buf, bmsize, 1, f);
402 [ + + ]: 2 : if (!ret) {
403 : 1 : fprintf(stderr, "Failed to write CBT bitmap to file %s\n", name);
404 : 1 : err = -EIO;
405 : : }
406 : :
407 : 2 : log_meta->size = size;
408 : : }
409 : :
410 : : // Rewind pointer to start of file and rewrite data
411 : 5 : ret = fseek(f, 0, SEEK_SET);
412 [ - + ]: 5 : if(ret < 0) {
413 : 0 : fprintf(stderr, "Failed to seek to start of file %s. %s\n",
414 : 0 : name, strerror(errno));
415 : 0 : err = -errno;
416 : 0 : goto error;
417 : : }
418 : :
419 : 5 : ret = fwrite(log_meta, sizeof(struct cbt_log_metadata), 1, f);
420 [ + + ]: 5 : if (!ret) {
421 : 1 : fprintf(stderr, "Failed to write CBT metadata to file %s\n", name);
422 : 1 : err = -EIO;
423 : : }
424 : :
425 : : error:
426 [ + + ]: 12 : if(buf)
427 : 4 : free(buf);
428 [ + + ]: 12 : if(log_meta)
429 : 11 : free(log_meta);
430 [ + + ]: 12 : if(f)
431 : 10 : fclose(f);
432 : 12 : return err;
433 : :
434 : : usage:
435 : : printf("cbt-util set: Set field in log file\n\n");
436 : : printf("Options:\n");
437 : : printf(" -n name\tName of log file\n");
438 : : printf("[-p parent]\tParent log file UUID\n");
439 : : printf("[-c child]\tChild log file UUID\n");
440 : : printf("[-f 0|1]\tConsistency flag\n");
441 : : printf("[-s size]\tSize of the disk in bytes\n");
442 : : printf("[-h]\t\thelp\n");
443 : :
444 : 2 : return -EINVAL;
445 : : }
446 : :
447 : : int
448 : 8 : cbt_util_create(int argc, char **argv)
449 : : {
450 : : char *name;
451 : : int err, c, ret;
452 : 8 : FILE *f = NULL;
453 : : uint64_t size, bitmap_sz;
454 : :
455 : 8 : err = 0;
456 : 8 : name = NULL;
457 : 8 : size = 0;
458 : :
459 [ + - ]: 8 : if (!argc || !argv)
460 : : goto usage;
461 : :
462 : : /* Make sure we start from the start of the args */
463 : 8 : optind = 1;
464 : :
465 [ + + ]: 22 : while ((c = getopt(argc, argv, "n:s:h")) != -1) {
466 [ + + - ]: 14 : switch (c) {
467 : : case 'n':
468 : 7 : name = optarg;
469 : 7 : break;
470 : : case 's':
471 : 7 : size = strtoull(optarg, NULL, 10);
472 : 14 : break;
473 : : case 'h':
474 : : default:
475 : : goto usage;
476 : : }
477 : : }
478 : :
479 [ + + ]: 8 : if (!name || !size)
480 : : goto usage;
481 : :
482 : : /* Initialise metadata */
483 : 6 : struct cbt_log_data *log_data = malloc(sizeof(struct cbt_log_data));
484 [ + + ]: 6 : if (!log_data) {
485 : : err = -ENOMEM;
486 : : goto error;
487 : : }
488 : :
489 : 5 : uuid_clear(log_data->metadata.parent);
490 : 5 : uuid_clear(log_data->metadata.child);
491 : 5 : log_data->metadata.consistent = 0;
492 : 5 : log_data->metadata.size = size;
493 : :
494 : : DPRINTF("Creating new log file %s of size %"PRIu64"\n", name, size);
495 : :
496 : 5 : bitmap_sz = bitmap_size(size);
497 : 5 : log_data->bitmap = (char*)malloc(bitmap_sz);
498 [ + + ]: 5 : if (!log_data->bitmap) {
499 : : err = -ENOMEM;
500 : : goto error;
501 : : }
502 : :
503 : 4 : memset(log_data->bitmap, 0, bitmap_sz);
504 : :
505 : 4 : f = fopen(name, "w+");
506 [ + + ]: 4 : if (f == NULL) {
507 : 1 : fprintf(stderr, "Failed to open log file %s. %s\n",
508 : 1 : name, strerror(errno));
509 : 1 : err = -errno;
510 : 1 : goto error;
511 : : }
512 : :
513 : 3 : ret = fwrite(&log_data->metadata, sizeof(struct cbt_log_metadata), 1, f);
514 [ + + ]: 3 : if (!ret) {
515 : 1 : fprintf(stderr, "Failed to write metadata to log file %s\n", name);
516 : 1 : err = -EIO;
517 : 1 : goto error;
518 : : }
519 : :
520 : 2 : ret = fwrite(log_data->bitmap, bitmap_sz, 1, f);
521 [ + + ]: 2 : if (!ret) {
522 : 1 : fprintf(stderr, "Failed to write bitmap to log file %s\n", name);
523 : 1 : err = -EIO;
524 : 1 : goto error;
525 : : }
526 : : else {
527 : : DPRINTF("Bitmap area of %"PRIu64" bytes initialised\n", bitmap_sz);
528 : : }
529 : :
530 : :
531 : : error:
532 [ + + ]: 6 : if(log_data) {
533 [ + + ]: 5 : if(log_data->bitmap) {
534 : 4 : free(log_data->bitmap);
535 : : }
536 : 5 : free(log_data);
537 : : }
538 [ + + ]: 6 : if(f)
539 : 3 : fclose(f);
540 : :
541 : 6 : return err;
542 : :
543 : : usage:
544 : : printf("cbt-util create: Create new CBT metadata log with default values\n\n");
545 : : printf("Options:\n\t-n Log file name\n\t-s Num blocks in bitmap\n"
546 : : "\t[-h help]\n");
547 : :
548 : 2 : return -EINVAL;
549 : : }
550 : :
551 : : int
552 : 16 : cbt_util_coalesce(int argc, char **argv)
553 : : {
554 : : char *parent, *child, *pbuf, *cbuf;
555 : : int err, c, ret;
556 : 16 : FILE *fparent = NULL, *fchild = NULL;;
557 : : struct cbt_log_data *parent_log, *child_log;
558 : : uint64_t size;
559 : :
560 : 16 : parent = NULL;
561 : 16 : child = NULL;
562 : 16 : parent_log = NULL;
563 : 16 : child_log = NULL;
564 : 16 : pbuf = NULL;
565 : 16 : cbuf = NULL;
566 : :
567 [ + - ]: 16 : if (!argc || !argv)
568 : : goto usage;
569 : :
570 : : /* Make sure we start from the start of the args */
571 : 16 : optind = 1;
572 : :
573 [ + + ]: 46 : while ((c = getopt(argc, argv, "p:c:h")) != -1) {
574 [ + + - ]: 30 : switch (c) {
575 : : case 'p':
576 : 15 : parent = optarg;
577 : 15 : break;
578 : : case 'c':
579 : 15 : child = optarg;
580 : 30 : break;
581 : : case 'h':
582 : : default:
583 : : goto usage;
584 : : }
585 : : }
586 : :
587 [ + + ]: 16 : if (!parent || !child)
588 : : goto usage;
589 : :
590 : : // Open parent log in r/o mode
591 : 14 : err = file_open(&fparent, parent, "r");
592 [ + + ]: 14 : if (err)
593 : : goto error;
594 : :
595 : 13 : err = malloc_cbt_log_data(&parent_log);
596 [ + + ]: 13 : if (err)
597 : : goto error;
598 : :
599 : : // Read parent metadata
600 : 12 : err = read_cbt_metadata(parent, fparent, &parent_log->metadata);
601 [ + + ]: 12 : if (err)
602 : : goto error;
603 : :
604 : : // Open child log in r/w mode
605 : 11 : err = file_open(&fchild, child, "r+");
606 [ + + ]: 11 : if (err)
607 : : goto error;
608 : :
609 : 10 : err = malloc_cbt_log_data(&child_log);
610 [ + + ]: 10 : if (err)
611 : : goto error;
612 : :
613 : : // Read child metadata
614 : 9 : err = read_cbt_metadata(child, fchild, &child_log->metadata);
615 [ + + ]: 9 : if (err)
616 : : goto error;
617 : :
618 : : // check parent size is <= child size
619 [ + + ]: 8 : if (bitmap_size(parent_log->metadata.size) >
620 : 8 : bitmap_size(child_log->metadata.size)) {
621 : 1 : fprintf(stderr, "Parent bitmap larger than child bitmap,"
622 : : "can't coalesce");
623 : : err = -EINVAL;
624 : : goto error;
625 : : }
626 : :
627 : : //allocate and read cbt bitmap for parent
628 : 7 : err = allocate_cbt_bitmap(parent_log);
629 [ + + ]: 7 : if (err)
630 : : goto error;
631 : :
632 : 6 : err = read_cbt_bitmap(fparent, parent_log);
633 [ + + ]: 6 : if (err)
634 : : goto error;
635 : :
636 : : //allocate and read cbt bitmap for child
637 : 5 : err = allocate_cbt_bitmap(child_log);
638 [ + + ]: 5 : if (err)
639 : : goto error;
640 : :
641 : 4 : err = read_cbt_bitmap(fchild, child_log);
642 [ + + ]: 4 : if (err)
643 : : goto error;
644 : :
645 : : // Coalesce up to size of parent bitmap
646 : 6 : size = bitmap_size(parent_log->metadata.size);
647 : 3 : pbuf = parent_log->bitmap;
648 : 3 : cbuf = child_log->bitmap;
649 : :
650 [ + + ]: 27 : while(size--){
651 : 24 : *cbuf++ |= *pbuf++;
652 : : }
653 : :
654 : : // Set file pointer to start of bitmap area
655 : 3 : ret = fseek(fchild, sizeof(struct cbt_log_metadata), SEEK_SET);
656 : :
657 [ + + ]: 3 : if(ret < 0) {
658 : 1 : fprintf(stderr, "Failed to seek to start of file %s. %s\n",
659 : 1 : child, strerror(errno));
660 : 1 : err = -errno;
661 : 1 : goto error;
662 : : }
663 : :
664 : 4 : size = bitmap_size(child_log->metadata.size);
665 : 2 : ret = fwrite(child_log->bitmap, size, 1, fchild);
666 [ + + ]: 2 : if (!ret) {
667 : 1 : fprintf(stderr, "Failed to write bitmap to log file %s\n", child);
668 : : err = -EIO;
669 : : goto error;
670 : : }
671 : :
672 : : error:
673 [ + + ]: 14 : if (parent_log) {
674 [ + + ]: 12 : if (parent_log->bitmap)
675 : 6 : free(parent_log->bitmap);
676 : 12 : free(parent_log);
677 : : }
678 [ + + ]: 14 : if (child_log) {
679 [ + + ]: 9 : if (child_log->bitmap)
680 : 4 : free(child_log->bitmap);
681 : 9 : free(child_log);
682 : : }
683 : :
684 [ + + ]: 14 : if (fparent)
685 : 13 : fclose(fparent);
686 [ + + ]: 14 : if (fchild)
687 : 10 : fclose(fchild);
688 : :
689 : 14 : return err;
690 : :
691 : : usage:
692 : : printf("cbt-util coalesce: Coalesce contents of parent bitmap on to child bitmap\n\n");
693 : : printf("Options:\n\t-p Parent log file name\n");
694 : : printf("\t-c Child log file name\n");
695 : : printf("\t[-h help]\n");
696 : :
697 : : return -EINVAL;
698 : :
699 : : }
700 : :
701 : : void
702 : 1 : help(void)
703 : : {
704 : : printf("usage: cbt-util COMMAND [OPTIONS]\n");
705 [ + + ]: 4 : print_commands();
706 : 1 : }
707 : :
708 : : struct command *
709 : 6 : get_command(char *command)
710 : : {
711 : : int i, n;
712 : :
713 [ + + ]: 6 : if (strnlen(command, 25) >= 25)
714 : : return NULL;
715 : :
716 : : n = sizeof(commands) / sizeof (struct command);
717 : :
718 [ + + ]: 15 : for (i = 0; i < n; i++)
719 [ + + ]: 14 : if (!strcmp(command, commands[i].name))
720 : 4 : return &commands[i];
721 : :
722 : : return NULL;
723 : : }
|