Commit 32d61ed6 authored by Pavel Emelyanov's avatar Pavel Emelyanov

crit: Add ability to en-/de-code flags as text

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: 's avatarPavel Emelyanov <xemul@parallels.com>
parent d2b914dc
...@@ -3,6 +3,7 @@ import "google/protobuf/descriptor.proto"; ...@@ -3,6 +3,7 @@ import "google/protobuf/descriptor.proto";
message CRIU_Opts { message CRIU_Opts {
optional bool hex = 1; // Idicate that CRIT should treat this field as hex. optional bool hex = 1; // Idicate that CRIT should treat this field as hex.
optional bool ipadd = 2; // The field is IPv4/v6 address optional bool ipadd = 2; // The field is IPv4/v6 address
optional string flags = 3;
} }
extend google.protobuf.FieldOptions { extend google.protobuf.FieldOptions {
......
...@@ -49,6 +49,26 @@ def _marked_as_hex(field): ...@@ -49,6 +49,26 @@ def _marked_as_hex(field):
def _marked_as_ip(field): def _marked_as_ip(field):
return field.GetOptions().Extensions[opts_pb2.criu].ipadd 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): def _pb2dict_cast(field, value, pretty = False, is_hex = False):
if not is_hex: if not is_hex:
is_hex = _marked_as_hex(field) is_hex = _marked_as_hex(field)
...@@ -61,12 +81,22 @@ def _pb2dict_cast(field, value, pretty = False, is_hex = False): ...@@ -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 return field.enum_type.values_by_number.get(value, None).name
elif field.type in _basic_cast: elif field.type in _basic_cast:
cast = _basic_cast[field.type] cast = _basic_cast[field.type]
if (cast == int or cast == long) and is_hex and pretty: if pretty and (cast == int or cast == long):
# Fields that have (criu).hex = true option set if is_hex:
# should be stored in hex string format. # Fields that have (criu).hex = true option set
return "0x%x" % value # should be stored in hex string format.
else: return "0x%x" % value
return cast(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: else:
raise Exception("Field(%s) has unsupported type %d" % (field.name, field.type)) raise Exception("Field(%s) has unsupported type %d" % (field.name, field.type))
...@@ -111,6 +141,15 @@ def _dict2pb_cast(field, value): ...@@ -111,6 +141,15 @@ def _dict2pb_cast(field, value):
elif field.type in _basic_cast: elif field.type in _basic_cast:
cast = _basic_cast[field.type] cast = _basic_cast[field.type]
if (cast == int or cast == long) and isinstance(value, unicode): 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 # Some int or long fields might be stored as hex
# strings. See _pb2dict_cast. # strings. See _pb2dict_cast.
return cast(value, 0) return cast(value, 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment