1 | """codefragments.py -- wrapper to modify code fragments."""
|
---|
2 |
|
---|
3 | # (c) 1998, Just van Rossum, Letterror
|
---|
4 |
|
---|
5 | __version__ = "0.8b3"
|
---|
6 | __author__ = "jvr"
|
---|
7 |
|
---|
8 | import warnings
|
---|
9 | warnings.warnpy3k("the cfmfile module is deprecated and is removed in 3,0",
|
---|
10 | stacklevel=2)
|
---|
11 |
|
---|
12 | import Carbon.File
|
---|
13 | import struct
|
---|
14 | from Carbon import Res
|
---|
15 | import os
|
---|
16 | import sys
|
---|
17 |
|
---|
18 | DEBUG = 0
|
---|
19 |
|
---|
20 | error = "cfm.error"
|
---|
21 |
|
---|
22 | BUFSIZE = 0x80000
|
---|
23 |
|
---|
24 | def mergecfmfiles(srclist, dst, architecture = 'fat'):
|
---|
25 | """Merge all files in srclist into a new file dst.
|
---|
26 |
|
---|
27 | If architecture is given, only code fragments of that type will be used:
|
---|
28 | "pwpc" for PPC, "m68k" for cfm68k. This does not work for "classic"
|
---|
29 | 68k code, since it does not use code fragments to begin with.
|
---|
30 | If architecture is None, all fragments will be used, enabling FAT binaries.
|
---|
31 | """
|
---|
32 |
|
---|
33 | srclist = list(srclist)
|
---|
34 | for i in range(len(srclist)):
|
---|
35 | srclist[i] = Carbon.File.pathname(srclist[i])
|
---|
36 | dst = Carbon.File.pathname(dst)
|
---|
37 |
|
---|
38 | dstfile = open(dst, "wb")
|
---|
39 | rf = Res.FSpOpenResFile(dst, 3)
|
---|
40 | try:
|
---|
41 | dstcfrg = CfrgResource()
|
---|
42 | for src in srclist:
|
---|
43 | srccfrg = CfrgResource(src)
|
---|
44 | for frag in srccfrg.fragments:
|
---|
45 | if frag.architecture == 'pwpc' and architecture == 'm68k':
|
---|
46 | continue
|
---|
47 | if frag.architecture == 'm68k' and architecture == 'pwpc':
|
---|
48 | continue
|
---|
49 | dstcfrg.append(frag)
|
---|
50 |
|
---|
51 | frag.copydata(dstfile)
|
---|
52 |
|
---|
53 | cfrgres = Res.Resource(dstcfrg.build())
|
---|
54 | Res.UseResFile(rf)
|
---|
55 | cfrgres.AddResource('cfrg', 0, "")
|
---|
56 | finally:
|
---|
57 | dstfile.close()
|
---|
58 | rf = Res.CloseResFile(rf)
|
---|
59 |
|
---|
60 |
|
---|
61 | class CfrgResource:
|
---|
62 |
|
---|
63 | def __init__(self, path = None):
|
---|
64 | self.version = 1
|
---|
65 | self.fragments = []
|
---|
66 | self.path = path
|
---|
67 | if path is not None and os.path.exists(path):
|
---|
68 | currentresref = Res.CurResFile()
|
---|
69 | resref = Res.FSpOpenResFile(path, 1)
|
---|
70 | Res.UseResFile(resref)
|
---|
71 | try:
|
---|
72 | try:
|
---|
73 | data = Res.Get1Resource('cfrg', 0).data
|
---|
74 | except Res.Error:
|
---|
75 | raise Res.Error, "no 'cfrg' resource found", sys.exc_traceback
|
---|
76 | finally:
|
---|
77 | Res.CloseResFile(resref)
|
---|
78 | Res.UseResFile(currentresref)
|
---|
79 | self.parse(data)
|
---|
80 | if self.version != 1:
|
---|
81 | raise error, "unknown 'cfrg' resource format"
|
---|
82 |
|
---|
83 | def parse(self, data):
|
---|
84 | (res1, res2, self.version,
|
---|
85 | res3, res4, res5, res6,
|
---|
86 | self.memberCount) = struct.unpack("8l", data[:32])
|
---|
87 | data = data[32:]
|
---|
88 | while data:
|
---|
89 | frag = FragmentDescriptor(self.path, data)
|
---|
90 | data = data[frag.memberSize:]
|
---|
91 | self.fragments.append(frag)
|
---|
92 |
|
---|
93 | def build(self):
|
---|
94 | self.memberCount = len(self.fragments)
|
---|
95 | data = struct.pack("8l", 0, 0, self.version, 0, 0, 0, 0, self.memberCount)
|
---|
96 | for frag in self.fragments:
|
---|
97 | data = data + frag.build()
|
---|
98 | return data
|
---|
99 |
|
---|
100 | def append(self, frag):
|
---|
101 | self.fragments.append(frag)
|
---|
102 |
|
---|
103 |
|
---|
104 | class FragmentDescriptor:
|
---|
105 |
|
---|
106 | def __init__(self, path, data = None):
|
---|
107 | self.path = path
|
---|
108 | if data is not None:
|
---|
109 | self.parse(data)
|
---|
110 |
|
---|
111 | def parse(self, data):
|
---|
112 | self.architecture = data[:4]
|
---|
113 | ( self.updatelevel,
|
---|
114 | self.currentVersion,
|
---|
115 | self.oldDefVersion,
|
---|
116 | self.stacksize,
|
---|
117 | self.applibdir,
|
---|
118 | self.fragtype,
|
---|
119 | self.where,
|
---|
120 | self.offset,
|
---|
121 | self.length,
|
---|
122 | self.res1, self.res2,
|
---|
123 | self.memberSize,) = struct.unpack("4lhBB4lh", data[4:42])
|
---|
124 | pname = data[42:self.memberSize]
|
---|
125 | self.name = pname[1:1+ord(pname[0])]
|
---|
126 |
|
---|
127 | def build(self):
|
---|
128 | data = self.architecture
|
---|
129 | data = data + struct.pack("4lhBB4l",
|
---|
130 | self.updatelevel,
|
---|
131 | self.currentVersion,
|
---|
132 | self.oldDefVersion,
|
---|
133 | self.stacksize,
|
---|
134 | self.applibdir,
|
---|
135 | self.fragtype,
|
---|
136 | self.where,
|
---|
137 | self.offset,
|
---|
138 | self.length,
|
---|
139 | self.res1, self.res2)
|
---|
140 | self.memberSize = len(data) + 2 + 1 + len(self.name)
|
---|
141 | # pad to 4 byte boundaries
|
---|
142 | if self.memberSize % 4:
|
---|
143 | self.memberSize = self.memberSize + 4 - (self.memberSize % 4)
|
---|
144 | data = data + struct.pack("hb", self.memberSize, len(self.name))
|
---|
145 | data = data + self.name
|
---|
146 | data = data + '\000' * (self.memberSize - len(data))
|
---|
147 | return data
|
---|
148 |
|
---|
149 | def getfragment(self):
|
---|
150 | if self.where != 1:
|
---|
151 | raise error, "can't read fragment, unsupported location"
|
---|
152 | f = open(self.path, "rb")
|
---|
153 | f.seek(self.offset)
|
---|
154 | if self.length:
|
---|
155 | frag = f.read(self.length)
|
---|
156 | else:
|
---|
157 | frag = f.read()
|
---|
158 | f.close()
|
---|
159 | return frag
|
---|
160 |
|
---|
161 | def copydata(self, outfile):
|
---|
162 | if self.where != 1:
|
---|
163 | raise error, "can't read fragment, unsupported location"
|
---|
164 | infile = open(self.path, "rb")
|
---|
165 | if self.length == 0:
|
---|
166 | infile.seek(0, 2)
|
---|
167 | self.length = infile.tell()
|
---|
168 |
|
---|
169 | # Position input file and record new offset from output file
|
---|
170 | infile.seek(self.offset)
|
---|
171 |
|
---|
172 | # pad to 16 byte boundaries
|
---|
173 | offset = outfile.tell()
|
---|
174 | if offset % 16:
|
---|
175 | offset = offset + 16 - (offset % 16)
|
---|
176 | outfile.seek(offset)
|
---|
177 | self.offset = offset
|
---|
178 |
|
---|
179 | l = self.length
|
---|
180 | while l:
|
---|
181 | if l > BUFSIZE:
|
---|
182 | outfile.write(infile.read(BUFSIZE))
|
---|
183 | l = l - BUFSIZE
|
---|
184 | else:
|
---|
185 | outfile.write(infile.read(l))
|
---|
186 | l = 0
|
---|
187 | infile.close()
|
---|