[CRIU] [PATCH 4/6] crit: add --format hex option

Ruslan Kuprieiev kupruser at gmail.com
Fri Jan 16 12:55:55 PST 2015


hex option could be combined with other options(i.e. --format nice hex).

Signed-off-by: Ruslan Kuprieiev <kupruser at gmail.com>
---
 crit                     | 14 +++++++++-----
 pycriu/images/images.py  | 24 ++++++++++++------------
 pycriu/images/pb2dict.py | 29 ++++++++++++++++++++++-------
 3 files changed, 43 insertions(+), 24 deletions(-)

diff --git a/crit b/crit
index e5d9b08..0b1671c 100755
--- a/crit
+++ b/crit
@@ -7,7 +7,7 @@ import pycriu
 
 def handle_cmdline_opts():
 	desc = 'CRiu Image Tool'
-	parser = argparse.ArgumentParser(description=desc)
+	parser = argparse.ArgumentParser(description=desc, formatter_class=argparse.RawTextHelpFormatter)
 	parser.add_argument('command',
 			    choices = ['decode', 'encode'],
 			help = 'decode/encode - convert criu image from/to binary type to/from json')
@@ -19,8 +19,12 @@ def handle_cmdline_opts():
 			help = 'output file (stdout by default)')
 	parser.add_argument('-f',
 			    '--format',
-			    choices = ['raw', 'nice'],
-			help = 'well-formated output (by default: raw for files and nice for stdout)')
+			    choices = ['raw', 'nice', 'hex'],
+			    nargs = '+',
+			    default = [],
+			help = 'raw  - all in one line\n'\
+			       'nice - add indents and newlines to look nice(default for stdout)\n'\
+			       'hex  - print int fields as hex strings where suitable(could be combined with others)')
 
 	opts = vars(parser.parse_args())
 
@@ -41,10 +45,10 @@ def outf(opts):
 
 def decode(opts):
 	indent = None
-	img = pycriu.images.load(inf(opts))
+	img = pycriu.images.load(inf(opts), 'hex' in opts['format'])
 
 	# For stdout --format nice is set by default.
-	if opts['format'] == 'nice' or (opts['format'] == None and opts['out'] == None):
+	if 'nice' in opts['format'] or ('raw' not in opts['format'] and opts['out'] == None):
 		indent = 4
 
 	f = outf(opts)
diff --git a/pycriu/images/images.py b/pycriu/images/images.py
index 83a1e3e..9460615 100644
--- a/pycriu/images/images.py
+++ b/pycriu/images/images.py
@@ -59,7 +59,7 @@ class entry_handler:
 		self.payload		= payload
 		self.extra_handler	= extra_handler
 
-	def load(self, f):
+	def load(self, f, print_hex = False):
 		"""
 		Convert criu image entries from binary format to dict(json).
 		Takes a file-like object and returnes a list with entries in
@@ -77,7 +77,7 @@ class entry_handler:
 				break
 			size, = struct.unpack('i', buf)
 			pb.ParseFromString(f.read(size))
-			entry = pb2dict.pb2dict(pb)
+			entry = pb2dict.pb2dict(pb, print_hex)
 
 			# Read extra
 			if self.extra_handler:
@@ -87,12 +87,12 @@ class entry_handler:
 
 		return entries
 
-	def loads(self, s):
+	def loads(self, s, print_hex = False):
 		"""
 		Same as load(), but takes a string as an argument.
 		"""
 		f = io.BytesIO(s)
-		return self.load(f)
+		return self.load(f, print_hex)
 
 	def dump(self, entries, f):
 		"""
