~ubuntu-branches/ubuntu/saucy/nspr/saucy-updates

« back to all changes in this revision

Viewing changes to mozilla/nsprpub/pr/src/md/mac/macio.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 <Types.h>
41
 
#include <Files.h>
42
 
#include <Devices.h>
43
 
#include <Folders.h>
44
 
#include <Errors.h>
45
 
#include <Resources.h>
46
 
#include <Processes.h>
47
 
#include <TextUtils.h>
48
 
 
49
 
#include <fcntl.h>
50
 
 
51
 
#include "FullPath.h"           /* MoreFiles */
52
 
 
53
 
#include "primpl.h"
54
 
#include "MacErrorHandling.h"
55
 
#include "mdmac.h"
56
 
 
57
 
#include "macio.h"
58
 
 
59
 
/* forward declarations */
60
 
extern unsigned long gJanuaryFirst1970Seconds;
61
 
 
62
 
extern void WaitOnThisThread(PRThread *thread, PRIntervalTime timeout);
63
 
extern void DoneWaitingOnThisThread(PRThread *thread);
64
 
extern void AsyncNotify(PRThread *thread);
65
 
 
66
 
 
67
 
/* PB for Read and Write */
68
 
struct ExtendedParamBlock {
69
 
        /* PB must be first so that the file system can get the right data. */
70
 
        ParamBlockRec   pb;
71
 
        PRThread                *thread;
72
 
};
73
 
typedef struct ExtendedParamBlock ExtendedParamBlock;
74
 
 
75
 
 
76
 
/* XXX Not done yet for 68K */
77
 
/* I/O completion routne for _MD_READ and _MD_WRITE */
78
 
static void AsyncIOCompletion (ExtendedParamBlock *pbAsyncPtr)
79
 
{
80
 
    _PRCPU *cpu = _PR_MD_CURRENT_CPU();
81
 
    PRThread *thread = pbAsyncPtr->thread;    
82
 
    PRIntn is;
83
 
    
84
 
    if (_PR_MD_GET_INTSOFF()) {
85
 
        thread->md.missedIONotify = PR_TRUE;
86
 
        cpu->u.missed[cpu->where] |= _PR_MISSED_IO;
87
 
    } else {
88
 
        _PR_INTSOFF(is);
89
 
 
90
 
        thread->md.osErrCode = noErr;
91
 
        DoneWaitingOnThisThread(thread);
92
 
 
93
 
        _PR_FAST_INTSON(is);
94
 
    }
95
 
 
96
 
    SignalIdleSemaphore();
97
 
}
98
 
 
99
 
void  _MD_SetError(OSErr oserror)
100
 
{
101
 
    PRErrorCode code;
102
 
 
103
 
    switch (oserror) {
104
 
      case memFullErr:
105
 
        code = PR_OUT_OF_MEMORY_ERROR;
106
 
        break;
107
 
      case fnfErr:
108
 
        code = PR_FILE_NOT_FOUND_ERROR;
109
 
        break;
110
 
      case dupFNErr:
111
 
        code = PR_FILE_EXISTS_ERROR;
112
 
        break;
113
 
      case ioErr:
114
 
        code = PR_IO_ERROR;
115
 
        break;
116
 
      case nsvErr:
117
 
      case wrgVolTypErr:
118
 
        code = PR_INVALID_DEVICE_STATE_ERROR;
119
 
        break;
120
 
      case bdNamErr:
121
 
      case fsRnErr:
122
 
        code = PR_NAME_TOO_LONG_ERROR;
123
 
        break;
124
 
      case tmfoErr:
125
 
        code = PR_INSUFFICIENT_RESOURCES_ERROR;
126
 
        break;
127
 
      case opWrErr:
128
 
      case wrPermErr:
129
 
      case permErr:
130
 
      case afpAccessDenied:
131
 
        code = PR_NO_ACCESS_RIGHTS_ERROR;
132
 
        break;
133
 
      case afpObjectTypeErr:
134
 
        code = PR_DIRECTORY_LOOKUP_ERROR;
135
 
        break;
136
 
      case wPrErr:
137
 
      case vLckdErr:
138
 
        code = PR_DEVICE_IS_LOCKED_ERROR;
139
 
        break;
140
 
      case fLckdErr:
141
 
        code = PR_FILE_IS_LOCKED_ERROR;
142
 
        break;
143
 
      case dirNFErr:
144
 
        code = PR_NOT_DIRECTORY_ERROR;
145
 
        break;
146
 
      case dirFulErr:
147
 
        code = PR_MAX_DIRECTORY_ENTRIES_ERROR;
148
 
        break;
149
 
      case dskFulErr:
150
 
        code = PR_NO_DEVICE_SPACE_ERROR;
151
 
        break;
152
 
      case rfNumErr:
153
 
      case fnOpnErr:
154
 
        code = PR_BAD_DESCRIPTOR_ERROR;
155
 
        break;
156
 
      case eofErr:
157
 
        code = PR_END_OF_FILE_ERROR;
158
 
        break;
159
 
      case posErr:
160
 
      case gfpErr:
161
 
        code = PR_FILE_SEEK_ERROR;
162
 
        break;
163
 
      case fBsyErr:
164
 
        code = PR_FILE_IS_BUSY_ERROR;
165
 
        break;
166
 
      case extFSErr:
167
 
        code = PR_REMOTE_FILE_ERROR;
168
 
        break;
169
 
      case abortErr:
170
 
        code = PR_PENDING_INTERRUPT_ERROR;
171
 
        break;
172
 
      case paramErr:
173
 
        code = PR_INVALID_ARGUMENT_ERROR;
174
 
        break;
175
 
      case unimpErr:
176
 
        code = PR_NOT_IMPLEMENTED_ERROR;
177
 
        break;
178
 
    }
179
 
 
180
 
    PR_SetError(code, oserror);
181
 
}
182
 
 
183
 
void _MD_IOInterrupt(void)
184
 
{
185
 
    PRCList *qp;
186
 
    PRThread *thread, *me = _PR_MD_CURRENT_THREAD();
187
 
 
188
 
    PR_ASSERT(_PR_MD_GET_INTSOFF() != 0);
189
 
 
190
 
    _PR_SLEEPQ_LOCK(me->cpu);
191
 
    qp = _PR_PAUSEQ(me->cpu).next;
192
 
    while (qp != &_PR_PAUSEQ(me->cpu)) {
193
 
 
194
 
                thread = _PR_THREAD_PTR(qp);
195
 
                PR_ASSERT(thread->flags & _PR_ON_PAUSEQ);
196
 
 
197
 
                qp = qp->next;
198
 
                
199
 
                if (thread->md.missedIONotify) {
200
 
                        thread->md.missedIONotify = PR_FALSE;
201
 
                        DoneWaitingOnThisThread(thread);
202
 
                }
203
 
 
204
 
                if (thread->md.missedAsyncNotify) {
205
 
                        thread->md.missedAsyncNotify = PR_FALSE;
206
 
                        AsyncNotify(thread);
207
 
                }
208
 
    }
209
 
    qp = _PR_SLEEPQ(me->cpu).next;
210
 
    while (qp != &_PR_SLEEPQ(me->cpu)) {
211
 
 
212
 
                thread = _PR_THREAD_PTR(qp);
213
 
                PR_ASSERT(thread->flags & _PR_ON_SLEEPQ);
214
 
 
215
 
                qp = qp->next;
216
 
                
217
 
                if (thread->md.missedIONotify) {
218
 
                        thread->md.missedIONotify = PR_FALSE;
219
 
                        DoneWaitingOnThisThread(thread);
220
 
                }
221
 
 
222
 
                if (thread->md.missedAsyncNotify) {
223
 
                        thread->md.missedAsyncNotify = PR_FALSE;
224
 
                        AsyncNotify(thread);
225
 
                }
226
 
    }
227
 
        _PR_SLEEPQ_UNLOCK(thread->cpu);
228
 
}
229
 
 
230
 
/* 
231
 
** All PR_read and PR_Write calls are synchronous from caller's perspective.
232
 
** They are internally made asynchronous calls.  This gives cpu to other
233
 
** user threads while the async io is in progress.
234
 
*/
235
 
PRInt32 ReadWriteProc(PRFileDesc *fd, void *buf, PRUint32 bytes, IOOperation op)
236
 
