| 
									
										
										
										
											1998-07-31 09:41:59 +00:00
										 |  |  | """codefragments.py -- wrapper to modify code fragments.""" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-09-06 20:43:28 +00:00
										 |  |  | # (c) 1998, Just van Rossum, Letterror | 
					
						
							| 
									
										
										
										
											1998-07-31 09:41:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | __version__ = "0.8b3" | 
					
						
							|  |  |  | __author__ = "jvr" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-12 21:42:13 +00:00
										 |  |  | import warnings | 
					
						
							| 
									
										
										
										
											2008-07-14 17:42:17 +00:00
										 |  |  | warnings.warnpy3k("the cfmfile module is deprecated and is removed in 3,0", | 
					
						
							|  |  |  |               stacklevel=2) | 
					
						
							| 
									
										
										
										
											2008-05-12 21:42:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-02-05 15:44:03 +00:00
										 |  |  | import Carbon.File | 
					
						
							| 
									
										
										
										
											1998-07-31 09:41:59 +00:00
										 |  |  | import struct | 
					
						
							| 
									
										
										
										
											2001-08-25 12:15:04 +00:00
										 |  |  | from Carbon import Res | 
					
						
							| 
									
										
										
										
											1998-07-31 09:41:59 +00:00
										 |  |  | import os | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEBUG = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | error = "cfm.error" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BUFSIZE = 0x80000 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def mergecfmfiles(srclist, dst, architecture = 'fat'): | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |     """Merge all files in srclist into a new file dst.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |     If architecture is given, only code fragments of that type will be used: | 
					
						
							|  |  |  |     "pwpc" for PPC, "m68k" for cfm68k. This does not work for "classic" | 
					
						
							|  |  |  |     68k code, since it does not use code fragments to begin with. | 
					
						
							|  |  |  |     If architecture is None, all fragments will be used, enabling FAT binaries. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |     srclist = list(srclist) | 
					
						
							|  |  |  |     for i in range(len(srclist)): | 
					
						
							|  |  |  |         srclist[i] = Carbon.File.pathname(srclist[i]) | 
					
						
							|  |  |  |     dst = Carbon.File.pathname(dst) | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |     dstfile = open(dst, "wb") | 
					
						
							|  |  |  |     rf = Res.FSpOpenResFile(dst, 3) | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         dstcfrg = CfrgResource() | 
					
						
							|  |  |  |         for src in srclist: | 
					
						
							|  |  |  |             srccfrg = CfrgResource(src) | 
					
						
							|  |  |  |             for frag in srccfrg.fragments: | 
					
						
							|  |  |  |                 if frag.architecture == 'pwpc' and architecture == 'm68k': | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 if frag.architecture == 'm68k' and architecture == 'pwpc': | 
					
						
							|  |  |  |                     continue | 
					
						
							|  |  |  |                 dstcfrg.append(frag) | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |                 frag.copydata(dstfile) | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |         cfrgres = Res.Resource(dstcfrg.build()) | 
					
						
							|  |  |  |         Res.UseResFile(rf) | 
					
						
							|  |  |  |         cfrgres.AddResource('cfrg', 0, "") | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         dstfile.close() | 
					
						
							|  |  |  |         rf = Res.CloseResFile(rf) | 
					
						
							| 
									
										
										
										
											1998-07-31 09:41:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class CfrgResource: | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |     def __init__(self, path = None): | 
					
						
							|  |  |  |         self.version = 1 | 
					
						
							|  |  |  |         self.fragments = [] | 
					
						
							|  |  |  |         self.path = path | 
					
						
							|  |  |  |         if path is not None and os.path.exists(path): | 
					
						
							|  |  |  |             currentresref = Res.CurResFile() | 
					
						
							|  |  |  |             resref = Res.FSpOpenResFile(path, 1) | 
					
						
							|  |  |  |             Res.UseResFile(resref) | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     data = Res.Get1Resource('cfrg', 0).data | 
					
						
							|  |  |  |                 except Res.Error: | 
					
						
							|  |  |  |                     raise Res.Error, "no 'cfrg' resource found", sys.exc_traceback | 
					
						
							|  |  |  |             finally: | 
					
						
							|  |  |  |                 Res.CloseResFile(resref) | 
					
						
							|  |  |  |                 Res.UseResFile(currentresref) | 
					
						
							|  |  |  |             self.parse(data) | 
					
						
							|  |  |  |             if self.version <> 1: | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |                 raise error, "unknown 'cfrg' resource format" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |     def parse(self, data): | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         (res1, res2, self.version, | 
					
						
							|  |  |  |             res3, res4, res5, res6, | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |             self.memberCount) = struct.unpack("8l", data[:32]) | 
					
						
							|  |  |  |         data = data[32:] | 
					
						
							|  |  |  |         while data: | 
					
						
							|  |  |  |             frag = FragmentDescriptor(self.path, data) | 
					
						
							|  |  |  |             data = data[frag.memberSize:] | 
					
						
							|  |  |  |             self.fragments.append(frag) | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |     def build(self): | 
					
						
							|  |  |  |         self.memberCount = len(self.fragments) | 
					
						
							|  |  |  |         data = struct.pack("8l", 0, 0, self.version, 0, 0, 0, 0, self.memberCount) | 
					
						
							|  |  |  |         for frag in self.fragments: | 
					
						
							|  |  |  |             data = data + frag.build() | 
					
						
							|  |  |  |         return data | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |     def append(self, frag): | 
					
						
							|  |  |  |         self.fragments.append(frag) | 
					
						
							| 
									
										
										
										
											1998-07-31 09:41:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FragmentDescriptor: | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |     def __init__(self, path, data = None): | 
					
						
							|  |  |  |         self.path = path | 
					
						
							|  |  |  |         if data is not None: | 
					
						
							|  |  |  |             self.parse(data) | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |     def parse(self, data): | 
					
						
							|  |  |  |         self.architecture = data[:4] | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |         (   self.updatelevel, | 
					
						
							|  |  |  |             self.currentVersion, | 
					
						
							|  |  |  |             self.oldDefVersion, | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |             self.stacksize, | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |             self.applibdir, | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |             self.fragtype, | 
					
						
							|  |  |  |             self.where, | 
					
						
							|  |  |  |             self.offset, | 
					
						
							|  |  |  |             self.length, | 
					
						
							|  |  |  |             self.res1, self.res2, | 
					
						
							|  |  |  |             self.memberSize,) = struct.unpack("4lhBB4lh", data[4:42]) | 
					
						
							|  |  |  |         pname = data[42:self.memberSize] | 
					
						
							|  |  |  |         self.name = pname[1:1+ord(pname[0])] | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |     def build(self): | 
					
						
							|  |  |  |         data = self.architecture | 
					
						
							|  |  |  |         data = data + struct.pack("4lhBB4l", | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |                 self.updatelevel, | 
					
						
							|  |  |  |                 self.currentVersion, | 
					
						
							|  |  |  |                 self.oldDefVersion, | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |                 self.stacksize, | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  |                 self.applibdir, | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |                 self.fragtype, | 
					
						
							|  |  |  |                 self.where, | 
					
						
							|  |  |  |                 self.offset, | 
					
						
							|  |  |  |                 self.length, | 
					
						
							|  |  |  |                 self.res1, self.res2) | 
					
						
							|  |  |  |         self.memberSize = len(data) + 2 + 1 + len(self.name) | 
					
						
							|  |  |  |         # pad to 4 byte boundaries | 
					
						
							|  |  |  |         if self.memberSize % 4: | 
					
						
							|  |  |  |             self.memberSize = self.memberSize + 4 - (self.memberSize % 4) | 
					
						
							|  |  |  |         data = data + struct.pack("hb", self.memberSize, len(self.name)) | 
					
						
							|  |  |  |         data = data + self.name | 
					
						
							|  |  |  |         data = data + '\000' * (self.memberSize - len(data)) | 
					
						
							|  |  |  |         return data | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |     def getfragment(self): | 
					
						
							|  |  |  |         if self.where <> 1: | 
					
						
							|  |  |  |             raise error, "can't read fragment, unsupported location" | 
					
						
							|  |  |  |         f = open(self.path, "rb") | 
					
						
							|  |  |  |         f.seek(self.offset) | 
					
						
							|  |  |  |         if self.length: | 
					
						
							|  |  |  |             frag = f.read(self.length) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             frag = f.read() | 
					
						
							|  |  |  |         f.close() | 
					
						
							|  |  |  |         return frag | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |     def copydata(self, outfile): | 
					
						
							|  |  |  |         if self.where <> 1: | 
					
						
							|  |  |  |             raise error, "can't read fragment, unsupported location" | 
					
						
							|  |  |  |         infile = open(self.path, "rb") | 
					
						
							|  |  |  |         if self.length == 0: | 
					
						
							|  |  |  |             infile.seek(0, 2) | 
					
						
							|  |  |  |             self.length = infile.tell() | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |         # Position input file and record new offset from output file | 
					
						
							|  |  |  |         infile.seek(self.offset) | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |         # pad to 16 byte boundaries | 
					
						
							|  |  |  |         offset = outfile.tell() | 
					
						
							|  |  |  |         if offset % 16: | 
					
						
							|  |  |  |             offset = offset + 16 - (offset % 16) | 
					
						
							|  |  |  |         outfile.seek(offset) | 
					
						
							|  |  |  |         self.offset = offset | 
					
						
							| 
									
										
										
										
											2004-07-18 06:16:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-04-09 13:25:43 +00:00
										 |  |  |         l = self.length | 
					
						
							|  |  |  |         while l: | 
					
						
							|  |  |  |             if l > BUFSIZE: | 
					
						
							|  |  |  |                 outfile.write(infile.read(BUFSIZE)) | 
					
						
							|  |  |  |                 l = l - BUFSIZE | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 outfile.write(infile.read(l)) | 
					
						
							|  |  |  |                 l = 0 | 
					
						
							|  |  |  |         infile.close() |