home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / open.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  27KB  |  847 lines

  1. /***
  2. *open.c - file open
  3. *
  4. *       Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines _open() and _sopen() - open or create a file
  8. *
  9. *******************************************************************************/
  10.  
  11. #ifndef _MAC
  12.  
  13.  
  14. #include <cruntime.h>
  15. #include <oscalls.h>
  16. #include <msdos.h>
  17. #include <errno.h>
  18. #include <fcntl.h>
  19. #include <internal.h>
  20. #include <io.h>
  21. #include <share.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <sys\types.h>
  25. #include <sys\stat.h>
  26. #include <mtdll.h>
  27. #include <stdarg.h>
  28. #include <tchar.h>
  29.  
  30. /***
  31. *int _open(path, flag, pmode) - open or create a file
  32. *
  33. *Purpose:
  34. *       Opens the file and prepares for subsequent reading or writing.
  35. *       the flag argument specifies how to open the file:
  36. *         _O_APPEND -   reposition file ptr to end before every write
  37. *         _O_BINARY -   open in binary mode
  38. *         _O_CREAT -    create a new file* no effect if file already exists
  39. *         _O_EXCL -     return error if file exists, only use with O_CREAT
  40. *         _O_RDONLY -   open for reading only
  41. *         _O_RDWR -     open for reading and writing
  42. *         _O_TEXT -     open in text mode
  43. *         _O_TRUNC -    open and truncate to 0 length (must have write permission)
  44. *         _O_WRONLY -   open for writing only
  45. *         _O_NOINHERIT -handle will not be inherited by child processes.
  46. *       exactly one of _O_RDONLY, _O_WRONLY, _O_RDWR must be given
  47. *
  48. *       The pmode argument is only required when _O_CREAT is specified.  Its
  49. *       flag settings:
  50. *         _S_IWRITE -   writing permitted
  51. *         _S_IREAD -    reading permitted
  52. *         _S_IREAD | _S_IWRITE - both reading and writing permitted
  53. *       The current file-permission maks is applied to pmode before
  54. *       setting the permission (see umask).
  55. *
  56. *       The oflag and mode parameter have different meanings under DOS. See
  57. *       the A_xxx attributes in msdos.inc
  58. *
  59. *       Note, the _creat() function also uses this function but setting up the
  60. *       correct arguments and calling _open(). _creat() sets the __creat_flag
  61. *       to 1 prior to calling _open() so _open() can return correctly. _open()
  62. *       returns the file handle in eax in this case.
  63. *
  64. *Entry:
  65. *       _TSCHAR *path - file name
  66. *       int flag - flags for _open()
  67. *       int pmode - permission mode for new files
  68. *
  69. *Exit:
  70. *       returns file handle of open file if successful
  71. *       returns -1 (and sets errno) if fails
  72. *
  73. *Exceptions:
  74. *
  75. *******************************************************************************/
  76.  
  77. int __cdecl _topen (
  78.         const _TSCHAR *path,
  79.         int oflag,
  80.         ...
  81.         )
  82. {
  83.         va_list ap;
  84.         int pmode;
  85.  
  86.         va_start(ap, oflag);
  87.         pmode = va_arg(ap, int);
  88.         va_end(ap);
  89.  
  90.         /* default sharing mode is DENY NONE */
  91.         return _tsopen(path, oflag, _SH_DENYNO, pmode);
  92. }
  93.  
  94. /***
  95. *int _sopen(path, oflag, shflag, pmode) - opne a file with sharing
  96. *
  97. *Purpose:
  98. *       Opens the file with possible file sharing.
  99. *       shflag defines the sharing flags:
  100. *         _SH_COMPAT -  set compatability mode
  101. *         _SH_DENYRW -  deny read and write access to the file
  102. *         _SH_DENYWR -  deny write access to the file
  103. *         _SH_DENYRD -  deny read access to the file
  104. *         _SH_DENYNO -  permit read and write access
  105. *
  106. *       Other flags are the same as _open().
  107. *
  108. *       SOPEN is the routine used when file sharing is desired.
  109. *
  110. *Entry:
  111. *       _TSCHAR *path - file to open
  112. *       int oflag -     open flag
  113. *       int shflag -    sharing flag
  114. *       int pmode -     permission mode (needed only when creating file)
  115. *
  116. *Exit:
  117. *       returns file handle for the opened file
  118. *       returns -1 and sets errno if fails.
  119. *
  120. *Exceptions:
  121. *
  122. *******************************************************************************/
  123.  
  124. int __cdecl _tsopen (
  125.         const _TSCHAR *path,
  126.         int oflag,
  127.         int shflag,
  128.         ...
  129.         )
  130. {
  131.  
  132.         int fh;                         /* handle of opened file */
  133.         int filepos;                    /* length of file - 1 */
  134.         _TSCHAR ch;                     /* character at end of file */
  135.         char fileflags;                 /* _osfile flags */
  136.         va_list ap;                     /* variable argument (pmode) */
  137.         int pmode;
  138.         HANDLE osfh;                    /* OS handle of opened file */
  139.         DWORD fileaccess;               /* OS file access (requested) */
  140.         DWORD fileshare;                /* OS file sharing mode */
  141.         DWORD filecreate;               /* OS method of opening/creating */
  142.         DWORD fileattrib;               /* OS file attribute flags */
  143.         DWORD isdev;                    /* device indicator in low byte */
  144.         SECURITY_ATTRIBUTES SecurityAttributes;
  145.  
  146.         SecurityAttributes.nLength = sizeof( SecurityAttributes );
  147.         SecurityAttributes.lpSecurityDescriptor = NULL;
  148.  
  149.         if (oflag & _O_NOINHERIT) {
  150.             SecurityAttributes.bInheritHandle = FALSE;
  151.             fileflags = FNOINHERIT;
  152.         }
  153.         else {
  154.             SecurityAttributes.bInheritHandle = TRUE;
  155.             fileflags = 0;
  156.         }
  157.  
  158.         /* figure out binary/text mode */
  159.         if ((oflag & _O_BINARY) == 0)
  160.             if (oflag & _O_TEXT)
  161.                 fileflags |= FTEXT;
  162.             else if (_fmode != _O_BINARY)   /* check default mode */
  163.                 fileflags |= FTEXT;
  164.  
  165.         /*
  166.          * decode the access flags
  167.          */
  168.         switch( oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR) ) {
  169.  
  170.             case _O_RDONLY:         /* read access */
  171.                     fileaccess = GENERIC_READ;
  172.                     break;
  173.             case _O_WRONLY:         /* write access */
  174.                     fileaccess = GENERIC_WRITE;
  175.                     break;
  176.             case _O_RDWR:           /* read and write access */
  177.                     fileaccess = GENERIC_READ | GENERIC_WRITE;
  178.                     break;
  179.             default:                /* error, bad oflag */
  180.                     errno = EINVAL;
  181.                     _doserrno = 0L; /* not an OS error */
  182.                     return -1;
  183.         }
  184.  
  185.         /*
  186.          * decode sharing flags
  187.          */
  188.         switch ( shflag ) {
  189.  
  190.             case _SH_DENYRW:        /* exclusive access */
  191.                 fileshare = 0L;
  192.                 break;
  193.  
  194.             case _SH_DENYWR:        /* share read access */
  195.                 fileshare = FILE_SHARE_READ;
  196.                 break;
  197.  
  198.             case _SH_DENYRD:        /* share write access */
  199.                 fileshare = FILE_SHARE_WRITE;
  200.                 break;
  201.  
  202.             case _SH_DENYNO:        /* share read and write access */
  203.                 fileshare = FILE_SHARE_READ | FILE_SHARE_WRITE;
  204.                 break;
  205.  
  206.             default:                /* error, bad shflag */
  207.                 errno = EINVAL;
  208.                 _doserrno = 0L; /* not an OS error */
  209.                 return -1;
  210.         }
  211.  
  212.         /*
  213.          * decode open/create method flags
  214.          */
  215.         switch ( oflag & (_O_CREAT | _O_EXCL | _O_TRUNC) ) {
  216.             case 0:
  217.             case _O_EXCL:                   // ignore EXCL w/o CREAT
  218.                 filecreate = OPEN_EXISTING;
  219.                 break;
  220.  
  221.             case _O_CREAT:
  222.                 filecreate = OPEN_ALWAYS;
  223.                 break;
  224.  
  225.             case _O_CREAT | _O_EXCL:
  226.             case _O_CREAT | _O_TRUNC | _O_EXCL:
  227.                 filecreate = CREATE_NEW;
  228.                 break;
  229.  
  230.             case _O_TRUNC:
  231.             case _O_TRUNC | _O_EXCL:        // ignore EXCL w/o CREAT
  232.                 filecreate = TRUNCATE_EXISTING;
  233.                 break;
  234.  
  235.             case _O_CREAT | _O_TRUNC:
  236.                 filecreate = CREATE_ALWAYS;
  237.                 break;
  238.  
  239.             default:
  240.                 // this can't happen ... all cases are covered
  241.                 errno = EINVAL;
  242.                 _doserrno = 0L;
  243.                 return -1;
  244.         }
  245.  
  246.         /*
  247.          * decode file attribute flags if _O_CREAT was specified
  248.          */
  249.         fileattrib = FILE_ATTRIBUTE_NORMAL;     /* default */
  250.  
  251.         if ( oflag & _O_CREAT ) {
  252.                 /*
  253.                  * set up variable argument list stuff
  254.                  */
  255.                 va_start(ap, shflag);
  256.                 pmode = va_arg(ap, int);
  257.                 va_end(ap);
  258.  
  259.                 if ( !((pmode & ~_umaskval) & _S_IWRITE) )
  260.                         fileattrib = FILE_ATTRIBUTE_READONLY;
  261.         }
  262.  
  263.         /*
  264.          * Set temporary file (delete-on-close) attribute if requested.
  265.          */
  266.         if ( oflag & _O_TEMPORARY ) {
  267.             fileattrib |= FILE_FLAG_DELETE_ON_CLOSE;
  268.             fileaccess |= DELETE;
  269.         }
  270.  
  271.         /*
  272.          * Set temporary file (delay-flush-to-disk) attribute if requested.
  273.          */
  274.         if ( oflag & _O_SHORT_LIVED )
  275.             fileattrib |= FILE_ATTRIBUTE_TEMPORARY;
  276.  
  277.         /*
  278.          * Set sequential or random access attribute if requested.
  279.          */
  280.         if ( oflag & _O_SEQUENTIAL )
  281.             fileattrib |= FILE_FLAG_SEQUENTIAL_SCAN;
  282.         else if ( oflag & _O_RANDOM )
  283.             fileattrib |= FILE_FLAG_RANDOM_ACCESS;
  284.  
  285.         /*
  286.          * get an available handle.
  287.          *
  288.          * multi-thread note: the returned handle is locked!
  289.          */
  290.         if ( (fh = _alloc_osfhnd()) == -1 ) {
  291.             errno = EMFILE;         /* too many open files */
  292.             _doserrno = 0L;         /* not an OS error */
  293.             return -1;              /* return error to caller */
  294.         }
  295.  
  296.         /*
  297.          * try to open/create the file
  298.          */
  299.         if ( (osfh = CreateFile( (LPTSTR)path,
  300.                                  fileaccess,
  301.                                  fileshare,
  302.                                  &SecurityAttributes,
  303.                                  filecreate,
  304.                                  fileattrib,
  305.                                  NULL ))
  306.              == (HANDLE)0xffffffff )
  307.         {
  308.             /*
  309.              * OS call to open/create file failed! map the error, release
  310.              * the lock, and return -1. note that it's not necessary to
  311.              * call _free_osfhnd (it hasn't been used yet).
  312.              */
  313.             _dosmaperr(GetLastError());     /* map error */
  314.             _unlock_fh(fh);
  315.             return -1;                      /* return error to caller */
  316.         }
  317.  
  318.         /* find out what type of file (file/device/pipe) */
  319.         if ( (isdev = GetFileType(osfh)) == FILE_TYPE_UNKNOWN ) {
  320.             CloseHandle(osfh);
  321.             _dosmaperr(GetLastError());     /* map error */
  322.             _unlock_fh(fh);
  323.             return -1;
  324.         }
  325.  
  326.         /* is isdev value to set flags */
  327.         if (isdev == FILE_TYPE_CHAR)
  328.             fileflags |= FDEV;
  329.         else if (isdev == FILE_TYPE_PIPE)
  330.             fileflags |= FPIPE;
  331.  
  332.         /*
  333.          * the file is open. now, set the info in _osfhnd array
  334.          */
  335.         _set_osfhnd(fh, (long)osfh);
  336.  
  337.         /*
  338.          * mark the handle as open. store flags gathered so far in _osfile
  339.          * array.
  340.          */
  341.         fileflags |= FOPEN;
  342.         _osfile(fh) = fileflags;
  343.  
  344.         if ( !(fileflags & (FDEV|FPIPE)) && (fileflags & FTEXT) &&
  345.              (oflag & _O_RDWR) )
  346.         {
  347.             /* We have a text mode file.  If it ends in CTRL-Z, we wish to
  348.                remove the CTRL-Z character, so that appending will work.
  349.                We do this by seeking to the end of file, reading the last
  350.                byte, and shortening the file if it is a CTRL-Z. */
  351.  
  352.             if ((filepos = _lseek_lk(fh, -1, SEEK_END)) == -1) {
  353.                 /* OS error -- should ignore negative seek error,
  354.                    since that means we had a zero-length file. */
  355.                 if (_doserrno != ERROR_NEGATIVE_SEEK) {
  356.                     _close(fh);
  357.                     _unlock_fh(fh);
  358.                     return -1;
  359.                 }
  360.             }
  361.             else {
  362.                 /* Seek was OK, read the last char in file. The last
  363.                    char is a CTRL-Z if and only if _read returns 0
  364.                    and ch ends up with a CTRL-Z. */
  365.                 ch = 0;
  366.                 if (_read_lk(fh, &ch, 1) == 0 && ch == 26) {
  367.                     /* read was OK and we got CTRL-Z! Wipe it
  368.                        out! */
  369.                     if (_chsize_lk(fh,filepos) == -1)
  370.                     {
  371.                         _close(fh);
  372.                         _unlock_fh(fh);
  373.                         return -1;
  374.                     }
  375.                 }
  376.  
  377.                 /* now rewind the file to the beginning */
  378.                 if ((filepos = _lseek_lk(fh, 0, SEEK_SET)) == -1) {
  379.                     _close(fh);
  380.                     _unlock_fh(fh);
  381.                     return -1;
  382.                 }
  383.             }
  384.         }
  385.  
  386.         /*
  387.          * Set FAPPEND flag if appropriate. Don't do this for devices or pipes.
  388.          */
  389.         if ( !(fileflags & (FDEV|FPIPE)) && (oflag & _O_APPEND) )
  390.             _osfile(fh) |= FAPPEND;
  391.  
  392.         _unlock_fh(fh);                 /* unlock handle */
  393.  
  394.         return fh;                      /* return handle */
  395. }
  396.  
  397.  
  398. #else  /* _MAC */
  399.  
  400.  
  401. #include <cruntime.h>
  402. #include <internal.h>
  403. #include <string.h>
  404. #include <memory.h>
  405. #include <msdos.h>
  406. #include <errno.h>
  407. #include <fcntl.h>
  408. #include <macos\files.h>
  409. #include <string.h>
  410. #include <macos\errors.h>
  411. #include <macos\types.h>
  412. #include <io.h>
  413. #include <share.h>
  414. #include <stdlib.h>
  415. #include <sys\types.h>
  416. #include <sys\stat.h>
  417. #include <stdarg.h>
  418.  
  419. /* define the entry in terminator table */
  420.  
  421. #pragma data_seg(".CRT$XTX")
  422.  
  423. _PVFV pendlowio = _endlowio;
  424.  
  425. #pragma data_seg()
  426.  
  427. /* Mac definitions for ioDenyModes */
  428.  
  429. #define MAC_PERMRD 0x0001
  430. #define MAC_PERMWR 0x0002
  431. #define MAC_DENYRD 0x0010
  432. #define MAC_DENYWR 0x0020
  433.  
  434.  
  435. /***
  436. *int _open(path, flag, pmode) - open or create a file
  437. *
  438. *Purpose:
  439. *       Opens the file and prepares for subsequent reading or writing.
  440. *       the flag argument specifies how to open the file:
  441. *         _O_APPEND -   reposition file ptr to end before every write
  442. *         _O_BINARY -   open in binary mode
  443. *         _O_CREAT -    create a new file* no effect if file already exists
  444. *         _O_EXCL -     return error if file exists, only use with O_CREAT
  445. *         _O_RDONLY -   open for reading only
  446. *         _O_RDWR -     open for reading and writing
  447. *         _O_TEXT -     open in text mode
  448. *         _O_TRUNC -    open and truncate to 0 length (must have write permission)
  449. *         _O_WRONLY -   open for writing only
  450. *       exactly one of _O_RDONLY, _O_WRONLY, _O_RDWR must be given
  451. *
  452. *       The pmode argument is only required when _O_CREAT is specified.  Its
  453. *       flag settings:
  454. *         _S_IWRITE -   writing permitted
  455. *         _S_IREAD -    reading permitted
  456. *         _S_IREAD | _S_IWRITE - both reading and writing permitted
  457. *       The current file-permission masks is applied to pmode before
  458. *       setting the permission (see umask).
  459. *
  460. *       Note, the _creat() function also uses this function but setting up the
  461. *       correct arguments and calling _open().
  462. *
  463. *Entry:
  464. *       char *path - file name
  465. *       int flag - flags for _open()
  466. *       int pmode - permission mode for new files
  467. *
  468. *Exit:
  469. *       returns file handle of open file if successful
  470. *       returns -1 (and sets errno) if fails
  471. *
  472. *Exceptions:
  473. *
  474. *******************************************************************************/
  475.  
  476. int __cdecl _open (
  477.         const char *path,
  478.         int oflag,
  479.         ...
  480.         )
  481. {
  482.         va_list ap;
  483.  
  484.         va_start(ap, oflag);
  485.         /* default sharing mode is DENY NONE */
  486.         return _sopen(path, oflag, _SH_DENYNO, va_arg(ap, int));
  487. }
  488.  
  489. /***
  490. *void __mopen(stpath, fh, ioPermssn, ioDenyModes) - MAC open a file with sharing
  491. *
  492. *Purpose:
  493. *       Worker routine to open a file on the MAC.  It only opens the file.
  494. *  If local open fails it will try AppleShare oepn.
  495. *
  496. *Entry:
  497. *       char *stpath -  file to open (Pascal string)
  498. *       int fh - file handle to use
  499. *       int ioPermssn - persmission modes flags
  500. *       int ioDenyModes -       Deny mode flags
  501. *
  502. *Exit:
  503. *       returns TRUE if successful and sets errno & _osfhnd[fh] &
  504. *                       _osfile[fh] if successful
  505. *
  506. *Exceptions:
  507. *
  508. *******************************************************************************/
  509.  
  510. int __cdecl __mopen (
  511.         char *stpath,
  512.         int fh,
  513.         int ioPermssn,
  514.         int ioDenyModes
  515.         )
  516. {
  517.         HParamBlockRec parm;
  518.         OSErr osErr;
  519.         char sz[256];
  520.         char buf[10];
  521.         char *pch;
  522.  
  523.         //if starts with full path, test the availability of the volume
  524.         memcpy(sz, stpath, (*stpath+1));
  525.         _p2cstr(sz);
  526.  
  527.         if (*sz != ':' && (pch = strchr(sz, ':')) != NULL)
  528.         {
  529.                 *(pch+1) = '\0';
  530.                 _c2pstr(sz);
  531.                 memset(&parm, 0, sizeof(HParamBlockRec));
  532.                 memset(buf, 0, 10);
  533.                 parm.ioParam.ioNamePtr = sz;
  534.                 parm.ioParam.ioBuffer = buf;
  535.                 parm.ioParam.ioReqCount = 6;
  536.                 osErr = PBHGetVolParmsSync(&parm);
  537.  
  538.                 if (!osErr)
  539.                 {
  540.                         if (!(buf[4]&0x8000))
  541.                         {
  542.                                 parm.ioParam.ioNamePtr = stpath;
  543.                                 parm.ioParam.ioVRefNum = 0;
  544.                                 goto local;
  545.                         }
  546.                 }
  547.                 else
  548.                 {
  549.                         _dosmaperr(osErr);
  550.                         return osErr;
  551.                 }
  552.         }
  553.  
  554.         /* try to open the file using Appleshare calls*/
  555.         parm.ioParam.ioNamePtr = stpath;
  556.         parm.ioParam.ioVRefNum = 0;
  557.         parm.accessParam.ioDenyModes = (unsigned char)ioDenyModes;
  558.         _osperm[fh] = (unsigned char)ioDenyModes;
  559.         parm.fileParam.ioDirID = 0;
  560.         parm.ioParam.ioMisc = NULL;
  561.         osErr = PBHOpenDenySync(&parm);
  562.  
  563.         if (osErr == paramErr)
  564.         {
  565. local:
  566.                 /* Try local open */
  567.                 parm.ioParam.ioPermssn = ioPermssn;
  568.                 _osperm[fh] = (unsigned char)ioPermssn;
  569.                 osErr = PBHOpenDFSync(&parm);
  570.         }
  571.  
  572.         if (!osErr)
  573.         {
  574.                 _osfile[fh] |= FOPEN;
  575.                 _osfhnd[fh] = parm.ioParam.ioRefNum;
  576.         }
  577.         else
  578.         {
  579.                 _dosmaperr(osErr);
  580.         }
  581.  
  582.         return osErr;
  583. }
  584.  
  585. /***
  586. *int _sopen(path, oflag, shflag, pmode) - open a file with sharing
  587. *
  588. *Purpose:
  589. *       Opens the file with possible file sharing.
  590. *       shflag defines the sharing flags:
  591. *         _SH_DENYRW -  deny read and write access to the file
  592. *         _SH_DENYNO -  permit read and write access
  593. *
  594. *       Other flags are the same as _open().
  595. *
  596. *       SOPEN is the routine used when file sharing is desired.
  597. *
  598. *Entry:
  599. *       char *path - file to open (C string)
  600. *       int oflag -     open flag
  601. *       int shflag -    sharing flag
  602. *       int pmode -     permission mode (needed only when creating file)
  603. *
  604. *Exit:
  605. *       returns file handle for the opened file
  606. *       returns -1 and sets errno if fails.
  607. *
  608. *Exceptions:
  609. *
  610. *******************************************************************************/
  611.  
  612. int _cdecl _sopen (
  613.         const char *path,
  614.         int oflag,
  615.         int shflag,
  616.         ...
  617.         )
  618. {
  619.  
  620.         int fh;         /* handle of opened file */
  621.         OSErr osErr = 0;
  622.         unsigned char ioPermssn;
  623.         short int ioDenyModes;
  624.         ParamBlockRec parm;
  625.         int pmode;
  626.         va_list ap;                     /* variable argument (pmode) */
  627.         char lpath[256];
  628.  
  629.         if (!*path)
  630.         {
  631.                 errno = ENOENT;
  632.                 return -1;
  633.         }
  634.  
  635.         strcpy(lpath,path);
  636.         _c2pstr(lpath);
  637.  
  638.         /* get a file handle*/
  639.         for (fh = 0; fh <_nfile; fh++)
  640.         {
  641.                 if (!(_osfile[fh] & FOPEN))
  642.                 {
  643.                         break;
  644.                 }
  645.         }
  646.  
  647.         if (fh >= _nfile)
  648.         {
  649.                 errno = EMFILE;
  650.                 _macerrno = 0;
  651.                 return -1;
  652.         }
  653.  
  654.         _osfile[fh] = 0;
  655.                 _osfileflags[fh] = 0;
  656.  
  657.         /* figure out binary/text mode */
  658.  
  659.         switch (oflag  & (_O_BINARY | _O_TEXT))
  660.         {
  661.                 case _O_BINARY:
  662.                         break;
  663.  
  664.                 case _O_TEXT:
  665.                         _osfile[fh] = (unsigned char)FTEXT;
  666.                         break;
  667.  
  668.                 case _O_TEXT | _O_BINARY:
  669.                         errno = EINVAL;
  670.                         return -1;
  671.  
  672.                 default:
  673.                         if (_fmode != _O_BINARY)
  674.                         {
  675.                                 _osfile[fh] = (unsigned char)FTEXT;
  676.                         }
  677.                         break;
  678.         }
  679.  
  680.         /* figure out read/write modes */
  681.  
  682.         switch (oflag & (_O_RDWR | _O_RDONLY | _O_WRONLY))
  683.         {
  684.                 case _O_RDONLY:
  685.                         ioPermssn = fsRdPerm;
  686.                         _osfile[fh] |= FRDONLY;
  687.                         if (oflag & _O_TRUNC)
  688.                         {
  689.                                 errno = EINVAL;
  690.                                 return -1;
  691.                         }
  692.                         ioDenyModes = MAC_PERMRD;
  693.                         break;
  694.  
  695.                 case _O_WRONLY:
  696.                         ioPermssn = fsRdWrShPerm;
  697.                         _osfile[fh] |= FWRONLY;
  698.                         ioDenyModes = MAC_PERMWR;
  699.                         break;
  700.  
  701.                 case _O_RDWR:
  702.                         ioPermssn  = fsRdWrPerm;
  703.                         ioDenyModes = MAC_PERMRD | MAC_PERMWR;
  704.                         break;
  705.  
  706.                 default:
  707.                         errno = EINVAL;
  708.                         return -1;
  709.         }
  710.  
  711.         switch (shflag)
  712.         {
  713.                 case _SH_DENYRD:
  714.                         ioDenyModes |= MAC_DENYRD;
  715.                         break;
  716.  
  717.                 case _SH_DENYWR:
  718.                         ioDenyModes |= MAC_DENYWR;
  719.                         break;
  720.  
  721.                 case _SH_DENYRW:
  722.                         ioDenyModes |= MAC_DENYRD | MAC_DENYWR;
  723.                         break;
  724.  
  725.                 case _SH_DENYNO:
  726.                         if (ioPermssn == fsRdWrPerm)
  727.                         {
  728.                                 ioPermssn = fsRdWrShPerm;
  729.                         }
  730.                         break;
  731.  
  732.                 default:
  733.                         errno = EINVAL;
  734.                         return -1;
  735.         }
  736.  
  737.         if (!(oflag & _O_CREAT && oflag & _O_EXCL))
  738.         {
  739.                 /* try to open the file */
  740.                 if (!__mopen(lpath, fh, ioPermssn, ioDenyModes))
  741.                 {
  742.                         oflag &= ~_O_CREAT;     /*file open - no need to create*/
  743.                 }
  744.         }
  745.  
  746.         /* Didn't work try creating the file if requested */
  747.         if (oflag & _O_CREAT)
  748.         {
  749.                 /* reset errno from mopen, since we can try create*/
  750.                 errno = 0;
  751.                 va_start(ap, shflag);
  752.                 pmode = va_arg(ap, int);
  753.                 pmode &= ~_umaskval;
  754.                 if (!(pmode & (_S_IREAD | _S_IWRITE)))
  755.                 {
  756.                         errno = EINVAL;
  757.                         return -1;
  758.                 }
  759.                 parm.fileParam.ioNamePtr = lpath;
  760.                 parm.fileParam.ioVRefNum = 0;
  761.                 osErr = PBCreateSync(&parm);
  762.                 if (!osErr)
  763.                 {
  764.                         parm.fileParam.ioFDirIndex = 0;
  765.                         PBGetFInfoSync(&parm);
  766.                         parm.fileParam.ioFlFndrInfo.fdType = (_osfile[fh] & FTEXT ? 'TEXT' : '    ');
  767.                         parm.fileParam.ioFlFndrInfo.fdCreator = '    ';
  768.                         PBSetFInfoSync(&parm);
  769.                 }
  770.                 else
  771.                 {
  772.                         if (osErr == dupFNErr && oflag & _O_EXCL)
  773.                         {
  774.                                 errno = EEXIST; /*special case normally returns EACCES*/
  775.                                 _macerrno = osErr;
  776.                         }
  777.                         else
  778.                         {
  779.                                 _dosmaperr(osErr);
  780.                         }
  781.                         return -1;
  782.                 }
  783.                 if (osErr = __mopen(lpath, fh, ioPermssn, ioDenyModes))
  784.                 {
  785.                         _dosmaperr(osErr);
  786.                         return -1;
  787.                 }
  788.                 else if (!(pmode & _S_IWRITE))
  789.                 {
  790.                         PBSetFLockSync(&parm);
  791.                 }
  792.         }
  793.         if (!(_osfile[fh] & FOPEN))
  794.         {
  795.                 goto ErrExit;
  796.         }
  797.  
  798.         parm.ioParam.ioRefNum = _osfhnd[fh];
  799.  
  800.         /* Truncate file */
  801.         if (oflag & _O_TRUNC)
  802.         {
  803.                 parm.ioParam.ioMisc = 0;
  804.                 osErr = PBSetEOFSync(&parm);
  805.                 if (osErr)
  806.                 {
  807.                         _dosmaperr(osErr);
  808.                         goto ErrExit;
  809.                 }
  810.         }
  811.  
  812.         /* get vol reference */
  813.         parm.volumeParam.ioVolIndex = -1;
  814.         parm.ioParam.ioNamePtr = lpath;
  815.         parm.ioParam.ioVRefNum = 0;
  816.         osErr = PBGetVInfoSync(&parm);
  817.         if (osErr)
  818.         {
  819.                 _dosmaperr(osErr);
  820.                 goto ErrExit;
  821.         }
  822.         _osVRefNum[fh] = parm.volumeParam.ioVRefNum;
  823.  
  824.         if (oflag & _O_APPEND)
  825.         {
  826.                 _osfile[fh] |= FAPPEND;
  827.         }
  828.  
  829.         if (oflag & _O_TEMPORARY)
  830.         {
  831.                 _osfileflags[fh] |= FTEMP;
  832.         }
  833.         return fh;                      /* return handle */
  834.  
  835.  
  836. ErrExit:
  837.         if (_osfile[fh] & FOPEN)
  838.         {
  839.                 PBCloseSync(&parm);
  840.                 _osfile[fh] = 0;
  841.         }
  842.         return -1;
  843. }
  844.  
  845.  
  846. #endif  /* _MAC */
  847.