{
237
 
        PRInt32 refNum = fd->secret->md.osfd;
238
 
        OSErr                           err;
239
 
        ExtendedParamBlock      pbAsync;
240
 
        PRThread                        *me = _PR_MD_CURRENT_THREAD();
241
 
        _PRCPU *cpu = _PR_MD_CURRENT_CPU();
242
 
 
243
 
        /* quick hack to allow PR_fprintf, etc to work with stderr, stdin, stdout */
244
 
        /* note, if a user chooses "seek" or the like as an operation in another function */
245
 
        /* this will not work */
246
 
        if (refNum >= 0 && refNum < 3)
247
 
        {
248
 
                switch (refNum)
249
 
                {
250
 
                                case 0:
251
 
                                        /* stdin - not on a Mac for now */
252
 
                                        err = paramErr;
253
 
                                        goto ErrorExit;
254
 
                                        break;
255
 
                                case 1: /* stdout */
256
 
                                case 2: /* stderr */
257
 
                                        puts(buf);
258
 
                                        break;
259
 
                }
260
 
                
261
 
                return (bytes);
262
 
        }
263
 
        else
264
 
        {
265
 
                static IOCompletionUPP  sCompletionUPP = NULL;
266
 
                
267
 
                PRBool  doingAsync = PR_FALSE;
268
 
                
269
 
                /* allocate the callback Universal Procedure Pointer (UPP). This actually allocates
270
 
                   a 32 byte Ptr in the heap, so only do this once
271
 
                */
272
 
                if (!sCompletionUPP)
273
 
                        sCompletionUPP = NewIOCompletionUPP((IOCompletionProcPtr)&AsyncIOCompletion);
274
 
                        
275
 
                /* grab the thread so we know which one to post to at completion */
276
 
                pbAsync.thread  = me;
277
 
 
278
 
                pbAsync.pb.ioParam.ioCompletion = sCompletionUPP;
279
 
                pbAsync.pb.ioParam.ioResult             = noErr;
280
 
                pbAsync.pb.ioParam.ioRefNum             = refNum;
281
 
                pbAsync.pb.ioParam.ioBuffer             = buf;
282
 
                pbAsync.pb.ioParam.ioReqCount   = bytes;
283
 
                pbAsync.pb.ioParam.ioPosMode    = fsAtMark;
284
 
                pbAsync.pb.ioParam.ioPosOffset  = 0;
285
 
 
286
 
                /* 
287
 
                ** Issue the async read call and wait for the io semaphore associated
288
 
                ** with this thread.
289
 
                ** Async file system calls *never* return error values, so ignore their
290
 
                ** results (see <http://developer.apple.com/technotes/fl/fl_515.html>);
291
 
                ** the completion routine is always called.
292
 
                */
293
 
                me->io_fd = refNum;
294
 
                me->md.osErrCode = noErr;
295
 
                if (op == READ_ASYNC)
296
 
                {
297
 
                        /*
298
 
                        **  Skanky optimization so that reads < 20K are actually done synchronously
299
 
                        **  to optimize performance on small reads (e.g. registry reads on startup)
300
 
                        */
301
 
                        if ( bytes > 20480L )
302
 
                        {
303
 
                                doingAsync = PR_TRUE;
304
 
                                me->io_pending = PR_TRUE;
305
 
                                
306
 
                                (void)PBReadAsync(&pbAsync.pb);
307
 
                        }
308
 
                        else
309
 
                        {
310
 
                                pbAsync.pb.ioParam.ioCompletion = NULL;
311
 
                                me->io_pending = PR_FALSE;
312
 
                                
313
 
                                err = PBReadSync(&pbAsync.pb);
314
 
                                if (err != noErr && err != eofErr)
315
 
                                        goto ErrorExit;
316
 
                        }
317
 
                }
318
 
                else
319
 
                {
320
 
                        doingAsync = PR_TRUE;
321
 
                        me->io_pending = PR_TRUE;
322
 
 
323
 
                        /* writes are currently always async */
324
 
                        (void)PBWriteAsync(&pbAsync.pb);
325
 
                }
326
 
                
327
 
                if (doingAsync) {
328
 
                        WaitOnThisThread(me, PR_INTERVAL_NO_TIMEOUT);
329
 
                }
330
 
        }
331
 
        
332
 
        err = me->md.osErrCode;
333
 
        if (err != noErr)
334
 
                goto ErrorExit;
335
 
 
336
 
        err = pbAsync.pb.ioParam.ioResult;
337
 
        if (err != noErr && err != eofErr)
338
 
                goto ErrorExit;
339
 
        
340
 
        return pbAsync.pb.ioParam.ioActCount;
341
 
 
342
 
ErrorExit:
343
 
        me->md.osErrCode = err;
344
 
        _MD_SetError(err);
345
 
        return -1;
346
 
}
347
 
 
348
 
/*
349
 
Special WriteSyncProc for logging only.  IO occurs synchronously.  Otherwise,
350
 
logging internal to NSPR causes ReadWriteProc above to recurse on PR_WaitSem logging.
351
 
*/
352
 
PRInt32 WriteSyncProc(PRFileDesc *fd, void *buf, PRUint32 bytes)
353
 
{
354
 
        PRInt32                         refNum = fd->secret->md.osfd;
355
 
        OSErr                           err;
356
 
        ParamBlockRec           pb;
357
 
        PRThread                        *me = _PR_MD_CURRENT_THREAD();
358
 
        
359
 
        if (refNum >= 0 && refNum < 3)
360
 
        {
361
 
                PR_ASSERT(FALSE);       /* writing to these is hazardous to a Mac's health (refNum 2 is the system file) */
362
 
                err = paramErr;
363
 
                goto ErrorExit;
364
 
        }
365
 
 
366
 
        pb.ioParam.ioCompletion = NULL;
367
 
        pb.ioParam.ioResult             = noErr;
368
 
        pb.ioParam.ioRefNum             = refNum;
369
 
        pb.ioParam.ioBuffer             = buf;
370
 
        pb.ioParam.ioReqCount   = bytes;
371
 
        pb.ioParam.ioPosMode    = fsAtMark;
372
 
        pb.ioParam.ioPosOffset  = 0;
373
 
 
374
 
        err = PBWriteSync(&pb);
375
 
 
376
 
        if (err != noErr)
377
 
                goto ErrorExit;
378
 
        else
379
 
                return pb.ioParam.ioActCount;
380
 
 
381
 
ErrorExit:
382
 
        me->md.osErrCode = err;
383
 
        _MD_SetError(err);
384
 
    return -1;
385
 
}
386
 
 
387
 
/* File I/O functions called by PR I/O routines */
388
 
PRInt32 _MD_Open(const char *path, PRIntn flags, int mode)
389
 
{
390
 
// Macintosh doesn't really have mode bits, just drop them
391
 
#pragma unused (mode)
392
 
 
393
 
        OSErr                           err;
394
 
        HParamBlockRec          hpb;
395
 
        ParamBlockRec           pb;
396
 
        char                            *macFileName = NULL;
397
 
        Str255                          pascalName;
398
 
        PRInt8                          perm;
399
 
 
400
 
    err = ConvertUnixPathToMacPath(path, &macFileName);
401
 
        
402
 
        if (err != noErr)
403
 
                goto ErrorExit;
404
 
 
405
 
        hpb.ioParam.ioCompletion        = NULL;
406
 
        PStrFromCStr(macFileName, pascalName);
407
 
        PR_DELETE(macFileName);
408
 
        hpb.ioParam.ioNamePtr   = pascalName;
409
 
        hpb.ioParam.ioVRefNum   = 0;
410
 
        hpb.ioParam.ioVersNum   = 0;
411
 
        hpb.fileParam.ioDirID   = 0;
412
 
 
413
 
        if (flags & PR_RDWR)
414
 
                perm = fsRdWrPerm;
415
 
        else if (flags & PR_WRONLY)
416
 
                perm = fsWrPerm;
417
 
        else
418
 
                perm = fsRdPerm;        
419
 
        hpb.ioParam.ioPermssn   = perm;
420
 
 
421
 
        
422
 
    if (flags & PR_CREATE_FILE) {
423
 
                err = PBHCreateSync(&hpb);
424
 
               
425
 
       /* If opening with the PR_EXCL flag the existence of the file prior to opening is an error */
426
 
       if ((flags & PR_EXCL) &&  (err == dupFNErr)) {
427
 
           err = PR_FILE_EXISTS_ERROR;
428
 
           goto ErrorExit;
429
 
       }
430
 
       
431
 
       if ((err != noErr) && (err != dupFNErr))
432
 
          goto ErrorExit;
433
 
        }
434
 
 
435
 
    err = PBHOpenDFSync(&hpb);
436
 
 
437
 
        if (err != noErr)
438
 
                goto ErrorExit;
439
 
 
440
 
        if (flags & PR_TRUNCATE) {
441
 
                pb.ioParam.ioCompletion = NULL;
442
 
                pb.ioParam.ioRefNum = hpb.ioParam.ioRefNum;
443
 
                pb.ioParam.ioMisc = NULL;
444
 
                err = PBSetEOFSync(&pb);
445
 
                if (err != noErr)
446
 
                        goto ErrorExit;
447
 
        } else if (flags & PR_APPEND) {
448
 
                pb.ioParam.ioCompletion = NULL;
449
 
                pb.ioParam.ioRefNum = hpb.ioParam.ioRefNum;
450
 
                pb.ioParam.ioPosMode = fsFromLEOF;
451
 
                pb.ioParam.ioPosOffset = 0;
452
 
                err = PBSetFPosSync(&pb);
453
 
                if (err != noErr)
454
 
                        goto ErrorExit;
455
 
        }
456
 
        return hpb.ioParam.ioRefNum;
457
 
                
458
 
ErrorExit:
459
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
460
 
        _MD_SetError(err);
461
 
    return -1;
462
 
}
463
 
 
464
 
/* _MD_CLOSE_FILE, _MD_READ, _MD_WRITE, _MD_GET_FILE_ERROR are defined in _macos.h */
465
 
 
466
 
PROffset32 _MD_LSeek(PRFileDesc *fd, PROffset32 offset, PRSeekWhence how)
467
 
{
468
 
        PRInt32 refNum = fd->secret->md.osfd;
469
 
        OSErr   err = noErr;
470
 
        long    curPos, endPos;
471
 
 
472
 
        /* compute new mark */
473
 
        switch (how) {
474
 
                case PR_SEEK_SET:
475
 
                        endPos = offset;
476
 
                        break;
477
 
                
478
 
                case PR_SEEK_CUR:
479
 
                        err = GetFPos(refNum, &curPos);
480
 
                        endPos = curPos + offset;
481
 
                        break;
482
 
                
483
 
                case PR_SEEK_END:
484
 
                        err = GetEOF(refNum, &curPos);
485
 
                        endPos = curPos + offset;
486
 
                        break;
487
 
 
488
 
                default:
489
 
                        err = paramErr;
490
 
                        break;
491
 
        }
492
 
 
493
 
        /* set the new mark and extend the file if seeking beyond current EOF */
494
 
        /* making sure to set the mark after any required extend */
495
 
        if (err == noErr) {
496
 
                err = SetFPos(refNum, fsFromStart, endPos);
497
 
                if (err == eofErr) {
498
 
                        err = SetEOF(refNum, endPos);
499
 
                        if (err == noErr) {
500
 
                                err = SetFPos(refNum, fsFromStart, endPos);
501
 
                        }
502
 
                }
503
 
        }
504
 
 
505
 
        if (err == noErr) {
506
 
                return endPos;
507
 
        } else {
508
 
                _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
509
 
            _MD_SetError(err);
510
 
                return -1;
511
 
        }
512
 
}
513
 
 
514
 
PRInt32 _MD_FSync(PRFileDesc *fd)
515
 
{
516
 
        PRInt32 refNum = fd->secret->md.osfd;
517
 
        OSErr   err;
518
 
        ParamBlockRec           pb;
519
 
 
520
 
        pb.ioParam.ioCompletion         = NULL;
521
 
        pb.ioParam.ioRefNum             = refNum;
522
 
 
523
 
        err = PBFlushFileSync(&pb);
524
 
        if (err != noErr)
525
 
                goto ErrorExit;
526
 
                
527
 
        return 0;
528
 
 
529
 
ErrorExit:
530
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
531
 
        _MD_SetError(err);
532
 
    return -1;  
533
 
}
534
 
 
535
 