@@ -131,7 +131,7 @@ class pagemap_handler:
 	that it has a header of pagemap_head type followed by entries
 	of pagemap_entry type.
 	"""
-	def load(self, f):
+	def load(self, f, print_hex = False):
 		entries = []
 
 		pb = pagemap_head()
@@ -141,15 +141,15 @@ class pagemap_handler:
 				break
 			size, = struct.unpack('i', buf)
 			pb.ParseFromString(f.read(size))
-			entries.append(pb2dict.pb2dict(pb))
+			entries.append(pb2dict.pb2dict(pb, print_hex))
 
 			pb = pagemap_entry()
 
 		return entries
 
-	def loads(self, s):
+	def loads(self, s, print_hex = False):
 		f = io.BytesIO(s)
-		return self.load(f)
+		return self.load(f, print_hex)
 
 	def dump(self, entries, f):
 		pb = pagemap_head()
@@ -258,7 +258,7 @@ handlers = {
 	'IPCNS_MSG'		: entry_handler(ipc_msg_entry)
 	}
 
-def load(f):
+def load(f, print_hex = False):
 	"""
 	Convert criu image from binary format to dict(json).
 	Takes a file-like object to read criu image from.
@@ -281,16 +281,16 @@ def load(f):
 		raise Exception("No handler found for image with such magic "+m)
 
 	image['magic']		= m
-	image['entries']	= handler.load(f)
+	image['entries']	= handler.load(f, print_hex)
 
 	return image
 
-def loads(s):
+def loads(s, print_hex = False):
 	"""
 	Same as load(), but takes a string.
 	"""
 	f = io.BytesIO(s)
-	return load(f)
+	return load(f, print_hex)
 
 def dump(img, f):
 	"""
diff --git a/pycriu/images/pb2dict.py b/pycriu/images/pb2dict.py
index 815870b..c01442c 100644
--- a/pycriu/images/pb2dict.py
+++ b/pycriu/images/pb2dict.py
@@ -1,4 +1,5 @@
 from google.protobuf.descriptor import FieldDescriptor as FD
+import opts_pb2
 
 # pb2dict and dict2pb are methods to convert pb to/from dict.
 # Inspired by:
@@ -39,19 +40,27 @@ _basic_cast = {
 	FD.TYPE_STRING		: unicode
 }
 
-def _pb2dict_cast(field, value):
+def _pb2dict_cast(field, value, print_hex = False):
 	if field.type == FD.TYPE_MESSAGE:
-		return pb2dict(value)
+		return pb2dict(value, print_hex)
 	elif field.type == FD.TYPE_BYTES:
 		return value.encode('base64')
 	elif field.type == FD.TYPE_ENUM:
 		return field.enum_type.values_by_number.get(value, None).name
 	elif field.type in _basic_cast:
-		return _basic_cast[field.type](value)
+		cast = _basic_cast[field.type]
+		if (cast == int or cast == long) and \
+		   field.GetOptions().Extensions[opts_pb2.criu].hex and \
+		   print_hex:
+			# Fields that have (criu).hex = true option set
+			# should be stored in hex string format.
+			return "0x%x" % value
+		else:
+			return cast(value)
 	else:
 		raise Exception("Field(%s) has unsupported type %d" % (field.name, field.type))
 
-def pb2dict(pb):
+def pb2dict(pb, print_hex = False):
 	"""
 	Convert protobuf msg to dictionary.
 	Takes a protobuf message and returns a dict.
@@ -61,9 +70,9 @@ def pb2dict(pb):
 		if field.label == FD.LABEL_REPEATED:
 			d_val = []
 			for v in value:
-				d_val.append(_pb2dict_cast(field, v))
+				d_val.append(_pb2dict_cast(field, v, print_hex))
 		else:
-			d_val = _pb2dict_cast(field, value)
+			d_val = _pb2dict_cast(field, value, print_hex)
 
 		d[field.name] = d_val
 	return d
@@ -77,7 +86,13 @@ def _dict2pb_cast(field, value):
 	elif field.type == FD.TYPE_ENUM:
 		return field.enum_type.values_by_name.get(value, None).number
 	else:
-		return _basic_cast[field.type](value)
+		cast = _basic_cast[field.type]
+		if (cast == int or cast == long) and isinstance(value, unicode):
+			# Some int or long fields might be stored as hex
+			# strings. See _pb2dict_cast.
+			return cast(value, 0)
+		else:
+			return cast(value)
 
 def dict2pb(d, pb):
 	"""
-- 
2.1.0



More information about the CRIU mailing list