1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import os, shutil, errno
20 from stat import *
21
23 """(list, dir) --- Takes an array(list) and appends all files from dir down
24 the directory tree. Returns nothing. list is modified."""
25 for x in os.listdir("."):
26 if os.path.isdir(x):
27 os.chdir(x)
28 addtolist(mylist,curdir+x+"/")
29 os.chdir("..")
30 else:
31 if curdir+x not in mylist:
32 mylist.append(curdir+x)
33
35 """Takes a 4 byte integer and converts it into a string of 4 characters.
36 Returns the characters in a string."""
37 part1=chr((myint >> 24 ) & 0x000000ff)
38 part2=chr((myint >> 16 ) & 0x000000ff)
39 part3=chr((myint >> 8 ) & 0x000000ff)
40 part4=chr(myint & 0x000000ff)
41 return part1+part2+part3+part4
42
44 """Takes a 4 byte string and converts it into a 4 byte integer.
45 Returns an integer."""
46 myint=0
47 myint=myint+ord(mystring[3])
48 myint=myint+(ord(mystring[2]) << 8)
49 myint=myint+(ord(mystring[1]) << 16)
50 myint=myint+(ord(mystring[0]) << 24)
51 return myint
52
53 -def xpak(rootdir,outfile=None):
54 """(rootdir,outfile) -- creates an xpak segment of the directory 'rootdir'
55 and under the name 'outfile' if it is specified. Otherwise it returns the
56 xpak segment."""
57 try:
58 origdir=os.getcwd()
59 except SystemExit:
60 raise
61 except:
62 os.chdir("/")
63 origdir="/"
64 os.chdir(rootdir)
65 mylist=[]
66
67 addtolist(mylist,"")
68 mylist.sort()
69 mydata = {}
70 for x in mylist:
71 a = open(x, "r")
72 mydata[x] = a.read()
73 a.close()
74 os.chdir(origdir)
75
76 xpak_segment = xpak_mem(mydata)
77 if outfile:
78 outf = open(outfile, "w")
79 outf.write(xpak_segment)
80 outf.close()
81 else:
82 return xpak_segment
83
85 """Create an xpack segement from a map object."""
86 indexglob=""
87 indexpos=0
88 dataglob=""
89 datapos=0
90 for x, newglob in mydata.iteritems():
91 mydatasize=len(newglob)
92 indexglob=indexglob+encodeint(len(x))+x+encodeint(datapos)+encodeint(mydatasize)
93 indexpos=indexpos+4+len(x)+4+4
94 dataglob=dataglob+newglob
95 datapos=datapos+mydatasize
96 return "XPAKPACK" \
97 + encodeint(len(indexglob)) \
98 + encodeint(len(dataglob)) \
99 + indexglob \
100 + dataglob \
101 + "XPAKSTOP"
102
104 """(infile) -- Splits the infile into two files.
105 'infile.index' contains the index segment.
106 'infile.dat' contails the data segment."""
107 myfile=open(infile,"r")
108 mydat=myfile.read()
109 myfile.close()
110
111 splits = xsplit_mem(mydat)
112 if not splits:
113 return False
114
115 myfile=open(infile+".index","w")
116 myfile.write(splits[0])
117 myfile.close()
118 myfile=open(infile+".dat","w")
119 myfile.write(splits[1])
120 myfile.close()
121 return True
122
124 if mydat[0:8]!="XPAKPACK":
125 return None
126 if mydat[-8:]!="XPAKSTOP":
127 return None
128 indexsize=decodeint(mydat[8:12])
129
130 return (mydat[16:indexsize+16], mydat[indexsize+16:-8])
131
133 """(infile) -- grabs the index segment from the infile and returns it."""
134 myfile=open(infile,"r")
135 myheader=myfile.read(16)
136 if myheader[0:8]!="XPAKPACK":
137 myfile.close()
138 return
139 indexsize=decodeint(myheader[8:12])
140 myindex=myfile.read(indexsize)
141 myfile.close()
142 return myindex
143
145 """(infile) -- grabs the index and data segments from the infile.
146 Returns an array [indexSegment,dataSegment]"""
147 myfile=open(infile,"r")
148 myheader=myfile.read(16)
149 if myheader[0:8]!="XPAKPACK":
150 myfile.close()
151 return
152 indexsize=decodeint(myheader[8:12])
153 datasize=decodeint(myheader[12:16])
154 myindex=myfile.read(indexsize)
155 mydata=myfile.read(datasize)
156 myfile.close()
157 return myindex, mydata
158
160 """Print to the terminal the filenames listed in the indexglob passed in."""
161 for x in getindex_mem(myindex):
162 print x
163
165 """Returns the filenames listed in the indexglob passed in."""
166 myindexlen=len(myindex)
167 startpos=0
168 myret=[]
169 while ((startpos+8)<myindexlen):
170 mytestlen=decodeint(myindex[startpos:startpos+4])
171 myret=myret+[myindex[startpos+4:startpos+4+mytestlen]]
172 startpos=startpos+mytestlen+12
173 return myret
174
176 """(index,item) -- Finds the offset and length of the file 'item' in the
177 datasegment via the index 'index' provided."""
178 mylen=len(myitem)
179 myindexlen=len(myindex)
180 startpos=0
181 while ((startpos+8)<myindexlen):
182 mytestlen=decodeint(myindex[startpos:startpos+4])
183 if mytestlen==mylen:
184 if myitem==myindex[startpos+4:startpos+4+mytestlen]:
185
186 datapos=decodeint(myindex[startpos+4+mytestlen:startpos+8+mytestlen]);
187 datalen=decodeint(myindex[startpos+8+mytestlen:startpos+12+mytestlen]);
188 return datapos, datalen
189 startpos=startpos+mytestlen+12
190
192 myindex=myid[0]
193 mydata=myid[1]
194 myloc=searchindex(myindex,myitem)
195 if not myloc:
196 return None
197 return mydata[myloc[0]:myloc[0]+myloc[1]]
198
200 myindex=myid[0]
201 mydata=myid[1]
202 try:
203 origdir=os.getcwd()
204 except SystemExit:
205 raise
206 except:
207 os.chdir("/")
208 origdir="/"
209 os.chdir(mydest)
210 myindexlen=len(myindex)
211 startpos=0
212 while ((startpos+8)<myindexlen):
213 namelen=decodeint(myindex[startpos:startpos+4])
214 datapos=decodeint(myindex[startpos+4+namelen:startpos+8+namelen]);
215 datalen=decodeint(myindex[startpos+8+namelen:startpos+12+namelen]);
216 myname=myindex[startpos+4:startpos+4+namelen]
217 dirname=os.path.dirname(myname)
218 if dirname:
219 if not os.path.exists(dirname):
220 os.makedirs(dirname)
221 mydat=open(myname,"w")
222 mydat.write(mydata[datapos:datapos+datalen])
223 mydat.close()
224 startpos=startpos+namelen+12
225 os.chdir(origdir)
226
229 self.file=myfile
230 self.filestat=None
231 self.index=""
232 self.infosize=0
233 self.xpaksize=0
234 self.indexsize=None
235 self.datasize=None
236 self.indexpos=None
237 self.datapos=None
238 self.scan()
239
241 """Alias for unpackinfo() --- Complement to recompose() but optionally
242 deletes the destination directory. Extracts the xpak from the tbz2 into
243 the directory provided. Raises IOError if scan() fails.
244 Returns result of upackinfo()."""
245 if not self.scan():
246 raise IOError
247 if cleanup:
248 self.cleanup(datadir)
249 if not os.path.exists(datadir):
250 os.makedirs(datadir)
251 return self.unpackinfo(datadir)
252 - def compose(self,datadir,cleanup=0):
256 """Creates an xpak segment from the datadir provided, truncates the tbz2
257 to the end of regular data if an xpak segment already exists, and adds
258 the new segment to the file with terminating info."""
259 xpdata = xpak(datadir)
260 self.recompose_mem(xpdata)
261 if cleanup:
262 self.cleanup(datadir)
263
265 self.scan()
266 myfile=open(self.file,"a+")
267 if not myfile:
268 raise IOError
269 myfile.seek(-self.xpaksize,os.SEEK_END)
270 myfile.truncate()
271 myfile.write(xpdata+encodeint(len(xpdata))+"STOP")
272 myfile.flush()
273 myfile.close()
274 return 1
275
277 datadir_split = os.path.split(datadir)
278 if len(datadir_split) >= 2 and len(datadir_split[1]) > 0:
279
280
281 try:
282 shutil.rmtree(datadir)
283 except OSError, oe:
284 if oe.errno == errno.ENOENT:
285 pass
286 else:
287 raise oe
288
290 """Scans the tbz2 to locate the xpak segment and setup internal values.
291 This function is called by relevant functions already."""
292 try:
293 mystat=os.stat(self.file)
294 if self.filestat:
295 changed=0
296 for x in [ST_SIZE, ST_MTIME, ST_CTIME]:
297 if mystat[x] != self.filestat[x]:
298 changed=1
299 if not changed:
300 return 1
301 self.filestat=mystat
302 a=open(self.file,"r")
303 a.seek(-16,os.SEEK_END)
304 trailer=a.read()
305 self.infosize=0
306 self.xpaksize=0
307 if trailer[-4:]!="STOP":
308 a.close()
309 return 0
310 if trailer[0:8]!="XPAKSTOP":
311 a.close()
312 return 0
313 self.infosize=decodeint(trailer[8:12])
314 self.xpaksize=self.infosize+8
315 a.seek(-(self.xpaksize),os.SEEK_END)
316 header=a.read(16)
317 if header[0:8]!="XPAKPACK":
318 a.close()
319 return 0
320 self.indexsize=decodeint(header[8:12])
321 self.datasize=decodeint(header[12:16])
322 self.indexpos=a.tell()
323 self.index=a.read(self.indexsize)
324 self.datapos=a.tell()
325 a.close()
326 return 2
327 except SystemExit:
328 raise
329 except:
330 return 0
331
333 """Return an array of each file listed in the index."""
334 if not self.scan():
335 return None
336 return getindex_mem(self.index)
337
338 - def getfile(self,myfile,mydefault=None):
339 """Finds 'myfile' in the data segment and returns it."""
340 if not self.scan():
341 return None
342 myresult=searchindex(self.index,myfile)
343 if not myresult:
344 return mydefault
345 a=open(self.file,"r")
346 a.seek(self.datapos+myresult[0],0)
347 myreturn=a.read(myresult[1])
348 a.close()
349 return myreturn
350
352 """A split/array representation of tbz2.getfile()"""
353 mydat=self.getfile(myfile)
354 if not mydat:
355 return []
356 return mydat.split()
357
359 """Unpacks all the files from the dataSegment into 'mydest'."""
360 if not self.scan():
361 return 0
362 try:
363 origdir=os.getcwd()
364 except SystemExit:
365 raise
366 except:
367 os.chdir("/")
368 origdir="/"
369 a=open(self.file,"r")
370 if not os.path.exists(mydest):
371 os.makedirs(mydest)
372 os.chdir(mydest)
373 startpos=0
374 while ((startpos+8)<self.indexsize):
375 namelen=decodeint(self.index[startpos:startpos+4])
376 datapos=decodeint(self.index[startpos+4+namelen:startpos+8+namelen]);
377 datalen=decodeint(self.index[startpos+8+namelen:startpos+12+namelen]);
378 myname=self.index[startpos+4:startpos+4+namelen]
379 dirname=os.path.dirname(myname)
380 if dirname:
381 if not os.path.exists(dirname):
382 os.makedirs(dirname)
383 mydat=open(myname,"w")
384 a.seek(self.datapos+datapos)
385 mydat.write(a.read(datalen))
386 mydat.close()
387 startpos=startpos+namelen+12
388 a.close()
389 os.chdir(origdir)
390 return 1
391
393 """Returns all the files from the dataSegment as a map object."""
394 if not self.scan():
395 return 0
396 a = open(self.file, "r")
397 mydata = {}
398 startpos=0
399 while ((startpos+8)<self.indexsize):
400 namelen=decodeint(self.index[startpos:startpos+4])
401 datapos=decodeint(self.index[startpos+4+namelen:startpos+8+namelen]);
402 datalen=decodeint(self.index[startpos+8+namelen:startpos+12+namelen]);
403 myname=self.index[startpos+4:startpos+4+namelen]
404 a.seek(self.datapos+datapos)
405 mydata[myname] = a.read(datalen)
406 startpos=startpos+namelen+12
407 a.close()
408 return mydata
409
411 """Returns an array [indexSegment,dataSegment]"""
412 if not self.scan():
413 return None
414
415 a = open(self.file,"r")
416 a.seek(self.datapos)
417 mydata =a.read(self.datasize)
418 a.close()
419
420 return self.index, mydata
421