1 | /* |
---|
2 | * tclMacOSXBundle.c -- |
---|
3 | * |
---|
4 | * This file implements functions that inspect CFBundle structures on |
---|
5 | * MacOS X. |
---|
6 | * |
---|
7 | * Copyright 2001, Apple Computer, Inc. |
---|
8 | * Copyright (c) 2003-2007 Daniel A. Steffen <das@users.sourceforge.net> |
---|
9 | * |
---|
10 | * See the file "license.terms" for information on usage and redistribution of |
---|
11 | * this file, and for a DISCLAIMER OF ALL WARRANTIES. |
---|
12 | * |
---|
13 | * The following terms apply to all files originating from Apple |
---|
14 | * Computer, Inc. ("Apple") and associated with the software unless |
---|
15 | * explicitly disclaimed in individual files. |
---|
16 | * |
---|
17 | * Apple hereby grants permission to use, copy, modify, distribute, and |
---|
18 | * license this software and its documentation for any purpose, provided |
---|
19 | * that existing copyright notices are retained in all copies and that |
---|
20 | * this notice is included verbatim in any distributions. No written |
---|
21 | * agreement, license, or royalty fee is required for any of the |
---|
22 | * authorized uses. Modifications to this software may be copyrighted by |
---|
23 | * their authors and need not follow the licensing terms described here, |
---|
24 | * provided that the new terms are clearly indicated on the first page of |
---|
25 | * each file where they apply. |
---|
26 | * |
---|
27 | * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE SOFTWARE |
---|
28 | * BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR |
---|
29 | * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS |
---|
30 | * DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF APPLE OR THE |
---|
31 | * AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. APPLE, |
---|
32 | * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, |
---|
33 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
---|
34 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND |
---|
35 | * NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND |
---|
36 | * APPLE,THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE |
---|
37 | * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
---|
38 | * |
---|
39 | * GOVERNMENT USE: If you are acquiring this software on behalf of the |
---|
40 | * U.S. government, the Government shall have only "Restricted Rights" in |
---|
41 | * the software and related documentation as defined in the Federal |
---|
42 | * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are |
---|
43 | * acquiring the software on behalf of the Department of Defense, the |
---|
44 | * software shall be classified as "Commercial Computer Software" and the |
---|
45 | * Government shall have only "Restricted Rights" as defined in Clause |
---|
46 | * 252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the |
---|
47 | * authors grant the U.S. Government and others acting in its behalf |
---|
48 | * permission to use and distribute the software in accordance with the |
---|
49 | * terms specified in this license. |
---|
50 | * |
---|
51 | * RCS: @(#) $Id: tclMacOSXBundle.c,v 1.11 2007/04/23 20:46:13 das Exp $ |
---|
52 | */ |
---|
53 | |
---|
54 | #include "tclPort.h" |
---|
55 | |
---|
56 | #ifdef HAVE_COREFOUNDATION |
---|
57 | #include <CoreFoundation/CoreFoundation.h> |
---|
58 | #include <mach-o/dyld.h> |
---|
59 | #endif /* HAVE_COREFOUNDATION */ |
---|
60 | |
---|
61 | /* |
---|
62 | *---------------------------------------------------------------------- |
---|
63 | * |
---|
64 | * Tcl_MacOSXOpenBundleResources -- |
---|
65 | * |
---|
66 | * Given the bundle name for a shared library, this routine sets |
---|
67 | * libraryPath to the Resources/Scripts directory in the framework |
---|
68 | * package. If hasResourceFile is true, it will also open the main |
---|
69 | * resource file for the bundle. |
---|
70 | * |
---|
71 | * Results: |
---|
72 | * TCL_OK if the bundle could be opened, and the Scripts folder found. |
---|
73 | * TCL_ERROR otherwise. |
---|
74 | * |
---|
75 | * Side effects: |
---|
76 | * libraryVariableName may be set, and the resource file opened. |
---|
77 | * |
---|
78 | *---------------------------------------------------------------------- |
---|
79 | */ |
---|
80 | |
---|
81 | int |
---|
82 | Tcl_MacOSXOpenBundleResources( |
---|
83 | Tcl_Interp *interp, |
---|
84 | CONST char *bundleName, |
---|
85 | int hasResourceFile, |
---|
86 | int maxPathLen, |
---|
87 | char *libraryPath) |
---|
88 | { |
---|
89 | return Tcl_MacOSXOpenVersionedBundleResources(interp, bundleName, |
---|
90 | NULL, hasResourceFile, maxPathLen, libraryPath); |
---|
91 | } |
---|
92 | |
---|
93 | /* |
---|
94 | *---------------------------------------------------------------------- |
---|
95 | * |
---|
96 | * Tcl_MacOSXOpenVersionedBundleResources -- |
---|
97 | * |
---|
98 | * Given the bundle and version name for a shared library (version name |
---|
99 | * can be NULL to indicate latest version), this routine sets libraryPath |
---|
100 | * to the Resources/Scripts directory in the framework package. If |
---|
101 | * hasResourceFile is true, it will also open the main resource file for |
---|
102 | * the bundle. |
---|
103 | * |
---|
104 | * Results: |
---|
105 | * TCL_OK if the bundle could be opened, and the Scripts folder found. |
---|
106 | * TCL_ERROR otherwise. |
---|
107 | * |
---|
108 | * Side effects: |
---|
109 | * libraryVariableName may be set, and the resource file opened. |
---|
110 | * |
---|
111 | *---------------------------------------------------------------------- |
---|
112 | */ |
---|
113 | |
---|
114 | int |
---|
115 | Tcl_MacOSXOpenVersionedBundleResources( |
---|
116 | Tcl_Interp *interp, |
---|
117 | CONST char *bundleName, |
---|
118 | CONST char *bundleVersion, |
---|
119 | int hasResourceFile, |
---|
120 | int maxPathLen, |
---|
121 | char *libraryPath) |
---|
122 | { |
---|
123 | #ifdef HAVE_COREFOUNDATION |
---|
124 | CFBundleRef bundleRef; |
---|
125 | CFStringRef bundleNameRef; |
---|
126 | CFURLRef libURL; |
---|
127 | |
---|
128 | libraryPath[0] = '\0'; |
---|
129 | |
---|
130 | bundleNameRef = CFStringCreateWithCString(NULL, bundleName, |
---|
131 | kCFStringEncodingUTF8); |
---|
132 | |
---|
133 | bundleRef = CFBundleGetBundleWithIdentifier(bundleNameRef); |
---|
134 | CFRelease(bundleNameRef); |
---|
135 | |
---|
136 | if (bundleVersion && bundleRef) { |
---|
137 | /* |
---|
138 | * Create bundle from bundleVersion subdirectory of 'Versions'. |
---|
139 | */ |
---|
140 | |
---|
141 | CFBundleRef versionedBundleRef = NULL; |
---|
142 | CFURLRef versionedBundleURL = NULL; |
---|
143 | CFStringRef bundleVersionRef = CFStringCreateWithCString(NULL, |
---|
144 | bundleVersion, kCFStringEncodingUTF8); |
---|
145 | CFURLRef bundleURL = CFBundleCopyBundleURL(bundleRef); |
---|
146 | |
---|
147 | if (bundleURL) { |
---|
148 | CFStringRef bundleTailRef = CFURLCopyLastPathComponent(bundleURL); |
---|
149 | |
---|
150 | if (bundleTailRef) { |
---|
151 | if (CFStringCompare(bundleTailRef, bundleVersionRef, 0) == |
---|
152 | kCFCompareEqualTo) { |
---|
153 | versionedBundleRef = bundleRef; |
---|
154 | } |
---|
155 | CFRelease(bundleTailRef); |
---|
156 | } |
---|
157 | } |
---|
158 | |
---|
159 | if (bundleURL && !versionedBundleRef) { |
---|
160 | CFURLRef versURL = CFURLCreateCopyAppendingPathComponent(NULL, |
---|
161 | bundleURL, CFSTR("Versions"), TRUE); |
---|
162 | |
---|
163 | if (versURL) { |
---|
164 | versionedBundleURL = CFURLCreateCopyAppendingPathComponent( |
---|
165 | NULL, versURL, bundleVersionRef, TRUE); |
---|
166 | CFRelease(versURL); |
---|
167 | } |
---|
168 | CFRelease(bundleURL); |
---|
169 | } |
---|
170 | CFRelease(bundleVersionRef); |
---|
171 | if (versionedBundleURL) { |
---|
172 | versionedBundleRef = CFBundleCreate(NULL, versionedBundleURL); |
---|
173 | CFRelease(versionedBundleURL); |
---|
174 | } |
---|
175 | bundleRef = versionedBundleRef; |
---|
176 | } |
---|
177 | |
---|
178 | if (bundleRef) { |
---|
179 | if (hasResourceFile) { |
---|
180 | /* |
---|
181 | * Dynamically acquire address for CFBundleOpenBundleResourceMap |
---|
182 | * symbol, since it is only present in full CoreFoundation on Mac |
---|
183 | * OS X and not in CFLite on pure Darwin. |
---|
184 | */ |
---|
185 | |
---|
186 | static int initialized = FALSE; |
---|
187 | static short (*openresourcemap)(CFBundleRef) = NULL; |
---|
188 | |
---|
189 | if (!initialized) { |
---|
190 | NSSymbol nsSymbol = NULL; |
---|
191 | if (NSIsSymbolNameDefinedWithHint( |
---|
192 | "_CFBundleOpenBundleResourceMap", "CoreFoundation")) { |
---|
193 | nsSymbol = NSLookupAndBindSymbolWithHint( |
---|
194 | "_CFBundleOpenBundleResourceMap","CoreFoundation"); |
---|
195 | if (nsSymbol) { |
---|
196 | openresourcemap = NSAddressOfSymbol(nsSymbol); |
---|
197 | } |
---|
198 | } |
---|
199 | initialized = TRUE; |
---|
200 | } |
---|
201 | |
---|
202 | if (openresourcemap) { |
---|
203 | short refNum; |
---|
204 | |
---|
205 | refNum = openresourcemap(bundleRef); |
---|
206 | } |
---|
207 | } |
---|
208 | |
---|
209 | libURL = CFBundleCopyResourceURL(bundleRef, CFSTR("Scripts"), |
---|
210 | NULL, NULL); |
---|
211 | |
---|
212 | if (libURL) { |
---|
213 | /* |
---|
214 | * FIXME: This is a quick fix, it is probably not right for |
---|
215 | * internationalization. |
---|
216 | */ |
---|
217 | |
---|
218 | CFURLGetFileSystemRepresentation(libURL, TRUE, |
---|
219 | (unsigned char*) libraryPath, maxPathLen); |
---|
220 | CFRelease(libURL); |
---|
221 | } |
---|
222 | } |
---|
223 | |
---|
224 | if (libraryPath[0]) { |
---|
225 | return TCL_OK; |
---|
226 | } else { |
---|
227 | return TCL_ERROR; |
---|
228 | } |
---|
229 | #else /* HAVE_COREFOUNDATION */ |
---|
230 | return TCL_ERROR; |
---|
231 | #endif /* HAVE_COREFOUNDATION */ |
---|
232 | } |
---|
233 | |
---|
234 | /* |
---|
235 | * Local Variables: |
---|
236 | * mode: c |
---|
237 | * c-basic-offset: 4 |
---|
238 | * fill-column: 78 |
---|
239 | * End: |
---|
240 | */ |
---|