1 """cfmfile - Interface to code fragments on file"""
7 Error
= 'cfmfile.Error'
15 """Information on a single fragment"""
18 self
.current_version
= 0
19 self
.oldest_version
= 0
33 raise Error
, 'Not enough data in cfrg resource'
35 self
.update
, self
.current_version
, self
.oldest_version
, \
36 self
.stacksize
, self
.libdir
, self
.fragtype
, self
.location
, \
37 self
.offset
, self
.length
, self
.res_0
, self
.res_1
, length
= \
38 struct
.unpack("llllhbbllllh", data
[4:42])
39 namelen
= ord(data
[42])
40 self
.name
= data
[43:43+namelen
]
41 if len(self
.name
) != namelen
:
42 raise Error
, 'Not enough data in cfrg resource'
46 length
= (43+len(self
.name
)+3) & ~
3
47 data
= self
.arch
+ struct
.pack("llllhbbllllh", self
.update
, \
48 self
.current_version
, self
.oldest_version
, self
.stacksize
, \
49 self
.libdir
, self
.fragtype
, self
.location
, self
.offset
, \
50 self
.length
, self
.res_0
, self
.res_1
, length
)
51 data
= data
+ chr(len(self
.name
)) + self
.name
52 data
= data
+ ('\0'*(length
-len(data
)))
55 def copydata(self
, ofp
):
56 """Copy fragment data to a new file, updating self.offset"""
57 if self
.location
!= 1:
58 raise Error
, 'Can only copy kOnDiskFlat (data fork) fragments'
60 raise Error
, 'No source file for fragment'
61 # Find out real length (if zero)
64 self
.length
= self
.ifp
.tell()
65 # Position input file and record new offset from output file
66 self
.ifp
.seek(self
.offset
)
67 self
.offset
= ofp
.tell()
71 ofp
.write(self
.ifp
.read(BUFSIZE
))
74 ofp
.write(self
.ifp
.read(l
))
78 def setfile(self
, ifp
):
81 class FragmentResource
:
83 def __init__(self
, data
):
87 r0
, r1
, version
, r3
, r4
, r5
, r6
, nfrag
= struct
.unpack("llllllll", data
[:32])
89 raise Error
, 'Unsupported cfrg version number %d'%version
92 for i
in range(nfrag
):
96 self
.fragments
.append(f
)
98 raise Error
, 'Spurious data after fragment descriptions'
101 data
= struct
.pack("llllllll", 0, 0, 1, 0, 0, 0, 0, len(self
.fragments
))
102 for f
in self
.fragments
:
106 def setfile(self
, ifp
):
107 for f
in self
.fragments
:
110 def copydata(self
, ofp
):
111 for f
in self
.fragments
:
114 def getfragments(self
):
115 return self
.fragments
117 def addfragments(self
, fragments
):
118 self
.fragments
= self
.fragments
+ fragments
120 class ResourceCollection
:
121 def __init__(self
, fhandle
):
123 self
.fhandle
= fhandle
124 oldresfile
= Res
.CurResFile()
125 Res
.UseResFile(fhandle
)
127 ntypes
= Res
.Count1Types()
128 for itype
in range(1, 1+ntypes
):
129 type = Res
.Get1IndType(itype
)
130 nresources
= Res
.Count1Resources(type)
131 for ires
in range(1, 1+nresources
):
132 res
= Res
.Get1IndResource(type, ires
)
133 id, type, name
= res
.GetResInfo()
134 self
.reslist
.append((type, id))
136 Res
.UseResFile(oldresfile
)
138 def contains(self
, type, id):
139 return (type, id) in self
.reslist
141 def getresource(self
, type, id):
142 oldresfile
= Res
.CurResFile()
143 Res
.UseResFile(self
.fhandle
)
145 resource
= Res
.Get1Resource(type, id)
146 Res
.UseResFile(oldresfile
)
149 def saveresto(self
, type, id, fhandle
):
150 oldresfile
= Res
.CurResFile()
151 resource
= self
.getresource(type, id)
152 id, type, name
= resource
.GetResInfo()
153 resource
.DetachResource()
154 Res
.UseResFile(fhandle
)
155 resource
.AddResource(type, id, name
)
156 Res
.UseResFile(oldresfile
)
158 def getreslist(self
):
161 class CfmFile(ResourceCollection
, FragmentResource
):
163 def __init__(self
, fsspec
):
164 rfork
= Res
.FSpOpenResFile(fsspec
, READ
)
165 dfork
= open(fsspec
.as_pathname(), 'rb')
166 ResourceCollection
.__init
__(self
, rfork
)
167 cfrg_resource
= self
.getresource('cfrg', 0)
168 FragmentResource
.__init
__(self
, cfrg_resource
.data
)
171 def mergecfmfiles(inputs
, output
):
172 # Convert inputs/outputs to fsspecs
173 inputs
= map(None, inputs
)
174 for i
in range(len(inputs
)):
175 if type(inputs
[i
]) == type(''):
176 inputs
[i
] = macfs
.FSSpec(inputs
[i
])
177 if type(output
) == type(''):
178 output
= macfs
.FSSpec(output
)
182 input_list
.append(CfmFile(i
))
184 # Create output file, if needed
185 creator
, tp
= inputs
[0].GetCreatorType()
187 Res
.FSpCreateResFile(output
, creator
, tp
, smAllScripts
)
192 dfork
= open(output
.as_pathname(), 'wb')
198 for i
in input_list
[1:]:
199 input_list
[0].addfragments(i
.getfragments())
201 old_res_file
= Res
.CurResFile()
202 rfork
= Res
.FSpOpenResFile(output
, WRITE
)
203 Res
.UseResFile(rfork
)
206 data
= input_list
[0].save()
207 cfrg_resource
= Res
.Resource(data
)
208 cfrg_resource
.AddResource('cfrg', 0, '')
209 resources_done
= [('cfrg', 0)]
211 # Write other resources
213 todo
= i
.getreslist()
215 if (tp
, id) in resources_done
:
217 i
.saveresto(tp
, id, rfork
)
218 resources_done
.append(tp
, id)
223 fss
, ok
= macfs
.PromptGetFile("Next input file:", "shlb", "APPL")
228 output
, ok
= macfs
.StandardPutFile("Output file:")
231 mergecfmfiles(list, output
)
233 if __name__
== '__main__':