From patchwork Thu Apr 18 15:17:26 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 237674 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 B08392C0134 for ; Fri, 19 Apr 2013 01:18:25 +1000 (EST) Received: from localhost ([::1]:46666 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1USqbN-0004gW-BO for incoming@patchwork.ozlabs.org; Thu, 18 Apr 2013 11:18:21 -0400 Received: from eggs.gnu.org ([208.118.235.92]:35986) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1USqas-0004YZ-8W for qemu-devel@nongnu.org; Thu, 18 Apr 2013 11:17:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1USqaq-0000u0-Ek for qemu-devel@nongnu.org; Thu, 18 Apr 2013 11:17:50 -0400 Received: from mail-qc0-x22e.google.com ([2607:f8b0:400d:c01::22e]:36683) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1USqaq-0000tv-9q for qemu-devel@nongnu.org; Thu, 18 Apr 2013 11:17:48 -0400 Received: by mail-qc0-f174.google.com with SMTP id z24so1393238qcq.5 for ; Thu, 18 Apr 2013 08:17:48 -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=H5bKM2jvUhAbTW5RyRIREYr1pZ+ySCNp0D5TyjK+F0k=; b=0+If1zlH+aKjDWhU8QKGWwO/DYJTuvxsOyhs8kTA6KMnDZAFNnYIIMD01opO1CFRPc m6nWMTw2KdaduDNMPhvXepe3eQ//aXXB/83hUiPb8p+redMYMwxll9BjqF6mhxpIvHxi GcCVXh3kVvEhePDxN15TsL1dB1qV5cQojzbyOJnoJvZyPHw1yGfpGrPT2YddSzKkX/qR ChKW1Uqd0r9zjD9WWeweaH7qwcAhgcaiYo0zVjMvdkWLv/yhprtB1xaQKidxq/TNcCs2 oWPlAdBsnWyIHMsVu0k1DqoqNy1C3HZDCA1jE7YqEpp7uxL8h3B6BMPAGbpFpyYqT83l /p4w== X-Received: by 10.224.73.7 with SMTP id o7mr10743774qaj.58.1366298267952; Thu, 18 Apr 2013 08:17:47 -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.45 (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Thu, 18 Apr 2013 08:17:47 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 18 Apr 2013 17:17:26 +0200 Message-Id: <1366298249-11739-3-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: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:400d:c01::22e Cc: kwolf@redhat.com, stefanha@redhat.com Subject: [Qemu-devel] [RFC PATCH 2/5] qcow2.py: add ImageFile superclass 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 Signed-off-by: Paolo Bonzini --- tests/qemu-iotests/qcow2.py | 60 +++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py index 40241b1..773c947 100755 --- a/tests/qemu-iotests/qcow2.py +++ b/tests/qemu-iotests/qcow2.py @@ -15,7 +15,20 @@ class QcowHeaderExtension: def create(cls, magic, data): return QcowHeaderExtension(magic, len(data), data) -class Qcow: +class ImageFile: + def __init__(self, fd, fields): + self.__dict__ = fields + self.fd = fd + + def raw_pread(self, offset, size): + self.fd.seek(offset) + return self.fd.read(size) + + def raw_pwrite(self, offset, data): + self.fd.seek(offset) + return self.fd.write(data) + +class Qcow(ImageFile): uint32_t = 'I' uint64_t = 'Q' @@ -54,18 +67,19 @@ class Qcow: buf = fd.read(buf_size) header = struct.unpack(Qcow.HEADER_FMT, buf) - self.__dict__ = dict((field[2], header[i]) + fields = dict((field[2], header[i]) for i, field in enumerate(Qcow.fields)) + ImageFile.__init__(self, fd, fields) self.set_defaults() self.cluster_size = 1 << self.cluster_bits fd.seek(self.header_length) - self.load_extensions(fd) + self.load_extensions() if self.backing_file_offset: - fd.seek(self.backing_file_offset) - self.backing_file = fd.read(self.backing_file_size) + self.backing_file = self.raw_pread(self.backing_file_offset, + self.backing_file_size) else: self.backing_file = None @@ -77,7 +91,7 @@ class Qcow: self.refcount_order = 4 self.header_length = 72 - def load_extensions(self, fd): + def load_extensions(self): self.extensions = [] if self.backing_file_offset != 0: @@ -85,43 +99,41 @@ class Qcow: else: end = self.cluster_size - while fd.tell() < end: - (magic, length) = struct.unpack('>II', fd.read(8)) + while self.fd.tell() < end: + (magic, length) = struct.unpack('>II', self.fd.read(8)) if magic == 0: break else: padded = (length + 7) & ~7 - data = fd.read(padded) + data = self.fd.read(padded) self.extensions.append(QcowHeaderExtension(magic, length, data)) - def update_extensions(self, fd): + def update_extensions(self): - fd.seek(self.header_length) + self.fd.seek(self.header_length) extensions = self.extensions extensions.append(QcowHeaderExtension(0, 0, "")) for ex in extensions: buf = struct.pack('>II', ex.magic, ex.length) - fd.write(buf) - fd.write(ex.data) + self.fd.write(buf) + self.fd.write(ex.data) if self.backing_file != None: - self.backing_file_offset = fd.tell() - fd.write(self.backing_file) + self.backing_file_offset = self.fd.tell() + self.fd.write(self.backing_file) - if fd.tell() > self.cluster_size: + if self.fd.tell() > self.cluster_size: raise Exception("I think I just broke the image...") - - def update(self, fd): + def update(self): header_bytes = self.header_length - self.update_extensions(fd) + self.update_extensions() - fd.seek(0) header = tuple(self.__dict__[f] for t, p, f in Qcow.fields) buf = struct.pack(Qcow.HEADER_FMT, *header) buf = buf[0:header_bytes-1] - fd.write(buf) + self.raw_pwrite(0, buf) def dump(self): for f in Qcow.fields: @@ -158,7 +170,7 @@ def cmd_add_header_ext(fd, magic, data): h = Qcow(fd) h.extensions.append(QcowHeaderExtension.create(magic, data)) - h.update(fd) + h.update() def cmd_del_header_ext(fd, magic): try: @@ -179,7 +191,7 @@ def cmd_del_header_ext(fd, magic): print "No such header extension" return - h.update(fd) + h.update() def cmd_set_feature_bit(fd, group, bit): try: @@ -201,7 +213,7 @@ def cmd_set_feature_bit(fd, group, bit): print "'%s' is not a valid group, try 'incompatible', 'compatible', or 'autoclear'" % group sys.exit(1) - h.update(fd) + h.update() cmds = [ [ 'dump-header', cmd_dump_header, 0, 'Dump image header and header extensions' ],