home *** CD-ROM | disk | FTP | other *** search
/ Australian Personal Computer 2000 July / CD 3 / redhat-6.2.iso / RedHat / instimage / usr / lib / anaconda / gzread.py < prev    next >
Encoding:
Python Source  |  2000-03-08  |  4.7 KB  |  192 lines

  1. import string
  2. import zlib
  3. import __builtin__
  4.  
  5. # implements a python function that reads and writes a gzipped file
  6. # the user of the file doesn't have to worry about the compression,
  7. # but random access is not allowed
  8.  
  9. # based on Andrew Kuchling's minigzip.py distributed with the zlib module
  10.  
  11. FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT = 1, 2, 4, 8, 16
  12.  
  13. def read32(buf):
  14.     v = ord(buf[0])
  15.     v = v + (ord(buf[1]) << 8)
  16.     v = v + (ord(buf[2]) << 16)
  17.     v = v + (ord(buf[3]) << 24)
  18.     return v
  19.  
  20. def open(filename, fileobj=None):
  21.     return GzipFile(filename, fileobj)
  22.  
  23. class GzipFile:
  24.  
  25.     myfileobj = None
  26.  
  27.     def __init__(self, filename=None, fileobj=None):
  28.     if fileobj is None:
  29.         fileobj = self.myfileobj = __builtin__.open(filename, 'r')
  30.     self._init_read()
  31.     self.decompress = zlib.decompressobj(-zlib.MAX_WBITS)
  32.     self.fileobj = fileobj
  33.     self.compressed = 1
  34.     self._read_gzip_header()
  35.  
  36.     def _init_read(self):
  37.     self.crc = zlib.crc32("")
  38.     self.size = 0
  39.     self.extrabuf = ""
  40.     self.extrasize = 0
  41.     self.lastbuf = ""
  42.  
  43.     def _read_gzip_header(self):
  44.     magic = self.fileobj.read(2)
  45.     if magic != '\037\213':
  46.         self._unread(magic)
  47.         self.compressed = 0
  48.         return
  49.     method = ord( self.fileobj.read(1) )
  50.     if method != 8:
  51.         raise RuntimeError, 'Unknown compression method'
  52.     flag = ord( self.fileobj.read(1) )
  53.     # modtime = self.fileobj.read(4)
  54.     # extraflag = self.fileobj.read(1)
  55.     # os = self.fileobj.read(1)
  56.     self.fileobj.read(6)
  57.  
  58.     if flag & FEXTRA:
  59.         # Read & discard the extra field, if present
  60.         xlen=ord(self.fileobj.read(1))          
  61.         xlen=xlen+256*ord(self.fileobj.read(1))
  62.         self.fileobj.read(xlen)
  63.     if flag & FNAME:
  64.         # Read and discard a null-terminated string containing the filename
  65.         while (1):
  66.         s=self.fileobj.read(1)
  67.         if not s or s=='\000': break
  68.     if flag & FCOMMENT:
  69.         # Read and discard a null-terminated string containing a comment
  70.         while (1):
  71.         s=self.fileobj.read(1)
  72.         if not s or s=='\000': break
  73.     if flag & FHCRC:
  74.         self.fileobj.read(2)     # Read & discard the 16-bit header CRC
  75.  
  76.     def read(self,size=None):
  77.     if self.extrasize <= 0 and self.fileobj is None:
  78.         return ''
  79.  
  80.     if not self.compressed:
  81.         chunk = ''
  82.         if size and self.extrasize >= size:
  83.         chunk = self.extrabuf[:size]
  84.         self.extrabuf = self.extrabuf[size:]
  85.         self.extrasize = self.extrasize - size
  86.         return chunk
  87.         if self.extrasize:
  88.         chunk = self.extrabuf
  89.         if size:
  90.             size = size - self.extrasize
  91.         self.extrasize = 0
  92.         self.extrabuf = ''
  93.         if not size:
  94.         return chunk + self.fileobj.read()
  95.         else:
  96.         return chunk + self.fileobj.read(size)
  97.  
  98.     readsize = 1024
  99.     if not size:    # get the whole thing
  100.         try:
  101.         while 1:
  102.             self._read(readsize)
  103.             readsize = readsize * 2
  104.         except EOFError:
  105.         size = self.extrasize
  106.     else:           # just get some more of it
  107.         try:
  108.         while size > self.extrasize:
  109.             self._read(readsize)
  110.             readsize = readsize * 2
  111.         except EOFError:
  112.         pass
  113.     
  114.     chunk = self.extrabuf[:size]
  115.     self.extrabuf = self.extrabuf[size:]
  116.     self.extrasize = self.extrasize - size
  117.  
  118.     return chunk
  119.  
  120.     def _unread(self, buf):
  121.     self.extrabuf = buf + self.extrabuf
  122.     self.extrasize = len(buf) + self.extrasize
  123.  
  124.     def _read(self, size=1024):
  125.     try:
  126.         buf = self.fileobj.read(size)
  127.     except AttributeError:
  128.         raise EOFError, "Reached EOF"
  129.     if buf == "":
  130.         uncompress = self.decompress.flush()
  131.         if uncompress == "":
  132.         self._read_eof()
  133.         self.fileobj = None
  134.         raise EOFError, 'Reached EOF'
  135.     else:
  136.         xlen = len(buf)
  137.         if xlen >= 8:
  138.         xoff = 0
  139.         boff = xlen - 8
  140.         else:
  141.         xoff = 8 - xlen
  142.         boff = 0
  143.         self.lastbuf = self.lastbuf[:xoff] + buf[boff:]
  144.         uncompress = self.decompress.decompress(buf)
  145.     self.crc = zlib.crc32(uncompress, self.crc)
  146.     self.extrabuf = self.extrabuf + uncompress
  147.     self.extrasize = self.extrasize + len(uncompress)
  148.     self.size = self.size + len(uncompress)
  149.  
  150.     def _read_eof(self):
  151.     crc32 = read32(self.lastbuf[:4])
  152.     isize = read32(self.lastbuf[4:8])
  153.     if crc32 != self.crc:
  154.         raise IOError, 'CRC check failed'
  155.     elif isize != self.size:
  156.         raise IOError, 'Incorrect length of data produced'
  157.  
  158.     def close(self):
  159.     self.fileobj = None
  160.     if self.myfileobj:
  161.         self.myfileobj.close()
  162.         self.myfileobj = None
  163.  
  164.     def flush(self):
  165.     self.fileobj.flush()
  166.  
  167.     def seek(self):
  168.     raise IOError, 'Random access not allowed in gzip files'
  169.  
  170.     def tell(self):
  171.     raise IOError, 'I won\'t tell() you for gzip files'
  172.  
  173.     def isatty(self):
  174.     return 0
  175.  
  176.     def readline(self):
  177.     bufs = []
  178.     readsize = 100
  179.     while 1:
  180.         c = self.read(readsize)
  181.         i = string.find(c, '\n')
  182.         if i >= 0 or c == '':
  183.         bufs.append(c[:i])
  184.         self._unread(c[i+1:])
  185.         return string.join(bufs, '')
  186.         bufs.append(c)
  187.         readsize = readsize * 2
  188.  
  189.     def readlines(self):
  190.     buf = self.read()
  191.     return string.split(buf, '\n')
  192.