# Copyright 2001-2004 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Id: /var/cvsroot/gentoo-src/portage/pym/xpak.py,v 1.13.2.3 2005/02/26 11:22:38 carpaski Exp $ # The format for a tbz2/xpak: # # tbz2: tar.bz2 + xpak + (xpak_offset) + "STOP" # xpak: "XPAKPACK" + (index_len) + (data_len) + index + data + "XPAKSTOP" # index: (pathname_len) + pathname + (data_offset) + (data_len) # index entries are concatenated end-to-end. # data: concatenated data chunks, end-to-end. # # [tarball]XPAKPACKIIIIDDDD[index][data]XPAKSTOPOOOOSTOP # # (integer) == encodeint(integer) ===> 4 characters (big-endian copy) # '+' means concatenate the fields ===> All chunks are strings import sys,os,string from stat import * def addtolist(mylist,curdir): """(list, dir) --- Takes an array(list) and appends all files from dir down the directory tree. Returns nothing. list is modified.""" for x in os.listdir("."): if os.path.isdir(x): os.chdir(x) addtolist(mylist,curdir+x+"/") os.chdir("..") else: if curdir+x not in mylist: mylist.append(curdir+x) def encodeint(myint): """Takes a 4 byte integer and converts it into a string of 4 characters. Returns the characters in a string.""" part1=chr((myint >> 24 ) & 0x000000ff) part2=chr((myint >> 16 ) & 0x000000ff) part3=chr((myint >> 8 ) & 0x000000ff) part4=chr(myint & 0x000000ff) return part1+part2+part3+part4 def decodeint(mystring): """Takes a 4 byte string and converts it into a 4 byte integer. Returns an integer.""" myint=0 myint=myint+ord(mystring[3]) myint=myint+(ord(mystring[2]) << 8) myint=myint+(ord(mystring[1]) << 16) myint=myint+(ord(mystring[0]) << 24) return myint def xpak(rootdir,outfile=None): """(rootdir,outfile) -- creates an xpak segment of the directory 'rootdir' and under the name 'outfile' if it is specified. Otherwise it returns the xpak segment.""" try: origdir=os.getcwd() except SystemExit, e: raise except: os.chdir("/") origdir="/" os.chdir(rootdir) mylist=[] addtolist(mylist,"") mylist.sort() #Our list index has been created indexglob="" indexpos=0 dataglob="" datapos=0 for x in mylist: a=open(x,"r") newglob=a.read() a.close() mydatasize=len(newglob) indexglob=indexglob+encodeint(len(x))+x+encodeint(datapos)+encodeint(mydatasize) indexpos=indexpos+4+len(x)+4+4 dataglob=dataglob+newglob datapos=datapos+mydatasize os.chdir(origdir) if outfile: outf=open(outfile,"w") outf.write("XPAKPACK"+encodeint(len(indexglob))+encodeint(len(dataglob))) outf.write(indexglob) outf.write(dataglob) outf.write("XPAKSTOP") outf.close() else: myret="XPAKPACK"+encodeint(len(indexglob))+encodeint(len(dataglob)) myret=myret+indexglob+dataglob+"XPAKSTOP" return myret def xsplit(infile): """(infile) -- Splits the infile into two files. 'infile.index' contains the index segment. 'infile.dat' contails the data segment.""" myfile=open(infile,"r") mydat=myfile.read() myfile.close() splits = xsplit_mem(mydat) if not splits: return myfile=open(infile+".index","w") myfile.write(splits[0]) myfile.close() myfile=open(infile+".dat","w") myfile.write(splits[1]) myfile.close() return def xsplit_mem(mydat): if mydat[0:8]!="XPAKPACK": return None if mydat[-8:]!="XPAKSTOP": return None indexsize=decodeint(mydat[8:12]) datasize=decodeint(mydat[12:16]) return (mydat[16:indexsize+16], mydat[indexsize+16:-8]) def getindex(infile): """(infile) -- grabs the index segment from the infile and returns it.""" myfile=open(infile,"r") myheader=myfile.read(16) if myheader[0:8]!="XPAKPACK": myfile.close() return indexsize=decodeint(myheader[8:12]) myindex=myfile.read(indexsize) myfile.close() return myindex def getboth(infile): """(infile) -- grabs the index and data segments from the infile. Returns an array [indexSegment,dataSegment]""" myfile=open(infile,"r") myheader=myfile.read(16) if myheader[0:8]!="XPAKPACK": myfile.close() return indexsize=decodeint(myheader[8:12]) datasize=decodeint(myheader[12:16]) myindex=myfile.read(indexsize) mydata=myfile.read(datasize) myfile.close() return [myindex,mydata] def listindex(myindex): """Print to the terminal the filenames listed in the indexglob passed in.""" for x in getindex_mem(myindex): print x def getindex_mem(myindex): """Returns the filenames listed in the indexglob passed in.""" myindexlen=len(myindex) startpos=0 myret=[] while ((startpos+8)