#!/usr/bin/env python
###
# isanypkg -- determine whether a binary package is architecture-independent.

# Copyright (C) 2009 Chris Brannon <cmbrannon79 _AT_ gmail _DOT_ com>
#
# License: do as you will, but don't remove the copyright notice!

# Usage: isanypkg <PACKAGE_FILE_NAME>
# Exits with a 0 status if package is architecture-independent, 30 if
# package is architecture-dependent.  Positive exit codes other than 30
# indicate error.

# Note: I don't check that a tarfile is, in fact, a binary ArchLinux
# package.  Perhaps I could look at the filename, or search for .PKGINFO,
# but I'm lazy.

import os
import sys
import tarfile
import itertools

def is_elf(pkg, entry):
  ret = False
  if entry.isfile() and entry.size >= 4:
    # In order to be an ELF file, entry needs to be a regular file whose
    # size is large enough to hold '\x7fELF'
    entry_data = pkg.extractfile(entry)
    try:
      ret = entry_data.read(4) == '\x7fELF'
    except:
      raise # Just re-raise it
    finally:
      entry_data.close() # And close the file object in any case
  return ret

def is_arch_independent(pkg):
  try:
    return not any(itertools.imap(lambda x : is_elf(pkg, x), pkg))
  except Exception as e:
    sys.stderr.write('Error while reading tarfile: %s\n' %  (str(e),))
    sys.exit(exitcode_readerr)
      
exitcode_argerr = 1
exitcode_openerr = 2
exitcode_readerr = 3
exitcode_archindep = 0
exitcode_archdep = 30 # Totally random constant.

if __name__ == '__main__':
  exitcode = exitcode_archindep
  if len(sys.argv) != 2:
    sys.stderr.write('Usage: %s <PACKAGEFILE>\n' % (sys.argv[0], ))
    sys.exit(exitcode_argerr)
  fname=sys.argv[1]
  try:
    pkg = tarfile.open(sys.argv[1], 'r')
    if is_arch_independent(pkg):
      print 'Package is architecture-independent.'
      exitcode = exitcode_archindep
    else:
      print 'Package is not architecture-independent.'
      exitcode = exitcode_archdep
    pkg.close()
  except Exception as e:
    sys.stderr.write('Error while opening file %s: %s\n' % (fname, str(e)))
    exitcode=exitcode_openerr
  
  sys.exit(exitcode)