#include "plstr.h"
536
 
 
537
 
PRStatus _MD_OpenDir(_MDDir *mdDir,const char *name)
538
 
{
539
 
        // Emulate the Unix opendir() routine.
540
 
 
541
 
        OSErr                           err;
542
 
        CInfoPBRec                      pb;
543
 
        char                            *macDirName = NULL;
544
 
        char                            *position = NULL;
545
 
        char                            volumeName[32];
546
 
        Str255                          pascalName;
547
 
 
548
 
        // Get the Macintosh path
549
 
        err = ConvertUnixPathToMacPath(name, &macDirName);
550
 
        if (err != noErr)
551
 
                goto ErrorExit;
552
 
        
553
 
        // Get the vRefNum
554
 
        position = PL_strchr(macDirName, PR_PATH_SEPARATOR);
555
 
        if ((position == macDirName) || (position == NULL))
556
 
                mdDir->ioVRefNum = 0;                                                                           // Use application relative searching
557
 
        else {
558
 
                memset(volumeName, 0, sizeof(volumeName));
559
 
                strncpy(volumeName, macDirName, position-macDirName);
560
 
                mdDir->ioVRefNum = GetVolumeRefNumFromName(volumeName);
561
 
        }
562
 
 
563
 
        // Get info about the object.
564
 
        PStrFromCStr(macDirName, pascalName);
565
 
        PR_DELETE(macDirName);
566
 
        
567
 
        pb.dirInfo.ioNamePtr = pascalName;
568
 
        pb.dirInfo.ioVRefNum = mdDir->ioVRefNum;
569
 
        pb.dirInfo.ioDrDirID = 0;
570
 
        pb.dirInfo.ioFDirIndex = 0;
571
 
        err = PBGetCatInfoSync(&pb);
572
 
        if (err != noErr)
573
 
                goto ErrorExit;
574
 
                
575
 
        // Are we dealing with a directory?
576
 
        if ((pb.dirInfo.ioFlAttrib & ioDirMask) == 0) {
577
 
                err = dirNFErr;
578
 
                goto ErrorExit;
579
 
        }
580
 
        
581
 
        /* This is a directory, store away the pertinent information.
582
 
        ** We post increment.  I.e. index is always the nth. item we 
583
 
        ** should get on the next call
584
 
        */
585
 
        mdDir->ioDirID = pb.dirInfo.ioDrDirID;
586
 
        mdDir->currentEntryName = NULL;
587
 
        mdDir->ioFDirIndex = 1;
588
 
        return PR_SUCCESS;
589
 
        
590
 
ErrorExit:
591
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
592
 
        _MD_SetError(err);
593
 
    return PR_FAILURE;
594
 
}
595
 
 
596
 
char *_MD_ReadDir(_MDDir *mdDir, PRIntn flags)
597
 
{
598
 
        // Emulate the Unix readdir() routine.
599
 
 
600
 
        // Mac doesn�t have the concept of .(PR_SKIP_DOT) & ..(PR_SKIP_DOT_DOT)
601
 
 
602
 
        OSErr                           err;
603
 
        CInfoPBRec                      pb;
604
 
        char                            *returnedCStr;
605
 
        Str255                          pascalName = "\p";
606
 
        PRBool                          foundEntry;
607
 
        
608
 
        PR_ASSERT(mdDir != NULL);
609
 
 
610
 
        do {
611
 
 
612
 
        // Release the last name read.
613
 
        PR_DELETE(mdDir->currentEntryName);
614
 
        mdDir->currentEntryName = NULL;
615
 
                
616
 
        // We�ve got all the info we need, just get info about this guy.
617
 
        pb.hFileInfo.ioNamePtr = pascalName;
618
 
        pb.hFileInfo.ioVRefNum = mdDir->ioVRefNum;
619
 
        pb.hFileInfo.ioFDirIndex = mdDir->ioFDirIndex;
620
 
        pb.hFileInfo.ioDirID = mdDir->ioDirID;
621
 
        err = PBGetCatInfoSync(&pb);
622
 
        if (err != noErr)
623
 
                goto ErrorExit;
624
 
        
625
 
        // Convert the Pascal string to a C string (actual allocation occurs in CStrFromPStr)
626
 
        CStrFromPStr(pascalName, &returnedCStr);
627
 
        
628
 
        mdDir->currentEntryName = returnedCStr;
629
 
        mdDir->ioFDirIndex++;
630
 
        
631
 
        // If it is not a hidden file and the flags did not specify skipping, we are done.
632
 
        if ((flags & PR_SKIP_HIDDEN) && (pb.hFileInfo.ioFlFndrInfo.fdFlags & fInvisible))
633
 
                foundEntry = PR_FALSE;
634
 
        else
635
 
                foundEntry = PR_TRUE;   
636
 
        
637
 
        } while (!foundEntry);
638
 
        
639
 
        return (mdDir->currentEntryName);
640
 
 
641
 
ErrorExit:
642
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
643
 
        _MD_SetError(err);
644
 
    return NULL;
645
 
}
646
 
 
647
 
 
648
 
void _MD_CloseDir(_MDDir *mdDir)
649
 
{
650
 
        // Emulate the Unix closedir() routine
651
 
 
652
 
        PR_DELETE(mdDir->currentEntryName);
653
 
}
654
 
 
655
 
PRInt32 _MD_MkDir(char *unixPath, PRIntn mode)
656
 
{
657
 
        HFileParam              fpb;
658
 
        Str255                  pascalName = "\p";
659
 
        char                    *cMacPath = NULL;
660
 
        OSErr                   err;
661
 
 
662
 
        #pragma unused (mode)   // Mode is ignored on the Mac
663
 
 
664
 
        if (unixPath) {
665
 
        err = ConvertUnixPathToMacPath(unixPath, &cMacPath);
666
 
                if (err != noErr)
667
 
                        goto ErrorExit;
668
 
 
669
 
        PStrFromCStr(cMacPath, pascalName);
670
 
                PR_DELETE(cMacPath);
671
 
                fpb.ioNamePtr = pascalName;
672
 
                fpb.ioVRefNum = 0;
673
 
                fpb.ioDirID = 0L;
674
 
 
675
 
                err = PBDirCreateSync((HParmBlkPtr)&fpb);
676
 
                if (err != noErr)
677
 
                        goto ErrorExit;
678
 
        }
679
 
 
680
 
        return 0;
681
 
        
682
 
ErrorExit:
683
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
684
 
        _MD_SetError(err);
685
 
    return -1;
686
 
}
687
 
 
688
 
PRInt32 _MD_Delete(char *unixPath)
689
 
{
690
 
        HFileParam              fpb;
691
 
        Str255                  pascalName = "\p";
692
 
        char                    *cMacPath = NULL;
693
 
        OSErr                   err;
694
 
 
695
 
        if (unixPath) {
696
 
        err = ConvertUnixPathToMacPath(unixPath, &cMacPath);
697
 
                if (err != noErr)
698
 
                        goto ErrorExit;
699
 
 
700
 
        PStrFromCStr(cMacPath, pascalName);
701
 
                PR_DELETE(cMacPath);
702
 
                fpb.ioNamePtr = pascalName;
703
 
                fpb.ioVRefNum = 0;
704
 
                fpb.ioDirID = 0L;
705
 
 
706
 
                err = PBHDeleteSync((HParmBlkPtr)&fpb);
707
 
                if (err != noErr)
708
 
                        goto ErrorExit;
709
 
        }
710
 
 
711
 
        return 0;
712
 
        
713
 
ErrorExit:
714
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
715
 
        _MD_SetError(err);
716
 
    return -1;
717
 
}
718
 
 
719
 
PRInt32 _MD_Rename(char *fromUnixPath, char *toUnixPath)
720
 
{
721
 
        OSErr                   err;
722
 
        FSSpec                  fromSpec;
723
 
        FSSpec                  toSpec;
724
 
        FSSpec                  destDirSpec;
725
 
        FSSpec                  beforeRenameSpec;
726
 
 
727
 
        if (fromUnixPath && toUnixPath) {
728
 
        err = ConvertUnixPathToFSSpec(fromUnixPath, &fromSpec);
729
 
                if (err != noErr)
730
 
                        goto ErrorExit;
731
 
 
732
 
        err = ConvertUnixPathToFSSpec(toUnixPath, &toSpec);
733
 
                if (err != noErr && err != fnfErr)
734
 
                        goto ErrorExit;
735
 
 
736
 
        /* make an FSSpec for the destination directory */
737
 
                err = FSMakeFSSpec(toSpec.vRefNum, toSpec.parID, nil, &destDirSpec);
738
 
                if (err != noErr) /* parent directory must exist */
739
 
                        goto ErrorExit;
740
 
 
741
 
                // move it to the directory specified
742
 
        err = FSpCatMove(&fromSpec, &destDirSpec);
743
 
                if (err != noErr)
744
 
                        goto ErrorExit;
745
 
            
746
 
            // make a new FSSpec for the file or directory in its new location  
747
 
                err = FSMakeFSSpec(toSpec.vRefNum, toSpec.parID, fromSpec.name, &beforeRenameSpec);
748
 
                if (err != noErr)
749
 
                        goto ErrorExit;
750
 
        
751
 
        // rename the file or directory
752
 
        err = FSpRename(&beforeRenameSpec, toSpec.name);
753
 
                if (err != noErr)
754
 
                        goto ErrorExit;
755
 
 
756
 
        } else {
757
 
                err = paramErr;
758
 
                goto ErrorExit;
759
 
        }
760
 
 
761
 
        return 0;
762
 
        
763
 
ErrorExit:
764
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
765
 
        _MD_SetError(err);
766
 
    return -1;
767
 
}
768
 
 
769
 
#define kWriteAccessAllowed (0x100)
770
 
PRInt32 _MD_Access(char *unixPath, int amode)
771
 
{
772
 
        //
773
 
        // Emulate the Unix access routine
774
 
        //
775
 
        
776
 
        OSErr                   err;
777
 
        CInfoPBRec              pb;
778
 
        FCBPBRec                fcbpb;
779
 
        char                    *cMacPath = NULL;
780
 
        Str255                  pascalMacPath;
781
 
        struct stat             info;
782
 
        
783
 
        // Convert to a Mac style path
784
 
        err = ConvertUnixPathToMacPath(unixPath, &cMacPath);
785
 
        if (err != noErr)
786
 
                goto ErrorExit;
787
 
        
788
 
        err = stat(cMacPath, &info);
789
 
        if (err != noErr)
790
 
                goto ErrorExit;
791
 
        
792
 
        
793
 
        // If all we�re doing is checking for the existence of the file, we�re out of here.
794
 
        // On the Mac, if a file exists, you can read from it.
795
 
        // This doesn�t handle remote AppleShare volumes.  Does it need to?
796
 
        if ((amode == PR_ACCESS_EXISTS) || (amode == PR_ACCESS_READ_OK)) {
797
 
                goto success;
798
 
        }
799
 
        
800
 
        PStrFromCStr(cMacPath, pascalMacPath);
801
 
        
802
 
        pb.hFileInfo.ioNamePtr = pascalMacPath;
803
 
        pb.hFileInfo.ioVRefNum = info.st_dev;
804
 
        pb.hFileInfo.ioDirID = 0;
805
 
        pb.hFileInfo.ioFDirIndex = 0;
806
 
        
807
 
        err = PBGetCatInfoSync(&pb);
808
 
        if (err != noErr)
809
 
                goto ErrorExit;
810
 
        // Check out all the access permissions.
811
 
        
812
 
        if (amode == PR_ACCESS_WRITE_OK) {
813
 
                fcbpb.ioNamePtr = NULL;
814
 
                fcbpb.ioVRefNum = pb.hFileInfo.ioVRefNum;
815
 
                fcbpb.ioRefNum = pb.hFileInfo.ioFRefNum;
816
 
                fcbpb.ioFCBIndx = 0;
817
 
        
818
 
                err = PBGetFCBInfoSync(&fcbpb);
819
 
                if (err != noErr)
820
 
                        goto ErrorExit;
821
 
        
822
 
                /* Look at Inside Mac IV-180 */
823
 
                if ((fcbpb.ioFCBFlags & kWriteAccessAllowed) == 0) {
824
 
                        err = permErr;
825
 
                        goto ErrorExit;
826
 
                }
827
 
        }
828
 
        
829
 
success:
830
 
        PR_DELETE(cMacPath);
831
 
        return 0;
832
 
        
833
 
ErrorExit:
834
 
        if (cMacPath != NULL)
835
 
                PR_DELETE(cMacPath);
836
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
837
 
        _MD_SetError(err);
838
 
    return -1;
839
 
}
840
 
 
841
 
PRInt32 _MD_GetFileInfo(char *unixPath, PRFileInfo *info)
842
 
{
843
 
        CInfoPBRec              pb;
844
 
        OSErr                   err;
845
 
        char                    *cMacPath = NULL;
846
 
        Str255                  pascalMacPath;
847
 
        PRTime                  oneMillion, dateInMicroSeconds;
848
 
        
849
 
        // Convert to a Mac style path
850
 
        err = ConvertUnixPathToMacPath(unixPath, &cMacPath);
851
 
        if (err != noErr)
852
 
                goto ErrorExit;
853
 
        
854
 
        PStrFromCStr(cMacPath, pascalMacPath);
855
 
        PR_DELETE(cMacPath);
856
 
        
857
 
        pb.hFileInfo.ioNamePtr = pascalMacPath;
858
 
        pb.hFileInfo.ioVRefNum = 0;
859
 
        pb.hFileInfo.ioDirID = 0;
860
 
        pb.hFileInfo.ioFDirIndex = 0;
861
 
        
862
 
        err = PBGetCatInfoSync(&pb);
863
 
        if (err != noErr)
864
 
                goto ErrorExit;
865
 
        
866
 
        if (pb.hFileInfo.ioFlAttrib & ioDirMask) {
867
 
                info->type = PR_FILE_DIRECTORY;
868
 
                info->size = 0;
869
 
        } else {
870
 
                info->type = PR_FILE_FILE;
871
 
                info->size = pb.hFileInfo.ioFlLgLen + pb.hFileInfo.ioFlRLgLen;
872
 
        }
873
 
 
874
 
        pb.hFileInfo.ioFlCrDat -= gJanuaryFirst1970Seconds;
875
 
        LL_I2L(dateInMicroSeconds, pb.hFileInfo.ioFlCrDat);
876
 
        LL_I2L(oneMillion, PR_USEC_PER_SEC);
877
 
        LL_MUL(info->creationTime, oneMillion, dateInMicroSeconds);
878
 
 
879
 
        pb.hFileInfo.ioFlMdDat -= gJanuaryFirst1970Seconds;
880
 
        LL_I2L(dateInMicroSeconds, pb.hFileInfo.ioFlMdDat);
881
 
        LL_MUL(info->modifyTime, oneMillion, dateInMicroSeconds);
882
 
 
883
 
        return 0;
884
 
        
885
 
ErrorExit:
886
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
887
 
        _MD_SetError(err);
888
 
    return -1;
889
 
}
890
 
 
891
 
PRInt32 _MD_GetOpenFileInfo(const PRFileDesc *fd, PRFileInfo *info)
892
 
{
893
 
        OSErr                   err;
894
 
        FCBPBRec                fcbpb;
895
 
        CInfoPBRec              pb;
896
 
        Str255                  pascalMacPath;
897
 
        PRTime                  oneMillion, dateInMicroSeconds;
898
 
        
899
 
        fcbpb.ioNamePtr = pascalMacPath;
900
 
        fcbpb.ioVRefNum = 0;
901
 
        fcbpb.ioRefNum = fd->secret->md.osfd;
902
 
        fcbpb.ioFCBIndx = 0;
903
 
        
904
 
        err = PBGetFCBInfoSync(&fcbpb);
905
 
        if (err != noErr)
906
 
                goto ErrorExit;
907
 
        
908
 
        info->type = PR_FILE_FILE;
909
 
        info->size = fcbpb.ioFCBEOF;
910
 
 
911
 
        pb.hFileInfo.ioNamePtr = pascalMacPath;
912
 
        pb.hFileInfo.ioVRefNum = fcbpb.ioFCBVRefNum;
913
 
        pb.hFileInfo.ioDirID = fcbpb.ioFCBParID;
914
 
        pb.hFileInfo.ioFDirIndex = 0;
915
 
        
916
 
        err = PBGetCatInfoSync(&pb);
917
 
        if (err != noErr)
918
 
                goto ErrorExit;
919
 
        
920
 
        pb.hFileInfo.ioFlCrDat -= gJanuaryFirst1970Seconds;
921
 
        LL_I2L(dateInMicroSeconds, pb.hFileInfo.ioFlCrDat);
922
 
        LL_I2L(oneMillion, PR_USEC_PER_SEC);
923
 
        LL_MUL(info->creationTime, oneMillion, dateInMicroSeconds);
924
 
 
925
 
        pb.hFileInfo.ioFlMdDat -= gJanuaryFirst1970Seconds;
926
 
        LL_I2L(dateInMicroSeconds, pb.hFileInfo.ioFlMdDat);
927
 
        LL_MUL(info->modifyTime, oneMillion, dateInMicroSeconds);
928
 
 
929
 
        return 0;
930
 
        
931
 
ErrorExit:
932
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
933
 
        _MD_SetError(err);
934
 
    return -1;
935
 
}
936
 
 
937
 
PRInt32 _MD_Stat(const char *path, struct stat *buf)
938
 
{
939
 
        OSErr   err;
940
 
        char    *macFileName = NULL;
941
 
        
942
 
    err = ConvertUnixPathToMacPath(path, &macFileName);
943
 
        if (err != noErr)
944
 
                goto ErrorExit;
945
 
        
946
 
        err = stat(macFileName, buf);
947
 
        if (err != noErr)
948
 
                goto ErrorExit;
949
 
                
950
 
        PR_DELETE(macFileName);
951
 
        
952
 
        return 0;
953
 
 
954
 
ErrorExit:
955
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
956
 
        _MD_SetError(err);
957
 
    return -1;
958
 
}
959
 
 
960
 
PRStatus _MD_LockFile(PRInt32 fd)
961
 
{
962
 
        OSErr                   err;
963
 
        FCBPBRec                fcbpb;
964
 
        HFileParam              fpb;
965
 
        Str255                  pascalName;
966
 
        
967
 
        fcbpb.ioNamePtr = pascalName;
968
 
        fcbpb.ioVRefNum = 0;
969
 
        fcbpb.ioRefNum = fd;
970
 
        fcbpb.ioFCBIndx = 0;
971
 
        
972
 
        err = PBGetFCBInfoSync(&fcbpb);
973
 
        if (err != noErr)
974
 
                goto ErrorExit;
975
 
        
976
 
        fpb.ioCompletion = NULL;
977
 
        fpb.ioNamePtr = pascalName;
978
 
        fpb.ioVRefNum = fcbpb.ioFCBVRefNum;
979
 
        fpb.ioDirID = fcbpb.ioFCBParID;
980
 
 
981
 
        err = PBHSetFLockSync((HParmBlkPtr)&fpb);
982
 
        if (err != noErr)
983
 
                goto ErrorExit;
984
 
        
985
 
        return PR_SUCCESS;
986
 
        
987
 
ErrorExit:
988
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
989
 
        _MD_SetError(err);
990
 
    return PR_FAILURE;
991
 
}
992
 
 
993
 
PRStatus _MD_TLockFile(PRInt32 fd)
994
 
{
995
 
        return (_MD_LockFile(fd));
996
 
}
997
 
 
998
 
PRStatus _MD_UnlockFile(PRInt32 fd)
999
 
{
1000
 
        OSErr                   err;
1001
 
        FCBPBRec                fcbpb;
1002
 
        HFileParam              fpb;
1003
 
        Str255                  pascalName;
1004
 
        
1005
 
        fcbpb.ioNamePtr = pascalName;
1006
 
        fcbpb.ioVRefNum = 0;
1007
 
        fcbpb.ioRefNum = fd;
1008
 
        fcbpb.ioFCBIndx = 0;
1009
 
        
1010
 
        err = PBGetFCBInfoSync(&fcbpb);
1011
 
        if (err != noErr)
1012
 
                goto ErrorExit;
1013
 
        
1014
 
        fpb.ioCompletion = NULL;
1015
 
        fpb.ioNamePtr = pascalName;
1016
 
        fpb.ioVRefNum = fcbpb.ioFCBVRefNum;
1017
 
        fpb.ioDirID = fcbpb.ioFCBParID;
1018
 
 
1019
 
        err = PBHRstFLockSync((HParmBlkPtr)&fpb);
1020
 
        if (err != noErr)
1021
 
                goto ErrorExit;
1022
 
        
1023
 
        return PR_SUCCESS;
1024
 
        
1025
 
ErrorExit:
1026
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
1027
 
        _MD_SetError(err);
1028
 
    return PR_FAILURE;
1029
 
}
1030
 
 
1031
 
