All pastes #955424 Raw Edit

Miscellany

public text v1 · immutable
#955424 ·published 2008-03-24 16:47 UTC
rendered paste body
import zlib, struct, bz2, os, sys
from xml.dom.minidom import parseString

def getByte(f):
    return struct.unpack("<B",f.read(1))[0];

def getWord(f):
    return struct.unpack(">H",f.read(2))[0];

def getSWord(f):
    return struct.unpack(">h",f.read(2))[0];

def getDWord(f):
    return struct.unpack(">I",f.read(4))[0];

def getSDWord(f):
    return struct.unpack(">i",f.read(4))[0];

def getQWord(f):
    return struct.unpack(">Q",f.read(8))[0];

def getDouble(f):
    return struct.unpack(">d",f.read(8))[0];

"""
struct xar_header {
        uint32_t magic;
        uint16_t size;
        uint16_t version;
        uint64_t toc_length_compressed;
        uint64_t toc_length_uncompressed;
        uint32_t cksum_alg;
};

"""

def getChildNodes(node, tagname):
  return [c for c in node.childNodes if ((c.nodeType==c.ELEMENT_NODE) and (c.tagName==tagname))]

def getChildNode(node, tagname):
  return getChildNodes(node, tagname)[0]

def domtext(node, subnode):
  n1 = getChildNode(node, subnode)
  for n2 in n1.childNodes:
    if n2.nodeType == n2.TEXT_NODE:
      return n2.data

def domint(node, subnode):
  return int(domtext(node, subnode))

def getattr(node, subnode, attrname):
  subn = node.getElementsByTagName(subnode)[0]
  attr = subn.getAttribute(attrname)
  return attr

class XarFile:

  def handleFile(self, fil, dirname):
    name = domtext(fil, "name")
    type = domtext(fil, "type")
    print "Name: %s"%name
    print "Type: %s"%type
    if type == "file":
      dtn = getChildNode(fil, "data")
      offset = domint(dtn, "offset")
      length = domint(dtn, "length")
      enc = getattr(dtn, "encoding", "style")
      self._file.seek(self.start_offset+offset)
      data = self._file.read(length)
      if enc=="application/x-bzip2":
        try:
           data = bz2.decompress(data)
        except:
           print "Error decompressing %s! Writing as-is"%name
      elif enc!="application/octet-stream":
        raise Exception("Unknown encoding: %s!"%enc)
      file(dirname+'/'+name, "wb").write(data)
    elif type == "directory":
      newdir = dirname+'/'+name
      try:
        os.makedirs(newdir)
      except:
        pass
      files = getChildNodes(fil, "file")
      for fil2 in files:
        #print fil
        self.handleFile(fil2, newdir)
            

  def walk_toc(self, toc_, dirname):
    dom = parseString(toc_)
    toc = dom.getElementsByTagName("toc")[0]
    files = getChildNodes(toc, "file")
    for fil in files:
      #print fil
      self.handleFile(fil, dirname)

  def doXar(self, fname, dirname):
    f = file(fname,"rb")
    if f.read(4)!='xar!':
      print "bad header!"
      return

    size = getWord(f)
    ver = getWord(f)
    tocu = getQWord(f)
    tocc = getQWord(f)
    f.seek(size)
    toc = zlib.decompress(f.read(tocc))
    #f.seek(size+tocu)
    self.start_offset = size+tocu
    #print toc
    self._file = f
    try:
      os.makedirs(dirname)
    except:
      pass
    self.walk_toc(toc, dirname)
    #return toc, (size+tocu)


xar = XarFile()
xar.doXar(sys.argv[1],sys.argv[2])