summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Levy <alevy@redhat.com>2011-07-29 14:12:49 +0300
committerAlon Levy <alevy@redhat.com>2011-07-29 14:12:49 +0300
commite89b797d484f3d8c8d7ac315b19a01dead87c982 (patch)
tree33fdf117346568a18abc58195482f89628c05547
parentb57e24f5f873e998a099663893940db204f16702 (diff)
add peversion, used by copy_qxl_to_image
-rwxr-xr-xpeversion147
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)
+