Advertisement
Guest User

Untitled

a guest
Nov 4th, 2011
323
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.81 KB | None | 0 0
  1. #!/usr/bin/python
  2. ########################################################################
  3. # Copyright (C) 2010 VMWare, Inc.                                      #
  4. # All Rights Reserved                                                  #
  5. ########################################################################
  6.  
  7. "Parse vmtar format."
  8.  
  9. import gzip
  10. import struct
  11.  
  12. TAR_TYPE_FILE         = '0'
  13. TAR_TYPE_LINK         = '1'
  14. TAR_TYPE_SYMLINK      = '2'
  15. TAR_TYPE_CHARDEV      = '3'
  16. TAR_TYPE_BLOCKDEV     = '4'
  17. TAR_TYPE_DIR          = '5'
  18. TAR_TYPE_FIFO         = '6'
  19. TAR_TYPE_SHAREDFILE   = '7'
  20. TAR_TYPE_GNU_LONGLINK = 'K'
  21. TAR_TYPE_GNU_LONGNAME = 'L'
  22.  
  23. def StrFromNTS(data):
  24.    i = data.find("\x00")
  25.    if i == -1:
  26.       return ""
  27.    return data[:i]
  28.  
  29. class VmTarError(Exception):
  30.    pass
  31.  
  32. class VmTarInfo(object):
  33.    "Class to represent one member of a vmtar archive."
  34.    MAGIC = "visor "
  35.    VERSION = "40"
  36.  
  37.    def __init__(self, name=""):
  38.       self.name = name
  39.       self.mode = 0644
  40.       self.uid = 0
  41.       self.gid = 0
  42.       self.size = 0
  43.       self.mtime = 0
  44.       self.chksum = 0
  45.       self.type = TAR_TYPE_FILE
  46.       self.linkname = ""
  47.       self.uname = ""
  48.       self.gname = ""
  49.       self.devmajor = 0
  50.       self.devminor = 0
  51.       self.prefix = ""
  52.       self.offset = 0
  53.       self.textoffset = 0
  54.       self.textsize = 0
  55.       self.numfixuppgs = 0
  56.  
  57.    @classmethod
  58.    def FromBuf(cls, buf):
  59.       """Initialize VmTarInfo object from raw vmtar header.
  60.            Parameters:
  61.               * buf - a 512-byte string.
  62.            Returns: A new VmTarInfo object, or None if end of headers.
  63.            Raises:
  64.               * VmTarError - If the tar magic or checksum are incorrect.
  65.      """
  66.       if buf[0] == "\x00":
  67.          return None
  68.       if len(buf) < 512:
  69.          raise VmTarError("Header too short")
  70.       magic = buf[257:263]
  71.       if magic != cls.MAGIC:
  72.          raise VmTarError("Invalid header magic")
  73.       version = buf[263:265] # Unused, apparently.
  74.       chksum = int(StrFromNTS(buf[148:156]), 8)
  75.       bytesum = sum(struct.unpack("148B", buf[:148])) + 256 + \
  76.                 sum(struct.unpack("356B", buf[156:512]))
  77.       ubytesum = sum(struct.unpack("148b", buf[:148])) + 256 + \
  78.                  sum(struct.unpack("356b", buf[156:512]))
  79.       if chksum != bytesum and chksum != ubytesum:
  80.          raise VmTarError("Invalid header checksum")
  81.       obj = cls(StrFromNTS(buf[:100]))
  82.       obj.mode = int(StrFromNTS(buf[100:108]) or "0", 8)
  83.       try:
  84.          obj.uid = int(StrFromNTS(buf[108:116]) or "0", 8)
  85.       except ValueError:
  86.          n = 0L
  87.          for i in range(7):
  88.             n <<= 8
  89.             n += ord(buf[109 + i])
  90.          obj.uid = n
  91.       try:
  92.          obj.gid = int(StrFromNTS(buf[116:124]) or "0", 8)
  93.       except ValueError:
  94.          n = 0L
  95.          for i in range(7):
  96.             n <<= 8
  97.             n += ord(buf[117 + i])
  98.          obj.gid = n
  99.       obj.size = int(StrFromNTS(buf[124:136]) or "0", 8)
  100.       obj.mtime = int(StrFromNTS(buf[136:148]) or "0", 8)
  101.       obj.chksum = chksum
  102.       obj.type = buf[156]
  103.       obj.linkname = StrFromNTS(buf[157:257])
  104.       obj.uname = StrFromNTS(buf[265:297])
  105.       obj.gname = StrFromNTS(buf[297:329])
  106.       obj.devmajor = int(StrFromNTS(buf[329:337]) or "0", 8)
  107.       obj.devminor = int(StrFromNTS(buf[337:345]) or "0", 8)
  108.       obj.prefix = buf[345:496]
  109.       # GNU makes every numeric field a human-readable octal. vmtar breaks that
  110.       # convention, and uses packed values for these.
  111.       obj.offset = struct.unpack("<I", buf[496:500])[0]
  112.       obj.textoffset = struct.unpack("<I", buf[500:504])[0]
  113.       obj.textsize = struct.unpack("<I", buf[504:508])[0]
  114.       obj.numfixuppgs = struct.unpack("<I", buf[508:512])[0]
  115.       return obj
  116.  
  117. class VmTar(object):
  118.    def __init__(self, name=None, mode="r|gz", fileobj=None):
  119.       """Class constructor.
  120.            Parameters:
  121.               * name    - The name of a file. May be None if fileobj is
  122.                           specified.
  123.               * mode    - The file mode. Currently only reading is supported.
  124.                           May also append |gz to specify that file or stream
  125.                           is gzip-compressed. Defaults to r|gz.
  126.               * fileobj - Read from a file-like object instead of the file
  127.                           given by name.
  128.            Raises:
  129.               * IOError    - If file cannot be opened or an unsupported mode
  130.                              is given.
  131.               * VmTarError - The data is not in the correct format.
  132.      """
  133.       compression = None
  134.       try:
  135.          mode, compression = mode.split("|")
  136.       except:
  137.          mode = mode
  138.  
  139.       if not "b" in mode:
  140.          mode += "b"
  141.  
  142.       if not fileobj:
  143.          fileobj = file(name, mode)
  144.  
  145.       if compression == "gz":
  146.          fileobj = gzip.GzipFile(mode=mode, fileobj=fileobj)
  147.  
  148.       self._fileobj = fileobj
  149.       self.members = list()
  150.  
  151.       self._ReadHeaders()
  152.  
  153.    def _ReadHeaders(self):
  154.       hdr = VmTarInfo.FromBuf(self._fileobj.read(512))
  155.       while hdr is not None:
  156.          # If hdr type indicates longlink or longname, then the 512-byte block
  157.          # following the header contains the long link name or file name. Note
  158.          # that there can be a 2048-byte sequence of
  159.          #    longlink hdr + longlink + longnamehdr + longname
  160.          # in cases where both a link target and link source are long names.
  161.          longlink = None
  162.          longname = None
  163.          while hdr.type in (TAR_TYPE_GNU_LONGLINK, TAR_TYPE_GNU_LONGNAME):
  164.             if hdr.type == TAR_TYPE_GNU_LONGLINK:
  165.                longlink = self._fileobj.read(512)[:hdr.size-1]
  166.             elif hdr.type == TAR_TYPE_GNU_LONGNAME:
  167.                longname = self._fileobj.read(512)[:hdr.size-1]
  168.             hdr = VmTarInfo.FromBuf(self._fileobj.read(512))
  169.          if longlink is not None:
  170.             hdr.linkname = longlink
  171.          if longname is not None:
  172.             hdr.name = longname
  173.          self.members.append(hdr)
  174.          hdr = VmTarInfo.FromBuf(self._fileobj.read(512))
  175.  
  176.    def getmember(self, name):
  177.       for info in self.members:
  178.          if info.name == name:
  179.             return name
  180.       raise KeyError(name)
  181.  
  182.    def getmembers(self):
  183.       return self.members
  184.  
  185.    def getnames(self):
  186.       return [info.name for info in self.members]
  187.  
  188. def open(name=None, mode="r", fileobj=None):
  189.    if fileobj is None and not mode.endswith("|gz"):
  190.       try:
  191.          vtar = VmTar(name, "%s|gz" % mode, fileobj)
  192.       except IOError:
  193.          vtar = VmTar(name, mode, fileobj)
  194.    else:
  195.       vtar = VmTar(name, mode, fileobj)
  196.    return vtar
  197.  
  198. if __name__ == "__main__":
  199.    import sys
  200.    for fn in sys.argv[1:]:
  201.       vtar = open(fn)
  202.       for name in vtar.getnames():
  203.          sys.stdout.write("%s\n" % name)
  204.  
  205.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement