home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / src / md / mac / macio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  47.0 KB  |  1,898 lines

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