~ubuntu-branches/ubuntu/quantal/nspr/quantal-security

« back to all changes in this revision

Viewing changes to mozilla/nsprpub/pr/src/md/mac/macdll.c

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Sack
  • Date: 2009-08-10 11:34:26 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090810113426-3uv4diflrkcbdimm
Tags: 4.8-0ubuntu1
* New upstream release: 4.8 (LP: #387812)
* adjust patches to changed upstreanm codebase
  - update debian/patches/99_configure.patch
* update shlibs symbols to include new API elements
  - update debian/libnspr4-0d.symbols

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
4
 
 *
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/
9
 
 *
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
13
 
 * License.
14
 
 *
15
 
 * The Original Code is the Netscape Portable Runtime (NSPR).
16
 
 *
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.
21
 
 *
22
 
 * Contributor(s):
23
 
 *
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.
35
 
 *
36
 
 * ***** END LICENSE BLOCK ***** */
37
 
 
38
 
#include <string.h>
39
 
 
40
 
#include <Files.h>
41
 
#include <Errors.h>
42
 
#include <Folders.h>
43
 
#include <CodeFragments.h>
44
 
#include <Aliases.h>
45
 
#include <Resources.h>
46
 
 
47
 
#include "IterateDirectory.h"           /* MoreFiles */
48
 
 
49
 
#include "MacErrorHandling.h"
50
 
#include "macdll.h"
51
 
#include "mdmac.h"
52
 
#include "macio.h"
53
 
 
54
 
#include "primpl.h"
55
 
#include "plstr.h"
56
 
 
57
 
/*
58
 
        turds used to iterate through the directories looking
59
 
        for the desired library.
60
 
*/
61
 
 
62
 
struct GetSharedLibraryFilterProcData
63
 
{
64
 
        Boolean                         inRecursive;
65
 
        StringPtr                       inName;
66
 
        
67
 
        Boolean                         outFound;
68
 
        CFragConnectionID       outID;
69
 
        Ptr                                     outAddress;
70
 
        OSErr                           outError;
71
 
};
72
 
typedef struct GetSharedLibraryFilterProcData GetSharedLibraryFilterProcData;
73
 
 
74
 
static pascal void
75
 
GetSharedLibraryFilterProc(const CInfoPBRec* const inCpb, Boolean* inWantQuit, void *inFilterData);
76
 
 
77
 
 
78
 
/*
79
 
        NSGetSharedLibrary
80
 
        
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.
84
 
*/
85
 
 
86
 
OSErr
87
 
NSGetSharedLibrary(Str255 inLibName, CFragConnectionID* outID, Ptr* outMainAddr)
88
 
{
89
 
        char*           curLibPath;
90
 
        char*           freeCurLibPath;
91
 
        OSErr           tempErr;
92
 
        Boolean         recursive;
93
 
        FSSpec          curFolder;      
94
 
        GetSharedLibraryFilterProcData filterData;
95
 
        char            *endCurLibPath;
96
 
        Boolean         done;
97
 
        
98
 
        filterData.outFound = false;
99
 
        filterData.outID = (CFragConnectionID)(-1);
100
 
        filterData.outAddress = NULL;
101
 
        filterData.inName = inLibName;
102
 
                
103
 
        freeCurLibPath = curLibPath = PR_GetLibraryPath();
104
 
        
105
 
        if (curLibPath == NULL)
106
 
                return (cfragNoLibraryErr);
107
 
        
108
 
        tempErr = cfragNoLibraryErr;
109
 
        
110
 
        do
111
 
        {
112
 
                endCurLibPath = PL_strchr(curLibPath, PR_PATH_SEPARATOR);
113
 
                done = (endCurLibPath == NULL);
114
 
 
115
 
#if 0
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 == ':')
120
 
                {
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
124
 
                        curLibPath++;
125
 
                        recursive = true;
126
 
                }
127
 
                else
128
 
#endif
129
 
                {
130
 
                        recursive = false;
131
 
                }
132
 
                
133
 
                if (!done)
134
 
                        *endCurLibPath = '\0';  // NULL terminate the string
135
 
                
136
 
                // convert to FSSpec
137
 
                tempErr = ConvertUnixPathToFSSpec(curLibPath, &curFolder);      
138
 
 
139
 
                // now look in this directory
140
 
                if (noErr == tempErr)
141
 
                {
142
 
                        filterData.inRecursive = recursive;
143
 
                        FSpIterateDirectory(&curFolder, recursive ? 0 : 1, &GetSharedLibraryFilterProc, &filterData);
144
 
                        
145
 
                        if (filterData.outFound)
146
 
                        {
147
 
                                *outID = filterData.outID;
148
 
                                *outMainAddr = filterData.outAddress;
149
 
                                tempErr = noErr;
150
 
                                break;
151
 
                        }
152
 
                        else 
153
 
                        {
154
 
                                tempErr = cfragNoLibraryErr;
155
 
                        }
156
 
                }
157
 
                
158
 
                curLibPath = endCurLibPath + 1; // skip to next path (past the '\0');
159
 
        } while (!done);
160
 
 
161
 
        free(freeCurLibPath);
162
 
        return (tempErr);
163
 
}
164
 
 
165
 
 
166
 
static Boolean
167
 
LibInPefContainer(const FSSpec* inSpec, StringPtr inName, UInt32* outCodeOffset, UInt32* outCodeLength);
168
 
 
169
 
 
170
 
/*
171
 
        GetSharedLibraryFilterProc
172
 
        
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.
176
 
*/
177
 
 
178
 
static pascal void
179
 
GetSharedLibraryFilterProc(const CInfoPBRec* const inCpb, Boolean* inWantQuit, void *inFilterData)
180
 
{
181
 
        GetSharedLibraryFilterProcData* pFilterData = (GetSharedLibraryFilterProcData*) inFilterData;
182
 
 
183
 
        if ((inCpb->hFileInfo.ioFlAttrib & (1 << ioDirFlg)) == 0)
184
 
        {
185
 
                FSSpec  fragSpec;
186
 
                OSErr   tempErr;
187
 
                Str255  errName;
188
 
                Boolean crap;
189
 
                UInt32  codeOffset;
190
 
                UInt32  codeLength;
191
 
                
192
 
                // it's a file
193
 
                
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)
196
 
                {
197
 
                        case kCFragLibraryFileType:
198
 
                        case 'APPL':
199
 
                                tempErr = FSMakeFSSpec(inCpb->hFileInfo.ioVRefNum, inCpb->hFileInfo.ioFlParID, inCpb->hFileInfo.ioNamePtr, &fragSpec);
200
 
 
201
 
                                // this shouldn't fail
202
 
                                if (noErr != tempErr)
203
 
                                {
204
 
                                        return;
205
 
                                }
206
 
                                
207
 
                                // resolve an alias if this was one
208
 
                                tempErr = ResolveAliasFile(&fragSpec, true, &crap, &crap);
209
 
 
210
 
                                // if got here we have a shlb (or app-like shlb)
211
 
                                if (noErr != tempErr)
212
 
                                {
213
 
                                        // probably couldn't resolve an alias
214
 
                                        return;
215
 
                                }
216
 
                
217
 
                                break;
218
 
                        default:
219
 
                                return;
220
 
                }
221
 
        
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);
225
 
                else
226
 
                        return;
227
 
                                
228
 
                // stop if we found a library by that name
229
 
                if (noErr == tempErr)
230
 
                {                       
231
 
                        *inWantQuit = true;
232
 
                        pFilterData->outFound = true;
233
 
                        pFilterData->outError = tempErr;
234
 
                }
235
 
        }
236
 
        // FSpIterateDirectory will automagically call us for subsequent sub-dirs if necessary
237
 
}
238
 
 
239
 
 
240
 
/*
241
 
        LibInPefContainer
242
 
        
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.
246
 
*/
247
 
 
248
 
static Boolean
249
 
LibInPefContainer(const FSSpec* inSpec, StringPtr inName, UInt32* outCodeOffset, UInt32* outCodeLength)
250
 
{
251
 
        short                                   refNum;
252
 
        CFragResourceHandle             hCfrg;
253
 
        CFragResourceMember*    pCurItem;
254
 
        UInt32                                  curLibIndex;
255
 
        Boolean                                 found;
256
 
        
257
 
        // asume we didn't find it
258
 
        found = false;
259
 
        
260
 
        // open the resource fork, if we can't bail
261
 
        refNum = FSpOpenResFile(inSpec, fsRdPerm);
262
 
        require(-1 != refNum, Exit);
263
 
        
264
 
        // grab out the alias record, if it's not there bail
265
 
        hCfrg = (CFragResourceHandle) Get1Resource(kCFragResourceType, kCFragResourceID);
266
 
        require(NULL != hCfrg, CloseResourceAndExit);
267
 
        
268
 
        HLock((Handle)hCfrg);
269
 
        
270
 
        // get ptr to first item
271
 
        pCurItem = &(*hCfrg)->firstMember;
272
 
        for (curLibIndex = 0; curLibIndex < (*hCfrg)->memberCount; curLibIndex++)
273
 
        {
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))
277
 
                {
278
 
                        *outCodeOffset = pCurItem->offset;
279
 
                        *outCodeLength = pCurItem->length;
280
 
                        found = true;
281
 
                }
282
 
                
283
 
                // skip to next one
284
 
                pCurItem = (CFragResourceMember*) ((char*) pCurItem + pCurItem->memberSize);                                            
285
 
        }
286
 
        
287
 
        HUnlock((Handle)hCfrg);
288
 
        
289
 
CloseResourceAndExit:
290
 
        CloseResFile(refNum);
291
 
Exit:
292
 
        return (found);
293
 
 
294
 
}
295
 
 
296
 
 
297
 
/*
298
 
        NSFindSymbol
299
 
        
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.
303
 
*/
304
 
 
305
 
OSErr
306
 
NSFindSymbol(CFragConnectionID inID, Str255 inSymName, Ptr*     outMainAddr, CFragSymbolClass *outSymClass)
307
 
{
308
 
        OSErr   err;
309
 
        
310
 
        if (inSymName[0] > 63)
311
 
        {
312
 
                /* 
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 
316
 
                        that way.
317
 
                */
318
 
                long    symbolCount;
319
 
                Str255  curSymName;
320
 
                long    curIndex;
321
 
                Boolean found;
322
 
                
323
 
                found = false;
324
 
                err = CountSymbols(inID, &symbolCount);
325
 
                if (noErr == err)
326
 
                {
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++)
330
 
                        {
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]))
333
 
                                {
334
 
                                        /* found our symbol */
335
 
                                        found = true;
336
 
                                }
337
 
                        }
338
 
                        
339
 
                        /* if we didn't find it set the error code so below it won't take this symbol */
340
 
                        if (!found)
341
 
                                err = cfragNoSymbolErr;
342
 
                }       
343
 
        }
344
 
        else
345
 
        {       
346
 
                err = FindSymbol(inID, inSymName, outMainAddr, outSymClass);
347
 
        }
348
 
        
349
 
        return (err);
350
 
}
351
 
 
352
 
 
353
 
#pragma mark -
354
 
 
355
 
 
356
 
/*-----------------------------------------------------------------
357
 
 
358
 
        GetNamedFragmentOffsets
359
 
 
360
 
        Get the offsets into the data fork of the named fragment,
361
 
        by reading the 'cfrg' resoruce.
362
 
 
363
 
-----------------------------------------------------------------*/
364
 
OSErr GetNamedFragmentOffsets(const FSSpec *fileSpec, const char* fragmentName,
365
 
                                                        UInt32 *outOffset, UInt32 *outLength)
366
 
