[CRIU] [PATCH 3/4] crit: Add ability to en-/de-code flags as text

Pavel Emelyanov xemul at parallels.com
Wed Sep 16 06:17:17 PDT 2015


Some flags have known text description, e.g. flags on a file
or flags on vma. Add ability to show these flags in decoded
form (and encode them back into binary).

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>
---
 protobuf/opts.proto      |  1 +
 pycriu/images/pb2dict.py | 51 ++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/protobuf/opts.proto b/protobuf/opts.proto
index ddfffd5..12e4ba4 100644
--- a/protobuf/opts.proto
+++ b/protobuf/opts.proto
@@ -3,6 +3,7 @@ import "google/protobuf/descriptor.proto";
 message CRIU_Opts {
 	optional bool hex = 1; // Idicate that CRIT should treat this field as hex.
 	optional bool ipadd = 2; // The field is IPv4/v6 address
+	optional string flags = 3;
 }
 
 extend google.protobuf.FieldOptions {
diff --git a/pycriu/images/pb2dict.py b/pycriu/images/pb2dict.py
index 39670da..557a83b 100644
--- a/pycriu/images/pb2dict.py
+++ b/pycriu/images/pb2dict.py
@@ -49,6 +49,26 @@ def _marked_as_hex(field):
 def _marked_as_ip(field):
 	return field.GetOptions().Extensions[opts_pb2.criu].ipadd
 
+def _marked_as_flags(field):
+	return field.GetOptions().Extensions[opts_pb2.criu].flags
+
+flags_maps = {
+}
+
+def map_flags(value, flags_map):
+	bs = map(lambda x: x[0], filter(lambda x: value & x[1], flags_map))
+	value &= ~sum(map(lambda x: x[1], flags_map))
+	if value:
+		bs.append("0x%x" % value)
+	return " | ".join(bs)
+
+def unmap_flags(value, flags_map):
+	if value == '':
+		return 0
+
+	bd = dict(flags_map)
+	return sum(map(lambda x: int(str(bd.get(x, x)), 0), map(lambda x: x.strip(), value.split('|'))))
+
 def _pb2dict_cast(field, value, pretty = False, is_hex = False):
 	if not is_hex:
 		is_hex = _marked_as_hex(field)
@@ -61,12 +81,22 @@ def _pb2dict_cast(field, value, pretty = False, is_hex = False):
 		return field.enum_type.values_by_number.get(value, None).name
 	elif field.type in _basic_cast:
 		cast = _basic_cast[field.type]
-		if (cast == int or cast == long) and is_hex and pretty:
-			# Fields that have (criu).hex = true option set
-			# should be stored in hex string format.
-			return "0x%x" % value
-		else:
-			return cast(value)
+		if pretty and (cast == int or cast == long):
+			if is_hex:
+				# Fields that have (criu).hex = true option set
+				# should be stored in hex string format.
+				return "0x%x" % value
+
+			flags = _marked_as_flags(field)
+			if flags:
+				try:
+					flags_map = flags_maps[flags]
+				except:
+					return "0x%x" % value # flags are better seen as hex anyway
+				else:
+					return map_flags(value, flags_map)
+
+		return cast(value)
 	else:
 		raise Exception("Field(%s) has unsupported type %d" % (field.name, field.type))
 
@@ -111,6 +141,15 @@ def _dict2pb_cast(field, value):
 	elif field.type in _basic_cast:
 		cast = _basic_cast[field.type]
 		if (cast == int or cast == long) and isinstance(value, unicode):
+			flags = _marked_as_flags(field)
+			if flags:
+				try:
+					flags_map = flags_maps[flags]
+				except:
+					pass # Try to use plain string cast
+				else:
+					return unmap_flags(value, flags_map)
+
 			# Some int or long fields might be stored as hex
 			# strings. See _pb2dict_cast.
 			return cast(value, 0)
-- 
1.9.3




More information about the CRIU mailing list