Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 55 additions & 15 deletions vhd/lib/libvhd.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,8 @@ vhd_checksum_footer(vhd_footer_t *footer)
return ~checksum;
}

int
vhd_validate_footer(vhd_footer_t *footer)
static int
vhd_validate_footer_impl(vhd_footer_t *footer, bool suppress_invalid_footer_warning)
{
int csize;
uint32_t checksum;
Expand All @@ -244,7 +244,8 @@ vhd_validate_footer(vhd_footer_t *footer)
char buf[9];
memcpy(buf, footer->cookie, 8);
buf[8]= '\0';
VHDLOG("invalid footer cookie: %s\n", buf);
if (!suppress_invalid_footer_warning)
VHDLOG("invalid footer cookie: %s\n", buf);
return -EINVAL;
}

Expand All @@ -267,15 +268,24 @@ vhd_validate_footer(vhd_footer_t *footer)
return 0;
}

VHDLOG("invalid footer checksum: "
"footer = 0x%08x, calculated = 0x%08x\n",
footer->checksum, checksum);
if (!suppress_invalid_footer_warning)
{
VHDLOG("invalid footer checksum: "
"footer = 0x%08x, calculated = 0x%08x\n",
footer->checksum, checksum);
}
return -EINVAL;
}

return 0;
}

int
vhd_validate_footer(vhd_footer_t *footer)
{
return vhd_validate_footer_impl(footer, false);
}

uint32_t
vhd_checksum_header(vhd_header_t *header)
{
Expand Down Expand Up @@ -841,8 +851,8 @@ vhd_put_batmap(vhd_context_t *ctx)
/*
* look for 511 byte footer at end of file
*/
int
vhd_read_short_footer(vhd_context_t *ctx, vhd_footer_t *footer)
static int
vhd_read_short_footer_impl(vhd_context_t *ctx, vhd_footer_t *footer, bool suppress_invalid_footer_warning)
{
off64_t eof;
void *buf;
Expand All @@ -860,6 +870,19 @@ vhd_read_short_footer(vhd_context_t *ctx, vhd_footer_t *footer)
goto out;
}

if (((eof - 511) % VHD_SECTOR_SIZE) != 0) {
/*
* The VHD file with short footer should have the size in the form 512 * n + 511,
* also vhd_read on block VHDs won't succeed if trying to read from a position
* that is not a multiple of 512.
*/
if (!suppress_invalid_footer_warning)
VHDLOG("%s: failed reading short footer: file size does not meet requirement",
ctx->file);
err = -EINVAL;
goto out;
}

err = vhd_seek(ctx, eof - 511, SEEK_SET);
if (err)
goto out;
Expand All @@ -881,18 +904,24 @@ vhd_read_short_footer(vhd_context_t *ctx, vhd_footer_t *footer)
memcpy(footer, buf, sizeof(vhd_footer_t));

vhd_footer_in(footer);
err = vhd_validate_footer(footer);
err = vhd_validate_footer_impl(footer, suppress_invalid_footer_warning);

out:
if (err)
if (err && !suppress_invalid_footer_warning)
VHDLOG("%s: failed reading short footer: %d\n",
ctx->file, err);
free(buf);
return err;
}

int
vhd_read_footer_at(vhd_context_t *ctx, vhd_footer_t *footer, off64_t off)
vhd_read_short_footer(vhd_context_t *ctx, vhd_footer_t *footer)
{
return vhd_read_short_footer_impl(ctx, footer, false);
}

static int
vhd_read_footer_at_impl(vhd_context_t *ctx, vhd_footer_t *footer, off64_t off, bool suppress_invalid_footer_warning)
{
void *buf;
int err;
Expand All @@ -917,16 +946,22 @@ vhd_read_footer_at(vhd_context_t *ctx, vhd_footer_t *footer, off64_t off)
memcpy(footer, buf, sizeof(vhd_footer_t));

vhd_footer_in(footer);
err = vhd_validate_footer(footer);
err = vhd_validate_footer_impl(footer, suppress_invalid_footer_warning);

out:
if (err)
if (err && !suppress_invalid_footer_warning)
VHDLOG("%s: reading footer at 0x%08"PRIx64" failed: %d\n",
ctx->file, off, err);
free(buf);
return err;
}

int
vhd_read_footer_at(vhd_context_t *ctx, vhd_footer_t *footer, off64_t off)
{
return vhd_read_footer_at_impl(ctx, footer, off, false);
}

int
vhd_read_footer(vhd_context_t *ctx, vhd_footer_t *footer, bool use_bkp_footer)
{
Expand All @@ -942,11 +977,16 @@ vhd_read_footer(vhd_context_t *ctx, vhd_footer_t *footer, bool use_bkp_footer)
return -errno;

if (!use_bkp_footer) {
err = vhd_read_footer_at(ctx, footer, off - 512);
/*
* As we will read the backup footer if the primary one is invalid,
* stop complaining the primary one is invalid
*/

err = vhd_read_footer_at_impl(ctx, footer, off - 512, true);
if (err != -EINVAL)
return err;

err = vhd_read_short_footer(ctx, footer);
err = vhd_read_short_footer_impl(ctx, footer, true);
if (err != -EINVAL)
return err;
}
Expand Down