1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Mozilla Public License Version
6
* 1.1 (the "License"); you may not use this file except in compliance with
7
* the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/MPL/
10
* Software distributed under the License is distributed on an "AS IS" basis,
11
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
* for the specific language governing rights and limitations under the
15
* The Original Code is the Netscape Portable Runtime (NSPR).
17
* The Initial Developer of the Original Code is
18
* Netscape Communications Corporation.
19
* Portions created by the Initial Developer are Copyright (C) 1998-2000
20
* the Initial Developer. All Rights Reserved.
24
* Alternatively, the contents of this file may be used under the terms of
25
* either the GNU General Public License Version 2 or later (the "GPL"), or
26
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27
* in which case the provisions of the GPL or the LGPL are applicable instead
28
* of those above. If you wish to allow use of your version of this file only
29
* under the terms of either the GPL or the LGPL, and not to allow others to
30
* use your version of this file under the terms of the MPL, indicate your
31
* decision by deleting the provisions above and replace them with the notice
32
* and other provisions required by the GPL or the LGPL. If you do not delete
33
* the provisions above, a recipient may use your version of this file under
34
* the terms of any one of the MPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
43
#include <CodeFragments.h>
45
#include <Resources.h>
47
#include "IterateDirectory.h" /* MoreFiles */
49
#include "MacErrorHandling.h"
58
turds used to iterate through the directories looking
59
for the desired library.
62
struct GetSharedLibraryFilterProcData
68
CFragConnectionID outID;
72
typedef struct GetSharedLibraryFilterProcData GetSharedLibraryFilterProcData;
75
GetSharedLibraryFilterProc(const CInfoPBRec* const inCpb, Boolean* inWantQuit, void *inFilterData);
81
Unfortunately CFM doesn't support user specified loader paths,
82
so we emulate the behavior. Effectively this is a GetSharedLibrary
83
where the loader path is user defined.
87
NSGetSharedLibrary(Str255 inLibName, CFragConnectionID* outID, Ptr* outMainAddr)
94
GetSharedLibraryFilterProcData filterData;
98
filterData.outFound = false;
99
filterData.outID = (CFragConnectionID)(-1);
100
filterData.outAddress = NULL;
101
filterData.inName = inLibName;
103
freeCurLibPath = curLibPath = PR_GetLibraryPath();
105
if (curLibPath == NULL)
106
return (cfragNoLibraryErr);
108
tempErr = cfragNoLibraryErr;
112
endCurLibPath = PL_strchr(curLibPath, PR_PATH_SEPARATOR);
113
done = (endCurLibPath == NULL);
116
// we overload the first character of a path if it's :
117
// then we want to recursively search that path
118
// see if path should be recursive
119
if (*curLibPath == ':')
121
// ':' is an illegal character in the name of a file
122
// if we start any path with this, we want to allow
123
// search recursively
134
*endCurLibPath = '\0'; // NULL terminate the string
137
tempErr = ConvertUnixPathToFSSpec(curLibPath, &curFolder);
139
// now look in this directory
140
if (noErr == tempErr)
142
filterData.inRecursive = recursive;
143
FSpIterateDirectory(&curFolder, recursive ? 0 : 1, &GetSharedLibraryFilterProc, &filterData);
145
if (filterData.outFound)
147
*outID = filterData.outID;
148
*outMainAddr = filterData.outAddress;
154
tempErr = cfragNoLibraryErr;
158
curLibPath = endCurLibPath + 1; // skip to next path (past the '\0');
161
free(freeCurLibPath);
167
LibInPefContainer(const FSSpec* inSpec, StringPtr inName, UInt32* outCodeOffset, UInt32* outCodeLength);
171
GetSharedLibraryFilterProc
173
Callback to FSpIterateDirectory, finds a library with the name matching the
174
data in inFilterData (of type GetSharedLibraryFilterProcData). Forces a quit
175
when a match is found.
179
GetSharedLibraryFilterProc(const CInfoPBRec* const inCpb, Boolean* inWantQuit, void *inFilterData)
181
GetSharedLibraryFilterProcData* pFilterData = (GetSharedLibraryFilterProcData*) inFilterData;
183
if ((inCpb->hFileInfo.ioFlAttrib & (1 << ioDirFlg)) == 0)
194
// � fix-me do we really want to allow all 'APPL's' for in which to find this library?
195
switch (inCpb->hFileInfo.ioFlFndrInfo.fdType)
197
case kCFragLibraryFileType:
199
tempErr = FSMakeFSSpec(inCpb->hFileInfo.ioVRefNum, inCpb->hFileInfo.ioFlParID, inCpb->hFileInfo.ioNamePtr, &fragSpec);
201
// this shouldn't fail
202
if (noErr != tempErr)
207
// resolve an alias if this was one
208
tempErr = ResolveAliasFile(&fragSpec, true, &crap, &crap);
210
// if got here we have a shlb (or app-like shlb)
211
if (noErr != tempErr)
213
// probably couldn't resolve an alias
222
// see if this symbol is in this fragment
223
if (LibInPefContainer(&fragSpec, pFilterData->inName, &codeOffset, &codeLength))
224
tempErr = GetDiskFragment(&fragSpec, codeOffset, codeLength, fragSpec.name, kLoadCFrag, &pFilterData->outID, &pFilterData->outAddress, errName);
228
// stop if we found a library by that name
229
if (noErr == tempErr)
232
pFilterData->outFound = true;
233
pFilterData->outError = tempErr;
236
// FSpIterateDirectory will automagically call us for subsequent sub-dirs if necessary
243
Tell whether library inName is contained it the file pointed to by inSpec.
244
Return the codeOffset and codeLength information, for a subsequent
245
call to GetDiskFragment.
249
LibInPefContainer(const FSSpec* inSpec, StringPtr inName, UInt32* outCodeOffset, UInt32* outCodeLength)
252
CFragResourceHandle hCfrg;
253
CFragResourceMember* pCurItem;
257
// asume we didn't find it
260
// open the resource fork, if we can't bail
261
refNum = FSpOpenResFile(inSpec, fsRdPerm);
262
require(-1 != refNum, Exit);
264
// grab out the alias record, if it's not there bail
265
hCfrg = (CFragResourceHandle) Get1Resource(kCFragResourceType, kCFragResourceID);
266
require(NULL != hCfrg, CloseResourceAndExit);
268
HLock((Handle)hCfrg);
270
// get ptr to first item
271
pCurItem = &(*hCfrg)->firstMember;
272
for (curLibIndex = 0; curLibIndex < (*hCfrg)->memberCount; curLibIndex++)
274
// is this our library?
275
if ((pCurItem->name[0] == inName[0]) &&
276
(strncmp((char*) inName + 1, (char*) pCurItem->name + 1, PR_MIN(pCurItem->name[0], inName[0])) == 0))
278
*outCodeOffset = pCurItem->offset;
279
*outCodeLength = pCurItem->length;
284
pCurItem = (CFragResourceMember*) ((char*) pCurItem + pCurItem->memberSize);
287
HUnlock((Handle)hCfrg);
289
CloseResourceAndExit:
290
CloseResFile(refNum);
300
Workaround bug in CFM FindSymbol (in at least 7.5.5) where symbols with lengths
301
greater than 63 chars cause a "paramErr". We iterate through all symbols
302
in the library to find the desired symbol.
306
NSFindSymbol(CFragConnectionID inID, Str255 inSymName, Ptr* outMainAddr, CFragSymbolClass *outSymClass)
310
if (inSymName[0] > 63)
313
if there are greater than 63 characters in the
314
name, CFM FindSymbol fails, so let's iterate through all
315
of the symbols in the fragment and grab it
324
err = CountSymbols(inID, &symbolCount);
327
/* now iterate through all the symbols in the library */
328
/* per DTS the indices apparently go 0 to n-1 */
329
for (curIndex = 0; (curIndex <= symbolCount - 1 && !found); curIndex++)
331
err = GetIndSymbol(inID, curIndex, curSymName, outMainAddr, outSymClass);
332
if (noErr == err && curSymName[0] == inSymName[0] && !strncmp((char*)curSymName + 1, (char*)inSymName + 1, curSymName[0]))
334
/* found our symbol */
339
/* if we didn't find it set the error code so below it won't take this symbol */
341
err = cfragNoSymbolErr;
346
err = FindSymbol(inID, inSymName, outMainAddr, outSymClass);
356
/*-----------------------------------------------------------------
358
GetNamedFragmentOffsets
360
Get the offsets into the data fork of the named fragment,
361
by reading the 'cfrg' resoruce.
363
-----------------------------------------------------------------*/
364
OSErr GetNamedFragmentOffsets(const FSSpec *fileSpec, const char* fragmentName,
365
UInt32 *outOffset, UInt32 *outLength)
367
CFragResourceHandle cFragHandle;
371
fileRefNum = FSpOpenResFile(fileSpec, fsRdPerm);
373
if (err != noErr) return err;
375
cFragHandle = (CFragResourceHandle)Get1Resource(kCFragResourceType, kCFragResourceID);
382
/* nothing here moves memory, so no need to lock the handle */
384
err = cfragNoLibraryErr; /* in case of failure */
388
/* Now look for the named fragment */
389
if ((**cFragHandle).memberCount > 0)
391
CFragResourceMemberPtr memberPtr;
394
for ( i = 0, memberPtr = &(**cFragHandle).firstMember;
395
i < (**cFragHandle).memberCount;
396
i ++, memberPtr = (CFragResourceMemberPtr)((char *)memberPtr + memberPtr->memberSize))
398
char memberName[256];
399
UInt16 nameLen = PR_MIN(memberPtr->name[0], 255);
401
// avoid malloc here for speed
402
strncpy(memberName, (char *)&memberPtr->name[1], nameLen);
403
memberName[nameLen] = '\0';
405
// fragment names are case insensitive, so act like the system
406
if (PL_strcasecmp(memberName, fragmentName) == 0)
408
*outOffset = memberPtr->offset;
409
*outLength = memberPtr->length;
416
/* Resource handle will go away when the res fork is closed */
419
CloseResFile(fileRefNum);
424
/*-----------------------------------------------------------------
426
GetIndexedFragmentOffsets
428
Get the offsets into the data fork of the indexed fragment,
429
by reading the 'cfrg' resoruce.
431
-----------------------------------------------------------------*/
432
OSErr GetIndexedFragmentOffsets(const FSSpec *fileSpec, UInt32 fragmentIndex,
433
UInt32 *outOffset, UInt32 *outLength, char **outFragmentName)
435
CFragResourceHandle cFragHandle;
439
fileRefNum = FSpOpenResFile(fileSpec, fsRdPerm);
441
if (err != noErr) return err;
443
cFragHandle = (CFragResourceHandle)Get1Resource(kCFragResourceType, kCFragResourceID);
450
err = cfragNoLibraryErr; /* in case of failure */
453
*outFragmentName = NULL;
455
/* the CStrFromPStr mallocs, so might move memory */
456
HLock((Handle)cFragHandle);
458
/* Now look for the named fragment */
459
if ((**cFragHandle).memberCount > 0)
461
CFragResourceMemberPtr memberPtr;
464
for ( i = 0, memberPtr = &(**cFragHandle).firstMember;
465
i < (**cFragHandle).memberCount;
466
i ++, memberPtr = (CFragResourceMemberPtr)((char *)memberPtr + memberPtr->memberSize))
469
if (i == fragmentIndex)
472
CStrFromPStr(memberPtr->name, &fragmentStr);
473
if (!fragmentStr) /* test for allocation failure */
479
*outFragmentName = fragmentStr;
480
*outOffset = memberPtr->offset;
481
*outLength = memberPtr->length;
488
HUnlock((Handle)cFragHandle);
490
/* Resource handle will go away when the res fork is closed */
493
CloseResFile(fileRefNum);
498
/*-----------------------------------------------------------------
502
Load the named fragment from the specified file. Aliases must
503
have been resolved by this point.
505
-----------------------------------------------------------------*/
507
OSErr NSLoadNamedFragment(const FSSpec *fileSpec, const char* fragmentName, CFragConnectionID *outConnectionID)
509
UInt32 fragOffset, fragLength;
510
short fragNameLength;
516
err = GetNamedFragmentOffsets(fileSpec, fragmentName, &fragOffset, &fragLength);
517
if (err != noErr) return err;
519
// convert fragment name to pascal string
520
fragNameLength = strlen(fragmentName);
521
if (fragNameLength > 255)
522
fragNameLength = 255;
523
BlockMoveData(fragmentName, &fragName[1], fragNameLength);
524
fragName[0] = fragNameLength;
526
// Note that we pass the fragment name as the 4th param to GetDiskFragment.
527
// This value affects the ability of debuggers, and the Talkback system,
528
// to match code fragments with symbol files
529
err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName,
530
kLoadCFrag, outConnectionID, &main, errName);
536
/*-----------------------------------------------------------------
538
NSLoadIndexedFragment
540
Load the indexed fragment from the specified file. Aliases must
541
have been resolved by this point.
543
*outFragName is a malloc'd block containing the fragment name,
546
-----------------------------------------------------------------*/
548
OSErr NSLoadIndexedFragment(const FSSpec *fileSpec, PRUint32 fragmentIndex,
549
char** outFragName, CFragConnectionID *outConnectionID)
551
UInt32 fragOffset, fragLength;
552
char *fragNameBlock = NULL;
554
Str255 fragName = "\p";
560
err = GetIndexedFragmentOffsets(fileSpec, fragmentIndex, &fragOffset, &fragLength, &fragNameBlock);
561
if (err != noErr) return err;
565
UInt32 nameLen = strlen(fragNameBlock);
568
BlockMoveData(fragNameBlock, &fragName[1], nameLen);
569
fragName[0] = nameLen;
572
// Note that we pass the fragment name as the 4th param to GetDiskFragment.
573
// This value affects the ability of debuggers, and the Talkback system,
574
// to match code fragments with symbol files
575
err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName,
576
kLoadCFrag, outConnectionID, &main, errName);
583
*outFragName = fragNameBlock;