void SetLogFileTypeCreator(const char *logFile)
1032
 
{
1033
 
        HParamBlockRec pb;
1034
 
        OSErr err;
1035
 
        Str31 pName;
1036
 
 
1037
 
        PStrFromCStr(logFile, pName);
1038
 
        pb.fileParam.ioCompletion = nil;
1039
 
        pb.fileParam.ioNamePtr = pName;
1040
 
        pb.fileParam.ioVRefNum = 0;
1041
 
        pb.fileParam.ioFDirIndex = 0;
1042
 
        pb.fileParam.ioDirID = 0;
1043
 
        err = PBHGetFInfoSync(&pb);
1044
 
        PR_ASSERT(err == noErr);
1045
 
 
1046
 
        pb.fileParam.ioDirID = 0;
1047
 
        pb.fileParam.ioFlFndrInfo.fdType = 'TEXT';
1048
 
        pb.fileParam.ioFlFndrInfo.fdCreator = 'ttxt';
1049
 
        err = PBHSetFInfoSync(&pb);
1050
 
        PR_ASSERT(err == noErr);
1051
 
}
1052
 
 
1053
 
#if DEVELOPER_DEBUG
1054
 
PR_IMPLEMENT (void)
1055
 
SetupMacPrintfLog(char *logFile)
1056
 
{
1057
 
        /*
1058
 
         * We do _PR_InitLog() twice.  The first to force the implicit initialization which
1059
 
         * will set logging to highest levels in _MD_EARLY_INIT.  Then, change the env variable
1060
 
         * to disable kernel logging and call _PR_InitLog() again to make it effective.  Since
1061
 
         * we are using logging to log test program output, we disable kernel logging to avoid
1062
 
         * all Kernel logging output.
1063
 
         */
1064
 
#ifdef PR_INTERNAL_LOGGING
1065
 
        _PR_InitLog();
1066
 
        _MD_PutEnv("NSPR_LOG_MODULES=clock:0,cmon:0,io:0,mon:0,linker:0,cvar:0,sched:0,thread:0");
1067
 
        _PR_InitLog();
1068
 
#endif
1069
 
        PR_ASSERT(PR_SetLogFile(logFile) == PR_TRUE);
1070
 
        
1071
 
        SetLogFileTypeCreator(logFile);
1072
 
}
1073
 
#endif
1074
 
 
1075
 
 
1076
 
/*
1077
 
********************** Old name related stuff that is unchanged. **********************
1078
 
*/
1079
 
 
1080
 
#if !defined(MAC_NSPR_STANDALONE)
1081
 
 
1082
 
short GetVolumeRefNumFromName(const char *cTgtVolName)
1083
 
{
1084
 
        OSErr                           err;
1085
 
        Str32                           pVolName;
1086
 
        char                            *cVolName = NULL;
1087
 
        HParamBlockRec          hPB;
1088
 
        short                           refNum = 0;
1089
 
        
1090
 
        hPB.volumeParam.ioVolIndex = 0;
1091
 
        hPB.volumeParam.ioNamePtr = pVolName;
1092
 
        do {
1093
 
                hPB.volumeParam.ioVolIndex++;
1094
 
                err = PBHGetVInfoSync(&hPB);
1095
 
                CStrFromPStr(pVolName, &cVolName);
1096
 
                if (strcmp(cTgtVolName, cVolName) == 0) {
1097
 
                        refNum =  hPB.volumeParam.ioVRefNum;
1098
 
                        PR_DELETE(cVolName);
1099
 
                        break;
1100
 
                }
1101
 
                PR_DELETE(cVolName);
1102
 
        } while (err == noErr);
1103
 
        
1104
 
        return refNum;
1105
 
}
1106
 
 
1107
 
static OSErr CreateMacPathFromUnixPath(const char *unixPath, char **macPath)
1108
 
{
1109
 
        // Given a Unix style path with '/' directory separators, this allocates 
1110
 
        // a path with Mac style directory separators in the path.
1111
 
        //
1112
 
        // It does not do any special directory translation; use ConvertUnixPathToMacPath
1113
 
        // for that.
1114
 
        
1115
 
        const char      *src;
1116
 
        char            *tgt;
1117
 
        OSErr           err = noErr;
1118
 
 
1119
 
        PR_ASSERT(unixPath != nil);
1120
 
        if (nil == unixPath) {
1121
 
                err = paramErr;
1122
 
                goto exit;
1123
 
        }
1124
 
 
1125
 
        // If unixPath is a zero-length string, we copy ":" into
1126
 
        // macPath, so we need a minimum of two bytes to handle
1127
 
        // the case of ":". 
1128
 
        *macPath = malloc(strlen(unixPath) + 2);        // Will be enough extra space.
1129
 
        require_action (*macPath != NULL, exit, err = memFullErr;);
1130
 
 
1131
 
        src = unixPath;
1132
 
        tgt = *macPath;
1133
 
        
1134
 
        if (PL_strchr(src, PR_DIRECTORY_SEPARATOR) == src)                              // If we�re dealing with an absolute
1135
 
                src++;                                                                                                  // path, skip the separator
1136
 
        else
1137
 
                *(tgt++) = PR_PATH_SEPARATOR;   
1138
 
                
1139
 
        if (PL_strstr(src, UNIX_THIS_DIRECTORY_STR) == src)                     // If it starts with /
1140
 
                src += 2;                                                                                               // skip it.
1141
 
                
1142
 
        while (*src) 
1143
 
        {                               // deal with the rest of the path
1144
 
                if (PL_strstr(src, UNIX_PARENT_DIRECTORY_STR) == src) { // Going up?
1145
 
                        *(tgt++) = PR_PATH_SEPARATOR;                                           // simply add an extra colon.
1146
 
                        src +=3;
1147
 
                }
1148
 
                else if (*src == PR_DIRECTORY_SEPARATOR) {                                      // Change the separator
1149
 
                        *(tgt++) = PR_PATH_SEPARATOR;
1150
 
                        src++;
1151
 
                }
1152
 
                else
1153
 
                        *(tgt++) = *(src++);
1154
 
        }
1155
 
        
1156
 
        *tgt = NULL;                                                    // make sure it�s null terminated.
1157
 
 
1158
 
exit:
1159
 
        return err;
1160
 
}
1161
 
 
1162
 
 
1163
 
static ProcessInfoRec gNavigatorProcInfo;
1164
 
static FSSpec gGutsFolder;
1165
 
static FSSpec gNetscapeFolder;
1166
 
 
1167
 
static OSErr SetupRequiredFSSpecs(void)
1168
 
{
1169
 
        OSErr err;
1170
 
        CInfoPBRec pb;
1171
 
        ProcessSerialNumber curPSN = {0, kCurrentProcess};      
1172
 
        
1173
 
        gNavigatorProcInfo.processInfoLength = sizeof(ProcessInfoRec);
1174
 
        gNavigatorProcInfo.processName = NULL;
1175
 
        gNavigatorProcInfo.processAppSpec = &gNetscapeFolder;
1176
 
 
1177
 
        err = GetProcessInformation (&curPSN, &gNavigatorProcInfo);
1178
 
        if (err != noErr)
1179
 
                goto ErrorExit;
1180
 
 
1181
 
        /* guts folder resides at the same place as the app file itself */
1182
 
        gGutsFolder = gNetscapeFolder;
1183
 
        /* How else do we do this hack??? 
1184
 
         * Should NSPR have a string resource for this ?
1185
 
         */
1186
 
        GetIndString( gGutsFolder.name, 300, 34);
1187
 
 
1188
 
        /* 
1189
 
         * vRefNum and parentDirID are now set up correctly for the app file itself. 
1190
 
         * parentDirID is the Netscape Folder's ID.  Then Find it's parent ID to
1191
 
         * set up the FSSpec and its own name.
1192
 
         */
1193
 
 
1194
 
        pb.dirInfo.ioCompletion = NULL;
1195
 
        pb.dirInfo.ioNamePtr = gNetscapeFolder.name;
1196
 
        pb.dirInfo.ioVRefNum = gNetscapeFolder.vRefNum;
1197
 
        pb.dirInfo.ioFDirIndex = -1;
1198
 
        pb.dirInfo.ioDrDirID = gNetscapeFolder.parID;
1199
 
        
1200
 
        err = PBGetCatInfoSync(&pb);
1201
 
        if (err != noErr)
1202
 
                goto ErrorExit;
1203
 
        
1204
 
        gNetscapeFolder.parID = pb.dirInfo.ioDrParID;
1205
 
        
1206
 
        return noErr;   
1207
 
 
1208
 
ErrorExit:
1209
 
        return err;
1210
 
}
1211
 
 
1212
 
static OSErr FindGutsFolder(FSSpec *foundSpec)
1213
 
{
1214
 
        OSErr err;
1215
 
        
1216
 
        if (gNavigatorProcInfo.processInfoLength == 0) { /* Uninitialized? */
1217
 
                err = SetupRequiredFSSpecs();
1218
 
                if (err != noErr)
1219
 
                        goto ErrorExit;
1220
 
        } 
1221
 
        
1222
 
        *foundSpec = gGutsFolder;
1223
 
        
1224
 
        return noErr;   
1225
 
 
1226
 
ErrorExit:
1227
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
1228
 
    return err; 
1229
 
}
1230
 
 
1231
 
static OSErr FindNetscapeFolder(FSSpec *foundSpec)
1232
 
{
1233
 
        OSErr err;
1234
 
        
1235
 
        if (gNavigatorProcInfo.processInfoLength == 0) { /* Uninitialized? */
1236
 
                err = SetupRequiredFSSpecs();
1237
 
                if (err != noErr)
1238
 
                        goto ErrorExit;
1239
 
        } 
1240
 
        
1241
 
        *foundSpec = gNetscapeFolder;
1242
 
        
1243
 
        return noErr;   
1244
 
 
1245
 
ErrorExit:
1246
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
1247
 
    return err; 
1248
 
}
1249
 
 
1250
 
 
1251
 
