def _EndRecData(fpin): """Return data from the "End of Central Directory" record, or None. The data is a list of the nine items in the ZIP "End of central dir" record followed by a tenth item, the file seek offset of this record.""" fpin.seek(-22, 2) # Assume no archive comment. filesize = fpin.tell() + 22 # Get file size data = fpin.readall() start = len(data)-2 assert start > 0 if data[0:4] == stringEndArchive and data[start:] == "\000\000": endrec = runpack(structEndArchive, data) return EndRecStruct(endrec, "", filesize - 22) # Search the last END_BLOCK bytes of the file for the record signature. # The comment is appended to the ZIP file and has a 16 bit length. # So the comment may be up to 64K long. We limit the search for the # signature to a few Kbytes at the end of the file for efficiency. # also, the signature must not appear in the comment. END_BLOCK = min(filesize, 1024 * 4) fpin.seek(filesize - END_BLOCK, 0) data = fpin.readall() start = data.rfind(stringEndArchive) if start >= 0: # Correct signature string was found endrec = runpack(structEndArchive, data[start:start+22]) comment = data[start+22:] if endrec[7] == len(comment): # Comment length checks out # Append the archive comment and start offset return EndRecStruct(endrec, comment, filesize - END_BLOCK + start) return # Error, return None
def _GetContents(self, fp): endrec = _EndRecData(fp) if not endrec: raise BadZipfile, "File is not a zip file" size_cd = endrec.stuff[5] # bytes in central directory offset_cd = endrec.stuff[6] # offset of central directory self.comment = endrec.comment x = endrec.filesize - size_cd concat = x - offset_cd self.start_dir = offset_cd + concat fp.seek(self.start_dir, 0) total = 0 while total < size_cd: centdir = fp.read(46) total = total + 46 if centdir[0:4] != stringCentralDir: raise BadZipfile, "Bad magic number for central directory" centdir = runpack(structCentralDir, centdir) filename = fp.read(centdir[_CD_FILENAME_LENGTH]) # Create ZipInfo instance to store file information x = RZipInfo(filename) x.extra = fp.read(centdir[_CD_EXTRA_FIELD_LENGTH]) x.comment = fp.read(centdir[_CD_COMMENT_LENGTH]) total = (total + centdir[_CD_FILENAME_LENGTH] + centdir[_CD_EXTRA_FIELD_LENGTH] + centdir[_CD_COMMENT_LENGTH]) x.header_offset = centdir[_CD_LOCAL_HEADER_OFFSET] + concat # file_offset must be computed below... (x.create_version, x.create_system, x.extract_version, x.reserved, x.flag_bits, x.compress_type, t, d, crc, x.compress_size, x.file_size) = centdir[1:12] x.CRC = r_uint(crc) & 0xffffffff x.dostime = t x.dosdate = d x.volume, x.internal_attr, x.external_attr = centdir[15:18] # Convert date/time code to (year, month, day, hour, min, sec) x.date_time = ( (d>>9)+1980, (d>>5)&0xF, d&0x1F, t>>11, (t>>5)&0x3F, (t&0x1F) * 2 ) self.filelist.append(x) self.NameToInfo[x.filename] = x for data in self.filelist: fp.seek(data.header_offset, 0) fheader = fp.read(30) if fheader[0:4] != stringFileHeader: raise BadZipfile, "Bad magic number for file header" fheader = runpack(structFileHeader, fheader) # file_offset is computed here, since the extra field for # the central directory and for the local file header # refer to different fields, and they can have different # lengths data.file_offset = (data.header_offset + 30 + fheader[_FH_FILENAME_LENGTH] + fheader[_FH_EXTRA_FIELD_LENGTH]) fname = fp.read(fheader[_FH_FILENAME_LENGTH]) if fname != data.orig_filename: raise RuntimeError, \ 'File name in directory "%s" and header "%s" differ.' % ( data.orig_filename, fname) fp.seek(self.start_dir, 0)
def unserialize_code(coderepr, start=0): coderepr = coderepr[start:] header = coderepr[:header_lgt] argcount, nlocals, stacksize, code_len = runpack(FMT, header) assert code_len >= 0 names_pos = code_len + header_lgt code = coderepr[header_lgt:names_pos] num = runpack('i', coderepr[names_pos:names_pos + int_lgt]) names, end_names = unserialize_names(coderepr[names_pos + int_lgt:], num) const_start = names_pos + int_lgt + end_names consts, pos = unserialize_consts(coderepr[const_start:]) pos = start + const_start + pos return Code(argcount, nlocals, stacksize, code, consts, names), pos
def unserialize_consts(constrepr): pos = int_lgt consts_w = [] num = runpack('i', constrepr[:int_lgt]) for i in range(num): next_const, pos = unserialize_const(constrepr, pos) consts_w.append(next_const) return consts_w, pos
def unserialize_const(c, start): assert start >= 0 if c[start] == 'd': end = start + int_lgt + 1 intval = runpack('i', c[start + 1:end]) return Int(intval), end elif c[start] == 's': value, end = unserialize_str(c, start + 1) return Str(value), end elif c[start] == 'n': return spli_None, start + 1 elif c[start] == 'c': return unserialize_code(c, start + 1) else: raise NotSupportedFormat(c[start])
def fromstring(space, s): from pypy.module.micronumpy.interp_numarray import SingleDimArray length = len(s) if length % FLOAT_SIZE == 0: number = length/FLOAT_SIZE else: raise OperationError(space.w_ValueError, space.wrap( "string length %d not divisable by %d" % (length, FLOAT_SIZE))) a = SingleDimArray(number) start = 0 end = FLOAT_SIZE i = 0 while i < number: part = s[start:end] a.storage[i] = runpack('d', part) i += 1 start += FLOAT_SIZE end += FLOAT_SIZE return space.wrap(a)
def fromstring(space, s): from pypy.module.micronumpy.interp_numarray import NDimArray length = len(s) if length % FLOAT_SIZE == 0: number = length/FLOAT_SIZE else: raise OperationError(space.w_ValueError, space.wrap( "string length %d not divisable by %d" % (length, FLOAT_SIZE))) dtype = space.fromcache(W_Float64Dtype) a = NDimArray(number, [number], dtype=dtype) start = 0 end = FLOAT_SIZE i = 0 while i < number: part = s[start:end] a.dtype.setitem(a.storage, i, dtype.box(runpack('d', part))) i += 1 start += FLOAT_SIZE end += FLOAT_SIZE return space.wrap(a)
def fn(): return runpack('i', data)
def fn(): a, b, c, d = runpack('iiii', data) return a * 1000 + b * 100 + c * 10 + d
def fn(): return runpack('sll', 'a\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00')[1]
def runpack_str(self, s): return self.box(runpack(self.format_code, s))
def fn(): return runpack('sll', 'a'+pad+'\x03'+pad+'\x04'+pad)[1]
def _PyFloat_Unpack8(space, ptr, le): input = rffi.charpsize2str(ptr, 8) if rffi.cast(lltype.Signed, le): return runpack.runpack("<d", input) else: return runpack.runpack(">d", input)
def unserialize_str(data, start): end_lgt = start + int_lgt lgt = runpack('i', data[start:end_lgt]) assert lgt >= 0 end_str = end_lgt + lgt return data[end_lgt:end_str], end_str