{
367
 
        CFragResourceHandle             cFragHandle;
368
 
        short                                                                   fileRefNum;
369
 
        OSErr                                                                   err = noErr;
370
 
        
371
 
        fileRefNum = FSpOpenResFile(fileSpec, fsRdPerm);
372
 
        err = ResError();
373
 
        if (err != noErr) return err;
374
 
 
375
 
        cFragHandle = (CFragResourceHandle)Get1Resource(kCFragResourceType, kCFragResourceID);  
376
 
        if (!cFragHandle)
377
 
        {
378
 
                err = resNotFound;
379
 
                goto done;
380
 
        }
381
 
        
382
 
        /* nothing here moves memory, so no need to lock the handle */
383
 
        
384
 
        err = cfragNoLibraryErr;                        /* in case of failure */
385
 
        *outOffset = 0;
386
 
        *outLength = 0;
387
 
        
388
 
        /* Now look for the named fragment */
389
 
        if ((**cFragHandle).memberCount > 0)
390
 
        {
391
 
                CFragResourceMemberPtr  memberPtr;
392
 
                UInt16                                                                  i;
393
 
                
394
 
                for (   i = 0, memberPtr = &(**cFragHandle).firstMember;
395
 
                                        i < (**cFragHandle).memberCount;
396
 
                                        i ++, memberPtr = (CFragResourceMemberPtr)((char *)memberPtr + memberPtr->memberSize))
397
 
                {
398
 
                        char            memberName[256];
399
 
                        UInt16  nameLen = PR_MIN(memberPtr->name[0], 255);
400
 
                
401
 
                        // avoid malloc here for speed
402
 
                        strncpy(memberName, (char *)&memberPtr->name[1], nameLen);
403
 
                        memberName[nameLen] = '\0';
404
 
                
405
 
                        // fragment names are case insensitive, so act like the system
406
 
                        if (PL_strcasecmp(memberName, fragmentName) == 0)
407
 
                        {
408
 
                                *outOffset = memberPtr->offset;
409
 
                                *outLength = memberPtr->length;
410
 
                                err = noErr;
411
 
                                break;
412
 
                        }
413
 
                }
414
 
        }
415
 
        
416
 
        /* Resource handle will go away when the res fork is closed */
417
 
        
418
 
done:
419
 
        CloseResFile(fileRefNum);
420
 
        return err;
421
 
}
422
 
 
423
 
 
424
 
/*-----------------------------------------------------------------
425
 
 
426
 
        GetIndexedFragmentOffsets
427
 
        
428
 
        Get the offsets into the data fork of the indexed fragment,
429
 
        by reading the 'cfrg' resoruce.
430
 
 
431
 
-----------------------------------------------------------------*/
432
 
OSErr GetIndexedFragmentOffsets(const FSSpec *fileSpec, UInt32 fragmentIndex,
433
 
                                                        UInt32 *outOffset, UInt32 *outLength, char **outFragmentName)
434
 
{
435
 
        CFragResourceHandle             cFragHandle;
436
 
        short                                                                   fileRefNum;
437
 
        OSErr                                                                   err = noErr;
438
 
        
439
 
        fileRefNum = FSpOpenResFile(fileSpec, fsRdPerm);
440
 
        err = ResError();
441
 
        if (err != noErr) return err;
442
 
 
443
 
        cFragHandle = (CFragResourceHandle)Get1Resource(kCFragResourceType, kCFragResourceID);  
444
 
        if (!cFragHandle)
445
 
        {
446
 
                err = resNotFound;
447
 
                goto done;
448
 
        }
449
 
                
450
 
        err = cfragNoLibraryErr;                        /* in case of failure */
451
 
        *outOffset = 0;
452
 
        *outLength = 0;
453
 
        *outFragmentName = NULL;
454
 
        
455
 
        /* the CStrFromPStr mallocs, so might move memory */
456
 
        HLock((Handle)cFragHandle);
457
 
        
458
 
        /* Now look for the named fragment */
459
 
        if ((**cFragHandle).memberCount > 0)
460
 
        {
461
 
                CFragResourceMemberPtr  memberPtr;
462
 
                UInt16                                                                  i;
463
 
                
464
 
                for (   i = 0, memberPtr = &(**cFragHandle).firstMember;
465
 
                                        i < (**cFragHandle).memberCount;
466
 
                                        i ++, memberPtr = (CFragResourceMemberPtr)((char *)memberPtr + memberPtr->memberSize))
467
 
                {
468
 
                        
469
 
                        if (i == fragmentIndex)
470
 
                        {
471
 
                                char    *fragmentStr;
472
 
                                CStrFromPStr(memberPtr->name, &fragmentStr);
473
 
                                if (!fragmentStr)               /* test for allocation failure */
474
 
                                {
475
 
                                        err = memFullErr;
476
 
                                        break;
477
 
                                }
478
 
                                
479
 
                                *outFragmentName = fragmentStr;
480
 
                                *outOffset = memberPtr->offset;
481
 
                                *outLength = memberPtr->length;
482
 
                                err = noErr;
483
 
                                break;
484
 
                        }
485
 
                }
486
 
        }
487
 
        
488
 
        HUnlock((Handle)cFragHandle);
489
 
        
490
 
        /* Resource handle will go away when the res fork is closed */
491
 
        
492
 
done:
493
 
        CloseResFile(fileRefNum);
494
 
        return err;
495
 
}
496
 
 
497
 
 
498
 