PR_IMPLEMENT (OSErr)
1252
 
ConvertUnixPathToMacPath(const char *unixPath, char **macPath)
1253
 
{       
1254
 
                OSErr           err = noErr;
1255
 
                
1256
 
        //      ******** HACK ALERT ********
1257
 
        //
1258
 
        //      Java really wants long file names (>31 chars).  We truncate file names 
1259
 
        //      greater than 31 characters long.  Truncation is from the middle.
1260
 
        //
1261
 
        //      Convert UNIX style path names (with . and / separators) into a Macintosh
1262
 
        //      style path (with :).
1263
 
        //
1264
 
        // There are also a couple of special paths that need to be dealt with
1265
 
        // by translating them to the appropriate Mac special folders.  These include:
1266
 
        //
1267
 
        //                      /usr/tmp/file  =>  {TempFolder}file
1268
 
        //
1269
 
        // The file conversions we need to do are as follows:
1270
 
        //
1271
 
        //                      file                    =>              file
1272
 
        //                      dir/file                =>              :dir:file
1273
 
        //                      ./file                  =>              file
1274
 
        //                      ../file                 =>              ::file
1275
 
        //                      ../dir/file             =>              ::dir:file
1276
 
        //                      /file                   =>              ::BootDrive:file
1277
 
        //                      /dir/file               =>              ::BootDrive:dir:file
1278
 
        
1279
 
        
1280
 
        if (!strcmp(unixPath, "."))
1281
 
        {
1282
 
                *macPath = malloc(sizeof(":"));
1283
 
                if (*macPath == NULL)
1284
 
                        err = memFullErr;
1285
 
                (*macPath)[0] = ':';
1286
 
                (*macPath)[1] = '\0';
1287
 
        }
1288
 
        else
1289
 
        
1290
 
        if (*unixPath != PR_DIRECTORY_SEPARATOR) {                              // Not root relative, just convert it.
1291
 
                err = CreateMacPathFromUnixPath(unixPath, macPath);
1292
 
        }
1293
 
        
1294
 
        else {
1295
 
                // We�re root-relative.  This is either a special Unix directory, or a 
1296
 
                // full path (which we�ll support on the Mac since they might be generated).
1297
 
                // This is not condoning the use of full-paths on the Macintosh for file 
1298
 
                // specification.
1299
 
                
1300
 
                FSSpec          foundSpec;
1301
 
                short           pathBufferSize;
1302
 
#if DEBUG       
1303
 
                char            *temp;
1304
 
#endif
1305
 
                int             tempLen;
1306
 
 
1307
 
                // Are we dealing with the temp folder?
1308
 
                if ((strncmp(unixPath, "/usr/tmp", strlen("/usr/tmp")) == 0) || 
1309
 
                        ((strncmp(unixPath, "/tmp", strlen("/tmp")) == 0))) {
1310
 
                    CInfoPBRec pb;
1311
 
 
1312
 
                        unixPath = PL_strchr(unixPath, PR_DIRECTORY_SEPARATOR);
1313
 
                        if (strncmp(unixPath, "/tmp", strlen("/tmp")) == 0) // skip past temp spec
1314
 
                                unixPath += 5;  
1315
 
                        else
1316
 
                                unixPath += 9;  
1317
 
                                                        
1318
 
                        err = FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder,    // Create if needed
1319
 
                                                                &foundSpec.vRefNum, &foundSpec.parID);
1320
 
                        if (err == noErr) {
1321
 
                                pb.dirInfo.ioCompletion = NULL;
1322
 
                                pb.dirInfo.ioNamePtr = foundSpec.name;
1323
 
                                pb.dirInfo.ioVRefNum = foundSpec.vRefNum;
1324
 
                                pb.dirInfo.ioFDirIndex = -1;
1325
 
                                pb.dirInfo.ioDrDirID = foundSpec.parID;
1326
 
                                
1327
 
                                err = PBGetCatInfoSync(&pb);
1328
 
                                foundSpec.parID = pb.dirInfo.ioDrParID;
1329
 
                        }
1330
 
                }
1331
 
                
1332
 
                else if (!strncmp(unixPath, "/usr/local/netscape/", (tempLen = strlen("/usr/local/netscape/")))) {
1333
 
                        
1334
 
                        unixPath += tempLen;
1335
 
                        
1336
 
                        if (!strncmp(unixPath, "RequiredGuts/", (tempLen = strlen("RequiredGuts/"))))
1337
 
                        {
1338
 
                                unixPath += tempLen;
1339
 
                                err = FindGutsFolder(&foundSpec);
1340
 
                        }
1341
 
                        else if (!strncmp(unixPath, "bin/", (tempLen = strlen("bin/"))))
1342
 
                        {
1343
 
                                unixPath += tempLen;
1344
 
                                err = FindNetscapeFolder(&foundSpec);
1345
 
                        }                       
1346
 
                        else if (*unixPath == '\0')
1347
 
                        {
1348
 
                                // it's /usr/local/netscape
1349
 
                                err = FindGutsFolder(&foundSpec);
1350
 
                        }
1351
 
 
1352
 
                }
1353
 
                
1354
 
                else {
1355
 
                        // This is a root relative directory, we�ll just convert the whole thing.
1356
 
                        err = CreateMacPathFromUnixPath(unixPath, macPath);
1357
 
                        goto Exit_ConvertUnixPathToMacPath;
1358
 
                }
1359
 
        
1360
 
 
1361
 
                
1362
 
                // We�re dealing with a special folder
1363
 
                if (err == noErr)
1364
 
                {
1365
 
                        Handle  hPathStr;
1366
 
                        // Get the path to the root-relative directory
1367
 
                        err = FSpGetFullPath(&foundSpec, &pathBufferSize, &hPathStr);           // NewHandle's hPathStr
1368
 
                         
1369
 
                        if (noErr == err)
1370
 
                        {
1371
 
                                // convert handle to c-string
1372
 
                                // add one for NULL termination
1373
 
                                // pathBufferSize is now one greater than the length of the string
1374
 
                                pathBufferSize++;       
1375
 
                                
1376
 
                                *macPath = (char*) malloc(sizeof(char) * pathBufferSize);
1377
 
                                (*macPath)[pathBufferSize - 1] = '\0';
1378
 
                                BlockMoveData(*hPathStr, *macPath, pathBufferSize - 1);
1379
 
                        
1380
 
                                DisposeHandle(hPathStr);
1381
 
                        }
1382
 
                }
1383
 
                
1384
 
                if (err == noErr)
1385
 
                {
1386
 
                        UInt32  unixPathLeft;
1387
 
                        UInt32  macPathLen;
1388
 
 
1389
 
                        unixPathLeft =  strlen(unixPath);
1390
 
                        macPathLen = strlen(*macPath);
1391
 
                        
1392
 
 
1393
 
                        // copy over the remaining file name, converting
1394
 
                        if (pathBufferSize - 1 < macPathLen + unixPathLeft) 
1395
 
                        {
1396
 
                                // need to grow string
1397
 
                                *macPath = realloc(*macPath, macPathLen + unixPathLeft + 1);
1398
 
                                err = (*macPath == NULL ? memFullErr : noErr);
1399
 
                        }
1400
 
                        
1401
 
                        if (err == noErr)
1402
 
                        {
1403
 
                                // carefully remove the '/''s out of the unix path.  If we see an "escaped" /
1404
 
                                // we will leave it in there, otherwise we take it out and replace it with a :
1405
 
                                // we have to do this before we convert to a mac-path, so we can tell what is
1406
 
                                // really a path separator and what is in the name of a file or directory
1407
 
                                // Make sure that all of the /�s are :�s in the final pathname
1408
 
                                // effectively we do a
1409
 
                                // strcat(*macPath, unixPath); while replace all occurrences of / with : in unixPath
1410
 
                                char*           dp;
1411
 
                                const char*     sp;
1412
 
                                
1413
 
                                sp = unixPath;
1414
 
                                dp = *macPath + macPathLen;
1415
 
                                
1416
 
                                for (;*sp != '\0'; sp++, dp++) 
1417
 
                                {
1418
 
                                        if (*sp == PR_DIRECTORY_SEPARATOR)
1419
 
                                        {
1420
 
                                                // if we can look at the previous character
1421
 
                                                if (sp > unixPath)                                      
1422
 
                                                {
1423
 
                                                        // check to see if previous character is an escape
1424
 
                                                        if (sp[-1] == '\\')
1425
 
                                                        {
1426
 
                                                                // leave it in, and cycle
1427
 
                                                                continue;
1428
 
                                                        }
1429
 
                                                        else
1430
 
                                                        {
1431
 
                                                                *dp = PR_PATH_SEPARATOR;
1432
 
                                                        }
1433
 
                                                }
1434
 
                                                else                            
1435
 
                                                        *dp = PR_PATH_SEPARATOR;
1436
 
                                        }
1437
 
                                        else
1438
 
                                        {
1439
 
                                                // just copy;
1440
 
                                                *dp = *sp;
1441
 
                                        }
1442
 
                                }
1443
 
                                
1444
 
                                *dp = '\0';   // NULL terminate *macPath
1445
 
                        }
1446
 
#if DEBUG       
1447
 
                        // we used to check here, now we check above, we leave this in
1448
 
                        // the debug build to make sure we didn't screw up
1449
 
                        // Make sure that all of the /�s are :�s in the final pathname
1450
 
                        for (temp = *macPath + strlen(*macPath) - strlen(unixPath); *temp != '\0'; temp++) {
1451
 
 
1452
 
                                if (*temp == PR_DIRECTORY_SEPARATOR)
1453
 
                                {
1454
 
                                        DebugStr("\pFound a slash");    
1455
 
                                        *temp = PR_PATH_SEPARATOR;
1456
 
                                }
1457
 
                        }
1458
 
#endif
1459
 
                }
1460
 
        }
1461
 
        
1462
 
        
1463
 
Exit_ConvertUnixPathToMacPath:
1464
 
 
1465
 
        return err;
1466
 
}
1467
 
 
1468
 
// Hey! Before you delete this "hack" you should look at how it's being
1469
 
