From patchwork Thu Apr 18 15:17:27 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 237675 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id C89E52C00FD for ; Fri, 19 Apr 2013 01:19:36 +1000 (EST) Received: from localhost ([::1]:50490 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1USqcX-0006rZ-G7 for incoming@patchwork.ozlabs.org; Thu, 18 Apr 2013 11:19:33 -0400 Received: from eggs.gnu.org ([208.118.235.92]:36015) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1USqav-0004cq-CV for qemu-devel@nongnu.org; Thu, 18 Apr 2013 11:17:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1USqas-0000v7-Ec for qemu-devel@nongnu.org; Thu, 18 Apr 2013 11:17:53 -0400 Received: from mail-qe0-f41.google.com ([209.85.128.41]:44292) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1USqas-0000us-Ae for qemu-devel@nongnu.org; Thu, 18 Apr 2013 11:17:50 -0400 Received: by mail-qe0-f41.google.com with SMTP id b10so1796610qen.0 for ; Thu, 18 Apr 2013 08:17:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:sender:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references; bh=TQkVQyaktUvikLlRkh5BnnnrovHWats5ruDdr+Chu9c=; b=DV3ZE7YwpwsKlmQgnTxaG4i9rPYc1+gVq6ak0n+Pu8zuo92YRkOwEn//5O/u/5Abf9 8TVvjxqg+IMBXAq2P4jealo7w30+O2xRAOMx223SCaYyPOm1thAQczo0qe+EaLn/05/X lNBsWsd2+8roK3TQnBA0KHQU/hou2zzdUR8IUTdZ2ac9R5/kHoRhNem97zx9aiIuBTNb v7CjZt2qsEsd3Aw3c4yLtcBI+H4Yt4vl5HJE43CsGIgoqJhU9+1M/AMgOexOSToFeKO3 mBBNKUOGUwxDpfutH9tfVPOsFJGvRdXcr6xbzWlk0K5T+MeHGuC3OzWHJ4Cs58B55dXr qc+A== X-Received: by 10.224.181.200 with SMTP id bz8mr10716223qab.68.1366298270039; Thu, 18 Apr 2013 08:17:50 -0700 (PDT) Received: from yakj.usersys.redhat.com (93-34-176-20.ip50.fastwebnet.it. [93.34.176.20]) by mx.google.com with ESMTPS id bv6sm12468970qab.5.2013.04.18.08.17.48 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Thu, 18 Apr 2013 08:17:49 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 18 Apr 2013 17:17:27 +0200 Message-Id: <1366298249-11739-4-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.2 In-Reply-To: <1366298249-11739-1-git-send-email-pbonzini@redhat.com> References: <1366298249-11739-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 209.85.128.41 Cc: kwolf@redhat.com, stefanha@redhat.com Subject: [Qemu-devel] [RFC PATCH 3/5] qcow2.py: add load_image() method X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The load_image() method optionally probes for the image format and returns an instance of a subclass of ImageFile. So far only qcow2 is supported. Signed-off-by: Paolo Bonzini --- tests/qemu-iotests/qcow2.py | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py index 773c947..77e03cb 100755 --- a/tests/qemu-iotests/qcow2.py +++ b/tests/qemu-iotests/qcow2.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import sys +import os import struct import string @@ -20,6 +21,10 @@ class ImageFile: self.__dict__ = fields self.fd = fd + def close(self): + self.fd.close() + self.fd = None + def raw_pread(self, offset, size): self.fd.seek(offset) return self.fd.read(size) @@ -28,6 +33,7 @@ class ImageFile: self.fd.seek(offset) return self.fd.write(data) + class Qcow(ImageFile): uint32_t = 'I' @@ -58,6 +64,7 @@ class Qcow(ImageFile): ]; HEADER_FMT = '>' + ''.join(field[0] for field in fields) + QCOW_MAGIC = 0x514649fb def __init__(self, fd): @@ -71,6 +78,9 @@ class Qcow(ImageFile): for i, field in enumerate(Qcow.fields)) ImageFile.__init__(self, fd, fields) + if self.magic != Qcow.QCOW_MAGIC: + raise Error('not a QCOW2 image') + self.set_defaults() self.cluster_size = 1 << self.cluster_bits @@ -155,31 +165,44 @@ class Qcow(ImageFile): print "%-25s %s" % ("data", data) print "" +def load_image(filename, mode='rb', format=None): + fd = open(filename, mode) + if format is None: + fd.seek(0) + buf = fd.read(4) + magic = struct.unpack('>I', buf) + if magic == Qcow.QCOW_MAGIC: + format = 'qcow2' + else: + format = 'raw' + + if format == 'qcow2': + return Qcow(fd) + + raise Error('unknown format %s' % format) + -def cmd_dump_header(fd): - h = Qcow(fd) +def cmd_dump_header(h): h.dump() h.dump_extensions() -def cmd_add_header_ext(fd, magic, data): +def cmd_add_header_ext(h, magic, data): try: magic = int(magic, 0) except: print "'%s' is not a valid magic number" % magic sys.exit(1) - h = Qcow(fd) h.extensions.append(QcowHeaderExtension.create(magic, data)) h.update() -def cmd_del_header_ext(fd, magic): +def cmd_del_header_ext(h, magic): try: magic = int(magic, 0) except: print "'%s' is not a valid magic number" % magic sys.exit(1) - h = Qcow(fd) found = False for ex in h.extensions: @@ -193,7 +216,7 @@ def cmd_del_header_ext(fd, magic): h.update() -def cmd_set_feature_bit(fd, group, bit): +def cmd_set_feature_bit(h, group, bit): try: bit = int(bit, 0) if bit < 0 or bit >= 64: @@ -202,7 +225,6 @@ def cmd_set_feature_bit(fd, group, bit): print "'%s' is not a valid bit number in range [0, 64)" % bit sys.exit(1) - h = Qcow(fd) if group == 'incompatible': h.incompatible_features |= 1 << bit elif group == 'compatible': @@ -223,7 +245,7 @@ cmds = [ ] def main(filename, cmd, args): - fd = open(filename, "r+b") + h = load_image(filename, 'r+b', 'qcow2') try: for name, handler, num_args, desc in cmds: if name != cmd: @@ -232,11 +254,11 @@ def main(filename, cmd, args): usage() return else: - handler(fd, *args) + handler(h, *args) return print "Unknown command '%s'" % cmd finally: - fd.close() + h.close() def usage(): print "Usage: %s [, ...]" % sys.argv[0]