static int vhd_print_bat_str(vhd_context_t *vhd) { int i, err, total_blocks, bitmap_size; char *bitmap; ssize_t n; err = 0; if (!vhd_type_dynamic(vhd)) return -EINVAL; total_blocks = vhd->footer.curr_size / vhd->header.block_size; bitmap_size = total_blocks >> 3; if (bitmap_size << 3 < total_blocks) bitmap_size++; bitmap = malloc(bitmap_size); if (!bitmap) return -ENOMEM; memset(bitmap, 0, bitmap_size); for (i = 0; i < total_blocks; i++) { if (vhd->bat.bat[i] != DD_BLK_UNUSED) set_bit(bitmap, i); } n = write(STDOUT_FILENO, bitmap, bitmap_size); if (n < 0) err = -errno; free(bitmap); return err; }
int get_footer(server *srv, chunkqueue *cq, vhd_state_t *state, off_t *curr_off) { int err; vhd_context_t *vhd = &state->vhd; err = fill(srv, cq, &vhd->footer, sizeof(vhd_footer_t), 0, curr_off); if (err) return err; if (*curr_off < 0 + sizeof(vhd_footer_t)) return 0; DEBUGLOG("s", "Footer all in"); vhd_footer_in(&vhd->footer); err = vhd_validate_footer(&vhd->footer); if (err) LOG("sd", "ERROR: VHD footer invalid:", err); if (!vhd_type_dynamic(vhd)) { LOG("s", "ERROR: static VHDs are not supported"); err = -EINVAL; } return err; }
static int vhd_print_headers(vhd_context_t *vhd, int hex) { int err; vhd_print_footer(&vhd->footer, hex); if (vhd_type_dynamic(vhd)) { vhd_print_header(vhd, &vhd->header, hex); if (vhd->footer.type == HD_TYPE_DIFF) vhd_print_parent_locators(vhd, hex); if (vhd_has_batmap(vhd)) { err = vhd_get_batmap(vhd); if (err) { printf("failed to get batmap header\n"); return err; } vhd_print_batmap_header(vhd, &vhd->batmap, hex); } } return 0; }
static int vhd_journal_add_footer(vhd_journal_t *j) { int err; off64_t off; vhd_context_t *vhd; vhd_footer_t footer; vhd = &j->vhd; err = vhd_seek(vhd, 0, SEEK_END); if (err) return err; off = vhd_position(vhd); if (off == (off64_t)-1) return -errno; err = vhd_read_footer_at(vhd, &footer, off - sizeof(vhd_footer_t)); if (err) return err; vhd_footer_out(&footer); err = vhd_journal_update(j, off - sizeof(vhd_footer_t), (char *)&footer, sizeof(vhd_footer_t), VHD_JOURNAL_ENTRY_TYPE_FOOTER_P); if (err) return err; if (!vhd_type_dynamic(vhd)) return 0; err = vhd_read_footer_at(vhd, &footer, 0); if (err) return err; vhd_footer_out(&footer); err = vhd_journal_update(j, 0, (char *)&footer, sizeof(vhd_footer_t), VHD_JOURNAL_ENTRY_TYPE_FOOTER_C); return err; }
static int vhd_journal_add_metadata(vhd_journal_t *j) { int err; off_t eof; vhd_context_t *vhd; vhd = &j->vhd; err = vhd_journal_add_footer(j); if (err) return err; if (!vhd_type_dynamic(vhd)) return 0; err = vhd_journal_add_header(j); if (err) return err; err = vhd_journal_add_locators(j); if (err) return err; err = vhd_journal_add_bat(j); if (err) return err; if (vhd_has_batmap(vhd)) { err = vhd_journal_add_batmap(j); if (err) return err; } j->header.journal_data_offset = j->header.journal_eof; return vhd_journal_write_header(j, &j->header); }
static int vhd_journal_restore_metadata(vhd_journal_t *j) { off64_t off; char **locators; vhd_footer_t copy; vhd_context_t *vhd; int i, locs, hlocs, err; vhd = &j->vhd; locs = 0; hlocs = 0; locators = NULL; err = vhd_journal_seek(j, sizeof(vhd_journal_header_t), SEEK_SET); if (err) return err; err = vhd_journal_read_footer(j, &vhd->footer); if (err) return err; if (!vhd_type_dynamic(vhd)) goto restore; err = vhd_journal_read_footer_copy(j, ©); if (err) return err; err = vhd_journal_read_header(j, &vhd->header); if (err) return err; for (hlocs = 0, i = 0; i < vhd_parent_locator_count(vhd); i++) { if (vhd_validate_platform_code(vhd->header.loc[i].code)) return err; if (vhd->header.loc[i].code != PLAT_CODE_NONE) hlocs++; } if (hlocs) { err = vhd_journal_read_locators(j, &locators, &locs); if (err) return err; if (hlocs != locs) { err = -EINVAL; goto out; } } err = vhd_journal_read_bat(j, &vhd->bat); if (err) goto out; if (vhd_has_batmap(vhd)) { err = vhd_journal_read_batmap(j, &vhd->batmap); if (err) goto out; } restore: off = vhd_journal_position(j); if (off == (off64_t)-1) return -errno; if (j->header.journal_data_offset != off) return -EINVAL; err = vhd_journal_restore_footer(j, &vhd->footer); if (err) goto out; if (!vhd_type_dynamic(vhd)) goto out; err = vhd_journal_restore_footer_copy(j, ©); if (err) goto out; err = vhd_journal_restore_header(j, &vhd->header); if (err) goto out; if (locs) { err = vhd_journal_restore_locators(j, locators, locs); if (err) goto out; } err = vhd_journal_restore_bat(j, &vhd->bat); if (err) goto out; if (vhd_has_batmap(vhd)) { err = vhd_journal_restore_batmap(j, &vhd->batmap); if (err) goto out; } err = 0; out: if (locators) { for (i = 0; i < locs; i++) free(locators[i]); free(locators); } if (!err && !vhd->is_block) err = ftruncate(vhd->fd, j->header.vhd_footer_offset + sizeof(vhd_footer_t)); return err; }
int vhd_journal_add_block(vhd_journal_t *j, uint32_t block, char mode) { int err; char *buf; off64_t off; size_t size; uint64_t blk; vhd_context_t *vhd; buf = NULL; vhd = &j->vhd; if (!vhd_type_dynamic(vhd)) return -EINVAL; err = vhd_get_bat(vhd); if (err) return err; if (block >= vhd->bat.entries) return -ERANGE; blk = vhd->bat.bat[block]; if (blk == DD_BLK_UNUSED) return 0; off = vhd_sectors_to_bytes(blk); if (mode & VHD_JOURNAL_METADATA) { size = vhd_sectors_to_bytes(vhd->bm_secs); err = vhd_read_bitmap(vhd, block, &buf); if (err) return err; err = vhd_journal_update(j, off, buf, size, VHD_JOURNAL_ENTRY_TYPE_DATA); free(buf); if (err) return err; } if (mode & VHD_JOURNAL_DATA) { off += vhd_sectors_to_bytes(vhd->bm_secs); size = vhd_sectors_to_bytes(vhd->spb); err = vhd_read_block(vhd, block, &buf); if (err) return err; err = vhd_journal_update(j, off, buf, size, VHD_JOURNAL_ENTRY_TYPE_DATA); free(buf); if (err) return err; } return vhd_journal_sync(j); }
int vhd_util_set_field(int argc, char **argv) { long value; int err, c; vhd_context_t vhd; char *name, *field; err = -EINVAL; value = 0; name = NULL; field = NULL; if (!argc || !argv) goto usage; optind = 0; while ((c = getopt(argc, argv, "n:f:v:h")) != -1) { switch (c) { case 'n': name = optarg; break; case 'f': field = optarg; break; case 'v': err = 0; value = strtol(optarg, NULL, 10); break; case 'h': default: goto usage; } } if (!name || !field || optind != argc || err) goto usage; if (strnlen(field, 25) >= 25) { printf("invalid field\n"); goto usage; } if (strcmp(field, "hidden") && strcmp(field, "marker")) { printf("invalid field %s\n", field); goto usage; } if (value < 0 || value > 255) { printf("invalid value %ld\n", value); goto usage; } err = vhd_open(&vhd, name, VHD_OPEN_RDWR); if (err) { printf("error opening %s: %d\n", name, err); return err; } if (!strcmp(field, "hidden")) { vhd.footer.hidden = (char)value; err = vhd_write_footer(&vhd, &vhd.footer); if (err == -ENOSPC && vhd_type_dynamic(&vhd) && value) /* if no space to write the primary footer, at least write the * backup footer so that it's possible to delete the VDI */ err = vhd_write_footer_at(&vhd, &vhd.footer, 0); } else { err = vhd_set_marker(&vhd, (char)value); } vhd_close(&vhd); return err; usage: printf("options: <-n name> <-f field> <-v value> [-h help]\n"); return -EINVAL; }