123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- #!/usr/bin/env python3
- #
- # Manipulations with qcow2 image
- #
- # Copyright (C) 2012 Red Hat, Inc.
- #
- # This program is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 2 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- #
- import sys
- from qcow2_format import (
- QcowHeader,
- QcowHeaderExtension
- )
- is_json = False
- def cmd_dump_header(fd):
- h = QcowHeader(fd)
- h.dump(is_json)
- print()
- h.dump_extensions(is_json)
- def cmd_dump_header_exts(fd):
- h = QcowHeader(fd)
- h.dump_extensions(is_json)
- def cmd_set_header(fd, name, value):
- try:
- value = int(value, 0)
- except ValueError:
- print("'%s' is not a valid number" % value)
- sys.exit(1)
- fields = (field[2] for field in QcowHeader.fields)
- if name not in fields:
- print("'%s' is not a known header field" % name)
- sys.exit(1)
- h = QcowHeader(fd)
- h.__dict__[name] = value
- h.update(fd)
- def cmd_add_header_ext(fd, magic, data):
- try:
- magic = int(magic, 0)
- except ValueError:
- print("'%s' is not a valid magic number" % magic)
- sys.exit(1)
- h = QcowHeader(fd)
- h.extensions.append(QcowHeaderExtension.create(magic,
- data.encode('ascii')))
- h.update(fd)
- def cmd_add_header_ext_stdio(fd, magic):
- data = sys.stdin.read()
- cmd_add_header_ext(fd, magic, data)
- def cmd_del_header_ext(fd, magic):
- try:
- magic = int(magic, 0)
- except ValueError:
- print("'%s' is not a valid magic number" % magic)
- sys.exit(1)
- h = QcowHeader(fd)
- found = False
- for ex in h.extensions:
- if ex.magic == magic:
- found = True
- h.extensions.remove(ex)
- if not found:
- print("No such header extension")
- return
- h.update(fd)
- def cmd_set_feature_bit(fd, group, bit):
- try:
- bit = int(bit, 0)
- if bit < 0 or bit >= 64:
- raise ValueError
- except ValueError:
- print("'%s' is not a valid bit number in range [0, 64)" % bit)
- sys.exit(1)
- h = QcowHeader(fd)
- if group == 'incompatible':
- h.incompatible_features |= 1 << bit
- elif group == 'compatible':
- h.compatible_features |= 1 << bit
- elif group == 'autoclear':
- h.autoclear_features |= 1 << bit
- else:
- print("'%s' is not a valid group, try "
- "'incompatible', 'compatible', or 'autoclear'" % group)
- sys.exit(1)
- h.update(fd)
- cmds = [
- ['dump-header', cmd_dump_header, 0,
- 'Dump image header and header extensions'],
- ['dump-header-exts', cmd_dump_header_exts, 0,
- 'Dump image header extensions'],
- ['set-header', cmd_set_header, 2, 'Set a field in the header'],
- ['add-header-ext', cmd_add_header_ext, 2, 'Add a header extension'],
- ['add-header-ext-stdio', cmd_add_header_ext_stdio, 1,
- 'Add a header extension, data from stdin'],
- ['del-header-ext', cmd_del_header_ext, 1, 'Delete a header extension'],
- ['set-feature-bit', cmd_set_feature_bit, 2, 'Set a feature bit'],
- ]
- def main(filename, cmd, args):
- fd = open(filename, "r+b")
- try:
- for name, handler, num_args, desc in cmds:
- if name != cmd:
- continue
- elif len(args) != num_args:
- usage()
- return
- else:
- handler(fd, *args)
- return
- print("Unknown command '%s'" % cmd)
- finally:
- fd.close()
- def usage():
- print("Usage: %s <file> <cmd> [<arg>, ...] [<key>, ...]" % sys.argv[0])
- print("")
- print("Supported commands:")
- for name, handler, num_args, desc in cmds:
- print(" %-20s - %s" % (name, desc))
- print("")
- print("Supported keys:")
- print(" %-20s - %s" % ('-j', 'Dump in JSON format'))
- if __name__ == '__main__':
- if len(sys.argv) < 3:
- usage()
- sys.exit(1)
- is_json = '-j' in sys.argv
- if is_json:
- sys.argv.remove('-j')
- main(sys.argv[1], sys.argv[2], sys.argv[3:])
|