From: Kevin Wolf <kwolf@redhat.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com
Subject: [Qemu-devel] [PULL 20/42] block/dmg: properly detect the UDIF trailer
Date: Fri, 6 Feb 2015 17:40:27 +0100 [thread overview]
Message-ID: <1423240849-15499-21-git-send-email-kwolf@redhat.com> (raw)
In-Reply-To: <1423240849-15499-1-git-send-email-kwolf@redhat.com>
From: Peter Wu <peter@lekensteyn.nl>
DMG files have a variable length with a UDIF trailer at the end of a
file. This UDIF trailer is essential as it describes the contents of
the image. At the moment however, the start of this trailer is almost
always incorrect as bdrv_getlength() returns a multiple of the block
size (rounded up). This results in a failure to recognize DMG files,
resulting in Invalid argument (EINVAL) errors.
As there is no API to retrieve the real file size, look for the magic
header in the last two sectors to find the start of this 512-byte UDIF
trailer (the "koly" block).
The resource fork offset ("info_begin") has its offset adjusted as the
initial value of offset does not mean "end of file" anymore, but "begin
of UDIF trailer".
[Replaced error_set(errp, ERROR_CLASS_GENERIC_ERROR, ...) with
error_setg(errp, ...) as discussed with Peter.
--Stefan]
Signed-off-by: Peter Wu <peter@lekensteyn.nl>
Reviewed-by: John Snow <jsnow@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: 1420566495-13284-2-git-send-email-peter@lekensteyn.nl
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
block/dmg.c | 47 +++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 43 insertions(+), 4 deletions(-)
diff --git a/block/dmg.c b/block/dmg.c
index e455886..cdad28f 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -131,6 +131,46 @@ static void update_max_chunk_size(BDRVDMGState *s, uint32_t chunk,
}
}
+static int64_t dmg_find_koly_offset(BlockDriverState *file_bs, Error **errp)
+{
+ int64_t length;
+ int64_t offset = 0;
+ uint8_t buffer[515];
+ int i, ret;
+
+ /* bdrv_getlength returns a multiple of block size (512), rounded up. Since
+ * dmg images can have odd sizes, try to look for the "koly" magic which
+ * marks the begin of the UDIF trailer (512 bytes). This magic can be found
+ * in the last 511 bytes of the second-last sector or the first 4 bytes of
+ * the last sector (search space: 515 bytes) */
+ length = bdrv_getlength(file_bs);
+ if (length < 0) {
+ error_setg_errno(errp, -length,
+ "Failed to get file size while reading UDIF trailer");
+ return length;
+ } else if (length < 512) {
+ error_setg(errp, "dmg file must be at least 512 bytes long");
+ return -EINVAL;
+ }
+ if (length > 511 + 512) {
+ offset = length - 511 - 512;
+ }
+ length = length < 515 ? length : 515;
+ ret = bdrv_pread(file_bs, offset, buffer, length);
+ if (ret < 0) {
+ error_setg_errno(errp, -ret, "Failed while reading UDIF trailer");
+ return ret;
+ }
+ for (i = 0; i < length - 3; i++) {
+ if (buffer[i] == 'k' && buffer[i+1] == 'o' &&
+ buffer[i+2] == 'l' && buffer[i+3] == 'y') {
+ return offset + i;
+ }
+ }
+ error_setg(errp, "Could not locate UDIF trailer in dmg file");
+ return -EINVAL;
+}
+
static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
Error **errp)
{
@@ -145,15 +185,14 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
s->n_chunks = 0;
s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
- /* read offset of info blocks */
- offset = bdrv_getlength(bs->file);
+ /* locate the UDIF trailer */
+ offset = dmg_find_koly_offset(bs->file, errp);
if (offset < 0) {
ret = offset;
goto fail;
}
- offset -= 0x1d8;
- ret = read_uint64(bs, offset, &info_begin);
+ ret = read_uint64(bs, offset + 0x28, &info_begin);
if (ret < 0) {
goto fail;
} else if (info_begin == 0) {
--
1.8.3.1
next prev parent reply other threads:[~2015-02-06 16:41 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-06 16:40 [Qemu-devel] [PULL 00/42] Block patches Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 01/42] Restore atapi_dma flag across migration Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 02/42] atapi migration: Throw recoverable error to avoid recovery Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 03/42] block/raw-posix: create translate_err helper to merge errno values Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 04/42] block/raw-posix: create do_fallocate helper Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 05/42] block/raw-posix: refactor handle_aiocb_write_zeroes a bit Kevin Wolf
2015-02-12 2:29 ` Peter Maydell
2015-02-12 4:44 ` Denis V. Lunev
2015-02-06 16:40 ` [Qemu-devel] [PULL 06/42] block: use fallocate(FALLOC_FL_ZERO_RANGE) in handle_aiocb_write_zeroes Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 07/42] block/raw-posix: call plain fallocate " Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 08/42] block: use fallocate(FALLOC_FL_PUNCH_HOLE) & fallocate(0) to write zeroes Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 09/42] block: change default for discard and write zeroes to INT_MAX Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 10/42] qemu-img: Add QEMU_PKGVERSION to QEMU_IMG_VERSION Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 11/42] qed: Really remove unused field QEDAIOCB.finished Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 12/42] block: add accounting for merged requests Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 13/42] hw/virtio-blk: add a constant for max number of " Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 14/42] block-backend: expose bs->bl.max_transfer_length Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 15/42] virtio-blk: introduce multiread Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 16/42] virtio-blk: add a knob to disable request merging Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 17/42] qemu-iotests: Fix supported_oses check Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 18/42] iotests: Specify format for qemu-nbd Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 19/42] block: add event when disk usage exceeds threshold Kevin Wolf
2015-02-06 16:40 ` Kevin Wolf [this message]
2015-02-06 16:40 ` [Qemu-devel] [PULL 21/42] block/dmg: extract mish block decoding functionality Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 22/42] block/dmg: extract processing of resource forks Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 23/42] block/dmg: process a buffer instead of reading ints Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 24/42] block/dmg: validate chunk size to avoid overflow Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 25/42] block/dmg: process XML plists Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 26/42] block/dmg: set virtual size to a non-zero value Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 27/42] block/dmg: fix sector data offset calculation Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 28/42] block/dmg: use SectorNumber from BLKX header Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 29/42] block/dmg: factor out block type check Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 30/42] block/dmg: support bzip2 block entry types Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 31/42] block/dmg: improve zeroes handling Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 32/42] qed: check for header size overflow Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 33/42] qemu-iotests: add 116 invalid QED input file tests Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 34/42] block: fix off-by-one error in qcow and qcow2 Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 35/42] iotests: Fix 083 Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 36/42] iotests: Fix 100 for nbd Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 37/42] iotests: Fix 104 for NBD Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 38/42] nbd: Improve error messages Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 39/42] block: introduce BDRV_REQUEST_MAX_SECTORS Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 40/42] nbd: fix max_discard/max_transfer_length Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 41/42] block: Give always priority to unused entries in the qcow2 L2 cache Kevin Wolf
2015-02-06 16:40 ` [Qemu-devel] [PULL 42/42] qcow2: Rewrite qcow2_alloc_bytes() Kevin Wolf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1423240849-15499-21-git-send-email-kwolf@redhat.com \
--to=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).