// used by sun-java/netscape/applet/appletStubs.c.
1470
 
PR_IMPLEMENT (OSErr)
1471
 
ConvertMacPathToUnixPath(const char *macPath, char **unixPath) 
1472
 
{
1473
 
        // *** HACK ***
1474
 
        // Get minimal version working
1475
 
        
1476
 
        char            *unixPathPtr;
1477
 
        
1478
 
        *unixPath = malloc(strlen(macPath) + 2);        // Add one for the front slash, one for null
1479
 
        if (*unixPath == NULL)
1480
 
                return (memFullErr);
1481
 
                
1482
 
        unixPathPtr = *unixPath;
1483
 
        
1484
 
        *unixPathPtr++ = PR_DIRECTORY_SEPARATOR;
1485
 
        
1486
 
        do {
1487
 
                // Translate all colons to slashes
1488
 
                if (*macPath == PR_PATH_SEPARATOR)
1489
 
                        *unixPathPtr = PR_DIRECTORY_SEPARATOR;
1490
 
                else
1491
 
                        *unixPathPtr = *macPath;
1492
 
 
1493
 
                unixPathPtr++;
1494
 
                macPath++;
1495
 
        } while (*macPath != NULL);
1496
 
        
1497
 
        // Terminate the string
1498
 
        *unixPathPtr = '\0';
1499
 
        
1500
 
        return (noErr);
1501
 
}
1502
 
 
1503
 
OSErr
1504
 
ConvertUnixPathToFSSpec(const char *unixPath, FSSpec *fileSpec)
1505
 
{
1506
 
    char*                   macPath;
1507
 
    OSErr                   convertError;
1508
 
    int                             len;
1509
 
    
1510
 
    convertError = ConvertUnixPathToMacPath(unixPath, &macPath);
1511
 
    if (convertError != noErr)
1512
 
        return convertError;
1513
 
 
1514
 
    len = strlen(macPath);
1515
 
 
1516
 
    if (*macPath == PR_PATH_SEPARATOR)
1517
 
    {
1518
 
        if (len < sizeof(Str255))
1519
 
        {
1520
 
            short   vRefNum;
1521
 
            long    dirID;
1522
 
            Str255  pascalMacPath;
1523
 
            
1524
 
            convertError = HGetVol(NULL, &vRefNum, &dirID);
1525
 
            if (convertError == noErr)
1526
 
            {
1527
 
                PStrFromCStr(macPath, pascalMacPath);
1528
 
                convertError = FSMakeFSSpec(vRefNum, dirID, pascalMacPath, fileSpec);
1529
 
            }
1530
 
        }
1531
 
        else
1532
 
            convertError = paramErr;
1533
 
    }
1534
 
    else
1535
 
    {
1536
 
        convertError = FSpLocationFromFullPath(len, macPath, fileSpec);
1537
 
            if (convertError == fnfErr)
1538
 
            {
1539
 
                        CInfoPBRec              pb;
1540
 
                        Str255  pascalMacPath;
1541
 
                        OSErr err;
1542
 
                        
1543
 
                        PStrFromCStr(macPath, pascalMacPath);
1544
 
                        /* 
1545
 
                        FSpLocationFromFullPath does not work for directories unless there is
1546
 
                        a ":" at the end.  We will make sure of an existence of a directory.
1547
 
                        If so, the returned fileSpec is valid from FSpLocationFromFullPath eventhough
1548
 
                        it returned an error.
1549
 
                        */
1550
 
                        pb.hFileInfo.ioNamePtr = pascalMacPath;
1551
 
                        pb.hFileInfo.ioVRefNum = 0;
1552
 
                        pb.hFileInfo.ioDirID = 0;
1553
 
                        pb.hFileInfo.ioFDirIndex = 0;
1554
 
                        
1555
 
                        err = PBGetCatInfoSync(&pb);
1556
 
                        if (err == noErr)
1557
 
                                convertError = noErr;
1558
 
                }
1559
 
    }
1560
 
    
1561
 
    free(macPath);
1562
 
    
1563
 
    return (convertError);
1564
 
}
1565
 
 
1566
 
 
1567
 
FILE *_OS_FOPEN(const char *filename, const char *mode) 
1568
 
{
1569
 
        OSErr   err = noErr;
1570
 
        char    *macFileName = NULL;
1571
 
        FILE    *result;
1572
 
        
1573
 
    err = ConvertUnixPathToMacPath(filename, &macFileName);
1574
 
        if (err != noErr)
1575
 
                goto ErrorExit;
1576
 
        
1577
 
        result = fopen(macFileName, mode);
1578
 
                
1579
 
        PR_DELETE(macFileName);
1580
 
        
1581
 
        return result;
1582
 
 
1583
 
ErrorExit:
1584
 
        _PR_MD_CURRENT_THREAD()->md.osErrCode = err;
1585
 
        _MD_SetError(err);
1586
 
    return NULL;
1587
 
}
1588
 
 
1589
 
#else
1590
 
 
1591
 
short GetVolumeRefNumFromName(const char *cTgtVolName)
1592
 
{
1593
 
        OSErr                           err;
1594
 
        Str32                           pVolName;
1595
 
        char                            *cVolName = NULL;
1596
 
        HParamBlockRec          hPB;
1597
 
        short                           refNum = 0;
1598
 
        
1599
 
        hPB.volumeParam.ioVolIndex = 0;
1600
 
        hPB.volumeParam.ioNamePtr = pVolName;
1601
 
        do {
1602
 
                hPB.volumeParam.ioVolIndex++;
1603
 
                err = PBHGetVInfoSync(&hPB);
1604
 
                CStrFromPStr(pVolName, &cVolName);
1605
 
                if (strcmp(cTgtVolName, cVolName) == 0) {
1606
 
                        refNum =  hPB.volumeParam.ioVRefNum;
1607
 
                        PR_DELETE(cVolName);
1608
 
                        break;
1609
 
                }
1610
 
                PR_DELETE(cVolName);
1611
 
        } while (err == noErr);
1612
 
        
1613
 
        return refNum;
1614
 
}
1615
 
 
1616
 
 
1617
 
 
1618
 
static OSErr GetFullPath(short vRefNum, long dirID, char **fullPath, int *strSize)
1619
 
{
1620
 
        Str255                  pascalDirName;
1621
 
        char                    cDirName[256];
1622
 
        char                    *tmpPath = NULL;                                                // needed since sprintf isn�t safe
1623
 
        CInfoPBRec              myPB;
1624
 
        OSErr                   err = noErr;
1625
 
        
1626
 
        
1627
 
        // get the full path of the temp folder.
1628
 
        *strSize = 256;
1629
 
        *fullPath = NULL;
1630
 
        *fullPath = malloc(*strSize);   // How big should this thing be?
1631
 
        require_action (*fullPath != NULL, errorExit, err = memFullErr;);
1632
 
                
1633
 
        tmpPath = malloc(*strSize);
1634
 
        require_action (tmpPath != NULL, errorExit, err = memFullErr;);
1635
 
 
1636
 
        strcpy(*fullPath, "");                          // Clear C result
1637
 
        strcpy(tmpPath, "");
1638
 
        pascalDirName[0] = 0;                           // Clear Pascal intermediate string
1639
 
        
1640
 
        myPB.dirInfo.ioNamePtr = &pascalDirName[0];
1641
 
        myPB.dirInfo.ioVRefNum = vRefNum;
1642
 
        myPB.dirInfo.ioDrParID = dirID;
1643
 
        myPB.dirInfo.ioFDirIndex = -1;                          // Getting info about
1644
 
        
1645
 
        do {
1646
 
                myPB.dirInfo.ioDrDirID = myPB.dirInfo.ioDrParID;
1647
 
 
1648
 
                err = PBGetCatInfoSync(&myPB);
1649
 
                require(err == noErr, errorExit);
1650
 
                        
1651
 
                // Move the name into C domain
1652
 
                memcpy(&cDirName, &pascalDirName, 256);
1653
 
                p2cstr((unsigned char *)&cDirName);                                                     // Changes in place!
1654
 
                
1655
 
                if ((strlen(cDirName) + strlen(*fullPath)) > *strSize) {
1656
 
                        // We need to grow the string, do it in 256 byte chunks
1657
 
                        (*strSize) += 256;                                                                              
1658
 
                        *fullPath = PR_REALLOC(*fullPath, *strSize);
1659
 
                        require_action (*fullPath != NULL, errorExit, err = memFullErr;);
1660
 
 
1661
 
                        tmpPath = PR_REALLOC(tmpPath, *strSize);
1662
 
                        require_action (tmpPath != NULL, errorExit, err = memFullErr;);
1663
 
                }
1664
 
                sprintf(tmpPath, "%s:%s", cDirName, *fullPath);
1665
 
                strcpy(*fullPath, tmpPath);
1666
 
        } while (myPB.dirInfo.ioDrDirID != fsRtDirID);
1667
 
        
1668
 
        PR_DELETE(tmpPath);
1669
 
        
1670
 
        return noErr;
1671
 
        
1672
 
        
1673
 
errorExit:
1674
 
        PR_DELETE(*fullPath);
1675
 
        PR_DELETE(tmpPath);
1676
 
        
1677
 
        return err;
1678
 
 
1679
 
}
1680
 
 
1681
 
static OSErr CreateMacPathFromUnixPath(const char *unixPath, char **macPath)
1682
 
