diff options
author | Alon Levy <alevy@redhat.com> | 2011-07-29 14:12:49 +0300 |
---|---|---|
committer | Alon Levy <alevy@redhat.com> | 2011-07-29 14:12:49 +0300 |
commit | e89b797d484f3d8c8d7ac315b19a01dead87c982 (patch) | |
tree | 33fdf117346568a18abc58195482f89628c05547 /peversion | |
parent | b57e24f5f873e998a099663893940db204f16702 (diff) |
add peversion, used by copy_qxl_to_image
Diffstat (limited to 'peversion')
-rwxr-xr-x | peversion | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/peversion b/peversion new file mode 100755 index 0000000..b41ff6a --- /dev/null +++ b/peversion @@ -0,0 +1,147 @@ +#!/usr/bin/python + +import struct +import os +import sys +import string +import datetime +import re + +#### util + +def oldness(f): + if not os.path.exists(f): + return 'file doesn\'t exist' + d = datetime.datetime.now() - datetime.datetime.fromtimestamp(os.stat(f).st_mtime) + if d.days > 0: + s = '%d days' % d.days + elif d.seconds > 3600: + s = '%d hours' % int(d.seconds / 3600) + elif d.seconds > 60: + s = '%d minutes' % int(d.seconds / 60) + s = '%d seconds' % d.seconds + return s, d.seconds + +def get_lib(fname, rexp): + l = os.popen('ldd "%s"' % fname).readlines() + refs_raw=[x.split('=>') for x in l if '=>' in x] + refs=[(r[0].strip().split()[0], r[1].strip().split()[0]) for r in refs_raw] + ref = [r[1] for r in refs if re.match(rexp, r[0])] + if len(ref) == 0: + return 'library not found' + return ref[0] + +#### small resource parsing library +""" +typedef struct { + DWORD DataSize; + DWORD HeaderSize; + DWORD TYPE; + DWORD NAME; + DWORD DataVersion; + WORD MemoryFlags; + WORD LanguageId; + DWORD Version; + DWORD Characteristics; +} RESOURCEHEADER; +""" + +def parse_resource_proper(rsrc): + # http://www.fine-view.com/jp/labs/doc/res32fmt.htm + # TODO + off = 0 + def get(d): + l = struct.calcsize(d) + return off + l, struct.unpack(d, rsrc[off:off+l]) + # data_size - extra space following header, not including padding + # header_size - size of header structure + # res_type - resource type id (standard or custom) + off, (data_size, header_size) = get('<LL') + return {} + (data_size, header_size, res_type, res_name, data_version, + memory_flags, language_id, version, characteristics + ) = struct.unpack(header_def, rsrc[:header_len]) + print data_size, header_size, res_type, res_name, data_version + return locals() + +printable = set(string.printable) + +def looks_like_a_string_key(key): + for key_i in xrange(1, len(key) - 1): + key_subset = set(key[key_i:]) + if key_subset <= printable and key[key_i-1] == '\x01': + return key_i + return None + +def resource_to_strings(rsrc): + """ + 1. split to repeating non zero two byte groups (i.e. utf-16 strings) + 2. throw anything of length 1 or 0 (fixes some misses with keys, particularily + CompanyName) + 3. go over anything left: a key looks like GGG\x01KKKKKK where G is garbage, K + is an ascii (so in printable). Check bruteforcely. The value is always right after + it. + """ + groups = [[]] + for u in [rsrc[x:x+2] for x in xrange(0,len(rsrc),2)]: + if u == '\x00\x00': + groups.append([]) + continue + groups[-1].append(u) + strings = [''.join([a[0] for a in g]) for g in groups if len(g) > 1] + out = {} + ind = 0 + #print '\n'.join('%2d: %r' % (i, s) for i, s in enumerate(strings)) + while ind < len(strings) - 1: + key = strings[ind] + #print ind, repr(key) + if key == 'VS_VERSION_INFO': + out['VS_VERSION_INFO'] = strings[ind+1] + ind += 2 + continue + if set(key) & printable == set(): + ind += 1 + continue + key_i = looks_like_a_string_key(key) + if key_i: + out[key[key_i:]] = strings[ind + 1] + ind += 2 + continue + ind += 1 + return out + +parse_resource = resource_to_strings +#### + +try: + import pefile +except: + if os.path.exists('/usr/bin/yum'): + print "please do 'yum install python-pefile'" + else: + print "missing python pefile module" + raise SystemExit + +if __name__ == '__main__': + f=sys.argv[-1] + if not os.path.exists(f): + print "%s doesn't exist" % f + raise SystemExit + try: + pe=pefile.PE(f) + except: + print "can't parse pe header - is this a PE file?" + raise SystemExit + rsrc = [s for s in pe.sections if s.Name.startswith('.rsrc\x00')] + if len(rsrc) == 0: + print "missing .rsrc section, no version information in this file" + raise SystemExit + d = parse_resource(rsrc[0].data) + n = max(map(len, d.keys())) + #print '\n'.join('%s: %r' % (k.ljust(n), v) for k,v in d.items()) + age_string, age_seconds = oldness(f) + print '%s: FV: %r, PV: %r\nage: %s' % (f, d['FileVersion'], d['ProductVersion'], age_string) + if age_seconds < 60: + sys.exit(0) + sys.exit(1) + |