]> Git Repo - qemu.git/blob - tests/qemu-iotests/qcow2.py
e968869ea6b234e45ed733244d1900b1f32c43e9
[qemu.git] / tests / qemu-iotests / qcow2.py
1 #!/usr/bin/env python3
2 #
3 # Manipulations with qcow2 image
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #
18
19 import sys
20
21 from qcow2_format import (
22     QcowHeader,
23     QcowHeaderExtension
24 )
25
26
27 def cmd_dump_header(fd):
28     h = QcowHeader(fd)
29     h.dump()
30     h.dump_extensions()
31
32
33 def cmd_dump_header_exts(fd):
34     h = QcowHeader(fd)
35     h.dump_extensions()
36
37
38 def cmd_set_header(fd, name, value):
39     try:
40         value = int(value, 0)
41     except ValueError:
42         print("'%s' is not a valid number" % value)
43         sys.exit(1)
44
45     fields = (field[2] for field in QcowHeader.fields)
46     if name not in fields:
47         print("'%s' is not a known header field" % name)
48         sys.exit(1)
49
50     h = QcowHeader(fd)
51     h.__dict__[name] = value
52     h.update(fd)
53
54
55 def cmd_add_header_ext(fd, magic, data):
56     try:
57         magic = int(magic, 0)
58     except ValueError:
59         print("'%s' is not a valid magic number" % magic)
60         sys.exit(1)
61
62     h = QcowHeader(fd)
63     h.extensions.append(QcowHeaderExtension.create(magic,
64                                                    data.encode('ascii')))
65     h.update(fd)
66
67
68 def cmd_add_header_ext_stdio(fd, magic):
69     data = sys.stdin.read()
70     cmd_add_header_ext(fd, magic, data)
71
72
73 def cmd_del_header_ext(fd, magic):
74     try:
75         magic = int(magic, 0)
76     except ValueError:
77         print("'%s' is not a valid magic number" % magic)
78         sys.exit(1)
79
80     h = QcowHeader(fd)
81     found = False
82
83     for ex in h.extensions:
84         if ex.magic == magic:
85             found = True
86             h.extensions.remove(ex)
87
88     if not found:
89         print("No such header extension")
90         return
91
92     h.update(fd)
93
94
95 def cmd_set_feature_bit(fd, group, bit):
96     try:
97         bit = int(bit, 0)
98         if bit < 0 or bit >= 64:
99             raise ValueError
100     except ValueError:
101         print("'%s' is not a valid bit number in range [0, 64)" % bit)
102         sys.exit(1)
103
104     h = QcowHeader(fd)
105     if group == 'incompatible':
106         h.incompatible_features |= 1 << bit
107     elif group == 'compatible':
108         h.compatible_features |= 1 << bit
109     elif group == 'autoclear':
110         h.autoclear_features |= 1 << bit
111     else:
112         print("'%s' is not a valid group, try "
113               "'incompatible', 'compatible', or 'autoclear'" % group)
114         sys.exit(1)
115
116     h.update(fd)
117
118
119 cmds = [
120     ['dump-header', cmd_dump_header, 0,
121      'Dump image header and header extensions'],
122     ['dump-header-exts', cmd_dump_header_exts, 0,
123      'Dump image header extensions'],
124     ['set-header', cmd_set_header, 2, 'Set a field in the header'],
125     ['add-header-ext', cmd_add_header_ext, 2, 'Add a header extension'],
126     ['add-header-ext-stdio', cmd_add_header_ext_stdio, 1,
127      'Add a header extension, data from stdin'],
128     ['del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension'],
129     ['set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
130 ]
131
132
133 def main(filename, cmd, args):
134     fd = open(filename, "r+b")
135     try:
136         for name, handler, num_args, desc in cmds:
137             if name != cmd:
138                 continue
139             elif len(args) != num_args:
140                 usage()
141                 return
142             else:
143                 handler(fd, *args)
144                 return
145         print("Unknown command '%s'" % cmd)
146     finally:
147         fd.close()
148
149
150 def usage():
151     print("Usage: %s <file> <cmd> [<arg>, ...]" % sys.argv[0])
152     print("")
153     print("Supported commands:")
154     for name, handler, num_args, desc in cmds:
155         print("    %-20s - %s" % (name, desc))
156
157
158 if __name__ == '__main__':
159     if len(sys.argv) < 3:
160         usage()
161         sys.exit(1)
162
163     main(sys.argv[1], sys.argv[2], sys.argv[3:])
This page took 0.023075 seconds and 2 git commands to generate.