{
1683
 
        // Given a Unix style path with '/' directory separators, this allocates 
1684
 
        // a path with Mac style directory separators in the path.
1685
 
        //
1686
 
        // It does not do any special directory translation; use ConvertUnixPathToMacPath
1687
 
        // for that.
1688
 
        
1689
 
        const char      *src;
1690
 
        char            *tgt;
1691
 
        OSErr           err = noErr;
1692
 
 
1693
 
        PR_ASSERT(unixPath != nil);
1694
 
        if (nil == unixPath) {
1695
 
                err = paramErr;
1696
 
                goto exit;
1697
 
        }
1698
 
 
1699
 
        // If unixPath is a zero-length string, we copy ":" into
1700
 
        // macPath, so we need a minimum of two bytes to handle
1701
 
        // the case of ":". 
1702
 
        *macPath = malloc(strlen(unixPath) + 2);        // Will be enough extra space.
1703
 
        require_action (*macPath != NULL, exit, err = memFullErr;);
1704
 
 
1705
 
        src = unixPath;
1706
 
        tgt = *macPath;
1707
 
        
1708
 
        if (PL_strchr(src, PR_DIRECTORY_SEPARATOR) == src)                              // If we�re dealing with an absolute
1709
 
                src++;                                                                                                  // path, skip the separator
1710
 
        else
1711
 
                *(tgt++) = PR_PATH_SEPARATOR;   
1712
 
                
1713
 
        if (PL_strstr(src, UNIX_THIS_DIRECTORY_STR) == src)                     // If it starts with ./
1714
 
                src += 2;                                                                                               // skip it.
1715
 
                
1716
 
        while (*src) 
1717
 
        {                               // deal with the rest of the path
1718
 
                if (PL_strstr(src, UNIX_PARENT_DIRECTORY_STR) == src) { // Going up?
1719
 
                        *(tgt++) = PR_PATH_SEPARATOR;                                           // simply add an extra colon.
1720
 
                        src +=3;
1721
 
                }
1722
 
                else if (*src == PR_DIRECTORY_SEPARATOR) {                                      // Change the separator
1723
 
                        *(tgt++) = PR_PATH_SEPARATOR;
1724
 
                        src++;
1725
 
                }
1726
 
                else
1727
 
                        *(tgt++) = *(src++);
1728
 
        }
1729
 
        
1730
 
        *tgt = NULL;                                                    // make sure it�s null terminated.
1731
 
 
1732
 
exit:
1733
 
        return err;
1734
 
}
1735
 
 
1736
 
static OSErr ConvertUnixPathToMacPath(const char *unixPath, char **macPath)
1737
 
{       
1738
 
                OSErr           err = noErr;
1739
 
                
1740
 
 
1741
 
        //
1742
 
        //      Convert UNIX style path names (with . and / separators) into a Macintosh
1743
 
        //      style path (with :).
1744
 
        //
1745
 
        // There are also a couple of special paths that need to be dealt with
1746
 
        // by translating them to the appropriate Mac special folders.  These include:
1747
 
        //
1748
 
        //                      /usr/tmp/file  =>  {TempFolder}file
1749
 
        //
1750
 
        // The file conversions we need to do are as follows:
1751
 
        //
1752
 
        //                      file                    =>              file
1753
 
        //                      dir/file                =>              :dir:file
1754
 
        //                      ./file                  =>              file
1755
 
        //                      ../file                 =>              ::file
1756
 
        //                      ../dir/file             =>              ::dir:file
1757
 
        //                      /file                   =>              ::BootDrive:file
1758
 
        //                      /dir/file               =>              ::BootDrive:dir:file
1759
 
        
1760
 
        
1761
 
        if (*unixPath != PR_DIRECTORY_SEPARATOR) {                              // Not root relative, just convert it.
1762
 
                err = CreateMacPathFromUnixPath(unixPath, macPath);
1763
 
        }
1764
 
        
1765
 
        else {
1766
 
                // We�re root-relative.  This is either a special Unix directory, or a 
1767
 
                // full path (which we�ll support on the Mac since they might be generated).
1768
 
                // This is not condoning the use of full-paths on the Macintosh for file 
1769
 
                // specification.
1770
 
                
1771
 
                short           foundVRefNum;
1772
 
                long            foundDirID;
1773
 
                int                     pathBufferSize;
1774
 
                char            *temp;
1775
 
                char            isNetscapeDir = false;
1776
 
 
1777
 
                // Are we dealing with the temp folder?
1778
 
                if (strncmp(unixPath, "/usr/tmp", strlen("/usr/tmp")) == 0){
1779
 
                        unixPath += 8;
1780
 
                        if (*unixPath == PR_DIRECTORY_SEPARATOR)
1781
 
                                unixPath++;                                                                                                             // Skip the slash
1782
 
                        err = FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder,    // Create if needed
1783
 
                                                                &foundVRefNum, &foundDirID);
1784
 
                }
1785
 
                
1786
 
                if (strncmp(unixPath, "/tmp", strlen("/tmp")) == 0) {
1787
 
                        unixPath += 4;                                                                                                                  // Skip the slash
1788
 
                        if (*unixPath == PR_DIRECTORY_SEPARATOR)
1789
 
                                unixPath++;                                                                                                             // Skip the slash
1790
 
                        err = FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder,    // Create if needed
1791
 
                                                                &foundVRefNum, &foundDirID);
1792
 
                }
1793
 
                
1794
 
                else if (strncmp(unixPath, "/usr", strlen("/usr")) == 0) {
1795
 
                
1796
 
                        int             usrNetscapePathLen;
1797
 
                        
1798
 
                        usrNetscapePathLen = strlen("/usr/local/netscape/");
1799
 
                
1800
 
                        if (strncmp(unixPath, "/usr/local/netscape/", usrNetscapePathLen) == 0) {
1801
 
                                unixPath += usrNetscapePathLen;                         
1802
 
//                              err = FindPreferencesFolder(&foundVRefNum, &foundDirID);
1803
 
                                err = paramErr;
1804
 
                                isNetscapeDir = true;
1805
 
                        }
1806
 
                        
1807
 
                        else {
1808
 
                                dprintf("Unable to translate Unix file path %s to Mac path\n", unixPath);
1809
 
                                err = -1;
1810
 
                                goto Exit_ConvertUnixPathToMacPath;
1811
 
                        }
1812
 
 
1813
 
                }
1814
 
                
1815
 
                else {
1816
 
                        // This is a root relative directory, we�ll just convert the whole thing.
1817
 
                        err = CreateMacPathFromUnixPath(unixPath, macPath);
1818
 
                        goto Exit_ConvertUnixPathToMacPath;
1819
 
                }
1820
 
        
1821
 
                // We�re dealing with a special folder
1822
 
                if (err == noErr)
1823
 
                        // Get the path to the root-relative directory
1824
 
                        err = GetFullPath(foundVRefNum, foundDirID, macPath, &pathBufferSize);          // mallocs macPath
1825
 
                
1826
 
                if (err == noErr){
1827
 
                        
1828
 
                        // copy over the remaining file name, converting
1829
 
                        if (pathBufferSize < (strlen(*macPath) + strlen(unixPath))) {
1830
 
                                // need to grow string
1831
 
                                *macPath = PR_REALLOC(*macPath, (strlen(*macPath) + strlen(unixPath) + 
1832
 
                                        (isNetscapeDir ? strlen("Netscape �:") : 0)));
1833
 
                                err = (*macPath == NULL ? memFullErr : noErr);
1834
 
                        }
1835
 
                        
1836
 
                        if (isNetscapeDir)
1837
 
                                strcat(*macPath, "Netscape �:");
1838
 
                
1839
 
                        if (err == noErr)
1840
 
                                strcat(*macPath, unixPath);
1841
 
                        
1842
 
                        //      Make sure that all of the /�s are :�s in the final pathname
1843
 
                                
1844
 
                        for (temp = *macPath + strlen(*macPath) - strlen(unixPath); *temp != '\0'; temp++) {
1845
 
                                if (*temp == PR_DIRECTORY_SEPARATOR)
1846
 
                                        *temp = PR_PATH_SEPARATOR;
1847
 
                        }
1848
 
 
1849
 
                }
1850
 
        }
1851
 
        
1852
 
        
1853
 
Exit_ConvertUnixPathToMacPath:
1854
 
 
1855
 
        return err;
1856
 
}
1857
 
 
1858
 
OSErr
1859
 
ConvertUnixPathToFSSpec(const char *unixPath, FSSpec *fileSpec)
1860
 
{
1861
 
    char*                   macPath;
1862
 
    OSErr                   convertError;
1863
 
    int                             len;
1864
 
    
1865
 
    convertError = ConvertUnixPathToMacPath(unixPath, &macPath);
1866
 
    if (convertError != noErr)
1867
 
        return convertError;
1868
 
 
1869
 
    len = strlen(macPath);
1870
 
 
1871
 
    if (*macPath == PR_PATH_SEPARATOR)
1872
 
    {
1873
 
        if (len < sizeof(Str255))
1874
 
        {
1875
 
            short   vRefNum;
1876
 
            long    dirID;
1877
 
            Str255  pascalMacPath;
1878
 
            
1879
 
            convertError = HGetVol(NULL, &vRefNum, &dirID);
1880
 
            if (convertError == noErr)
1881
 
            {
1882
 
                PStrFromCStr(macPath, pascalMacPath);
1883
 
                convertError = FSMakeFSSpec(vRefNum, dirID, pascalMacPath, fileSpec);
1884
 
            }
1885
 
        }
1886
 
        else
1887
 
            convertError = paramErr;
1888
 
    }
1889
 
    else
1890
 
    {
1891
 
        convertError = FSpLocationFromFullPath(len, macPath, fileSpec);
1892
 
    }
1893
 
    
1894
 
    free(macPath);
1895
 
    
1896
 
    return (convertError);
1897
 
}
1898
 
 
1899
 
 
1900
 
#endif
1901
 
 
1902
 
/*
1903
 
 **********************************************************************
1904
 
 *
1905
 
 * Memory-mapped files are not implementable on the Mac.
1906
 
 *
1907
 
 **********************************************************************
1908
 
 */
1909
 
 
1910
 
PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size)
1911
 
{
1912
 
#pragma unused (fmap, size)
1913
 
 
1914
 
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
1915
 
    return PR_FAILURE;
1916
 
}
1917
 
 
1918
 
PRInt32 _MD_GetMemMapAlignment(void)
1919
 
{
1920
 
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
1921
 
    return -1;
1922
 
}
1923
 
 
1924
 
void * _MD_MemMap(
1925
 
    PRFileMap *fmap,
1926
 
    PROffset64 offset,
1927
 
    PRUint32 len)
1928
 
{
1929
 
#pragma unused (fmap, offset, len)
1930
 
 
1931
 
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
1932
 
    return NULL;
1933
 
}
1934
 
 
1935
 
PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
1936
 
{
1937
 
#pragma unused (addr, len)
1938
 
 
1939
 
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
1940
 
    return PR_FAILURE;
1941
 
}
1942
 
 
1943
 
PRStatus _MD_CloseFileMap(PRFileMap *fmap)
1944
 
{
1945
 
#pragma unused (fmap)
1946
 
 
1947
 
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
1948
 
    return PR_FAILURE;
1949
 
}