/*-----------------------------------------------------------------
499
 
 
500
 
        NSLoadNamedFragment
501
 
        
502
 
        Load the named fragment from the specified file. Aliases must
503
 
        have been resolved by this point.
504
 
 
505
 
-----------------------------------------------------------------*/
506
 
 
507
 
OSErr NSLoadNamedFragment(const FSSpec *fileSpec, const char* fragmentName, CFragConnectionID *outConnectionID)
508
 
{
509
 
    UInt32      fragOffset, fragLength;
510
 
    short       fragNameLength;
511
 
    Ptr             main;
512
 
    Str255      fragName;
513
 
    Str255      errName;
514
 
    OSErr           err;
515
 
    
516
 
    err = GetNamedFragmentOffsets(fileSpec, fragmentName, &fragOffset, &fragLength);
517
 
    if (err != noErr) return err;
518
 
    
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;
525
 
    
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);
531
 
 
532
 
    return err;
533
 
}
534
 
 
535
 
 
536
 
/*-----------------------------------------------------------------
537
 
 
538
 
        NSLoadIndexedFragment
539
 
        
540
 
        Load the indexed fragment from the specified file. Aliases must
541
 
        have been resolved by this point.
542
 
        
543
 
        *outFragName is a malloc'd block containing the fragment name,
544
 
        if returning noErr.
545
 
 
546
 
-----------------------------------------------------------------*/
547
 
 
548
 
OSErr NSLoadIndexedFragment(const FSSpec *fileSpec, PRUint32 fragmentIndex,
549
 
                            char** outFragName, CFragConnectionID *outConnectionID)
550
 
{
551
 
    UInt32      fragOffset, fragLength;
552
 
    char        *fragNameBlock = NULL;
553
 
    Ptr         main;
554
 
    Str255      fragName = "\p";
555
 
    Str255      errName;
556
 
    OSErr       err;
557
 
 
558
 
    *outFragName = NULL;
559
 
    
560
 
    err = GetIndexedFragmentOffsets(fileSpec, fragmentIndex, &fragOffset, &fragLength, &fragNameBlock);
561
 
    if (err != noErr) return err;
562
 
                
563
 
    if (fragNameBlock)
564
 
    {
565
 
        UInt32 nameLen = strlen(fragNameBlock);
566
 
        if (nameLen > 63)
567
 
            nameLen = 63;
568
 
        BlockMoveData(fragNameBlock, &fragName[1], nameLen);
569
 
        fragName[0] = nameLen;
570
 
    }
571
 
 
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);
577
 
    if (err != noErr)
578
 
    {
579
 
        free(fragNameBlock);
580
 
        return err;
581
 
    }
582
 
 
583
 
    *outFragName = fragNameBlock;
584
 
    return noErr;
585
 
}
586
 
 
587