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

  1. /***
  2. *write.c - write to a file handle
  3. *
  4. *       Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines _write() - write to a file handle
  8. *
  9. *******************************************************************************/
  10.  
  11. #ifndef _MAC
  12.  
  13.  
  14. #include <cruntime.h>
  15. #include <oscalls.h>
  16. #include <io.h>
  17. #include <errno.h>
  18. #include <msdos.h>
  19. #include <mtdll.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <internal.h>
  23.  
  24. #define BUF_SIZE    1025    /* size of LF translation buffer */
  25.  
  26. #define LF '\n'      /* line feed */
  27. #define CR '\r'      /* carriage return */
  28. #define CTRLZ 26     /* ctrl-z */
  29.  
  30. /***
  31. *int _write(fh, buf, cnt) - write bytes to a file handle
  32. *
  33. *Purpose:
  34. *       Writes count bytes from the buffer to the handle specified.
  35. *       If the file was opened in text mode, each LF is translated to
  36. *       CR-LF.  This does not affect the return value.  In text
  37. *       mode ^Z indicates end of file.
  38. *
  39. *       Multi-thread notes:
  40. *       (1) _write() - Locks/unlocks file handle
  41. *           _write_lk() - Does NOT lock/unlock file handle
  42. *
  43. *Entry:
  44. *       int fh - file handle to write to
  45. *       char *buf - buffer to write from
  46. *       unsigned int cnt - number of bytes to write
  47. *
  48. *Exit:
  49. *       returns number of bytes actually written.
  50. *       This may be less than cnt, for example, if out of disk space.
  51. *       returns -1 (and set errno) if fails.
  52. *
  53. *Exceptions:
  54. *
  55. *******************************************************************************/
  56.  
  57. #ifdef _MT
  58.  
  59. /* define normal version that locks/unlocks, validates fh */
  60. int __cdecl _write (
  61.         int fh,
  62.         const void *buf,
  63.         unsigned cnt
  64.         )
  65. {
  66.         int r;                          /* return value */
  67.  
  68.         /* validate handle */
  69.         if ( ((unsigned)fh >= (unsigned)_nhandle) ||
  70.              !(_osfile(fh) & FOPEN) )
  71.         {
  72.                 /* out of range -- return error */
  73.                 errno = EBADF;
  74.                 _doserrno = 0;  /* not o.s. error */
  75.                 return -1;
  76.         }
  77.  
  78.         _lock_fh(fh);                   /* lock file */
  79.         r = _write_lk(fh, buf, cnt);    /* write bytes */
  80.         _unlock_fh(fh);                 /* unlock file */
  81.  
  82.         return r;
  83. }
  84.  
  85. /* now define version that doesn't lock/unlock, validate fh */
  86. int __cdecl _write_lk (
  87.         int fh,
  88.         const void *buf,
  89.         unsigned cnt
  90.         )
  91. {
  92.         int lfcount;            /* count of line feeds */
  93.         int charcount;          /* count of chars written so far */
  94.         int written;            /* count of chars written on this write */
  95.         ULONG dosretval;        /* o.s. return value */
  96.         char ch;                /* current character */
  97.         char *p, *q;            /* pointers into buf and lfbuf resp. */
  98.         char lfbuf[BUF_SIZE];   /* lf translation buffer */
  99.  
  100. #else  /* _MT */
  101.  
  102. /* now define normal version */
  103. int __cdecl _write (
  104.         int fh,
  105.         const void *buf,
  106.         unsigned cnt
  107.         )
  108. {
  109.         int lfcount;            /* count of line feeds */
  110.         int charcount;          /* count of chars written so far */
  111.         int written;            /* count of chars written on this write */
  112.         ULONG dosretval;        /* o.s. return value */
  113.         char ch;                /* current character */
  114.         char *p, *q;            /* pointers into buf and lfbuf resp. */
  115.         char lfbuf[BUF_SIZE];   /* lf translation buffer */
  116.  
  117.         /* validate handle */
  118.         if ( ((unsigned)fh >= (unsigned)_nhandle) ||
  119.              !(_osfile(fh) & FOPEN) )
  120.         {
  121.                 /* out of range -- return error */
  122.                 errno = EBADF;
  123.                 _doserrno = 0;  /* not o.s. error */
  124.                 return -1;
  125.         }
  126.  
  127. #endif  /* _MT */
  128.  
  129.         lfcount = charcount = 0;        /* nothing written yet */
  130.  
  131.         if (cnt == 0)
  132.                 return 0;               /* nothing to do */
  133.  
  134.  
  135.         if (_osfile(fh) & FAPPEND) {
  136.                 /* appending - seek to end of file; ignore error, because maybe
  137.                    file doesn't allow seeking */
  138.                 (void)_lseek_lk(fh, 0, FILE_END);
  139.         }
  140.  
  141.         /* check for text mode with LF's in the buffer */
  142.  
  143.         if ( _osfile(fh) & FTEXT ) {
  144.                 /* text mode, translate LF's to CR/LF's on output */
  145.  
  146.                 p = (char *)buf;        /* start at beginning of buffer */
  147.                 dosretval = 0;          /* no OS error yet */
  148.  
  149.                 while ( (unsigned)(p - (char *)buf) < cnt ) {
  150.                         q = lfbuf;      /* start at beginning of lfbuf */
  151.  
  152.                         /* fill the lf buf, except maybe last char */
  153.                         while ( q - lfbuf < BUF_SIZE - 1 &&
  154.                             (unsigned)(p - (char *)buf) < cnt ) {
  155.                                 ch = *p++;
  156.                                 if ( ch == LF ) {
  157.                                         ++lfcount;
  158.                                         *q++ = CR;
  159.                                 }
  160.                                 *q++ = ch;
  161.                         }
  162.  
  163.                         /* write the lf buf and update total */
  164.                         if ( WriteFile( (HANDLE)_osfhnd(fh),
  165.                                         lfbuf,
  166.                                         q - lfbuf,
  167.                                         (LPDWORD)&written,
  168.                                         NULL) )
  169.                         {
  170.                                 charcount += written;
  171.                                 if (written < q - lfbuf)
  172.                                         break;
  173.                         }
  174.                         else {
  175.                                 dosretval = GetLastError();
  176.                                 break;
  177.                         }
  178.                 }
  179.         }
  180.         else {
  181.                 /* binary mode, no translation */
  182.                 if ( WriteFile( (HANDLE)_osfhnd(fh),
  183.                                 (LPVOID)buf,
  184.                                 cnt,
  185.                                (LPDWORD)&written,
  186.                                 NULL) )
  187.                 {
  188.                         dosretval = 0;
  189.                         charcount = written;
  190.                 }
  191.                 else
  192.                         dosretval = GetLastError();
  193.         }
  194.  
  195.         if (charcount == 0) {
  196.                 /* If nothing was written, first check if an o.s. error,
  197.                    otherwise we return -1 and set errno to ENOSPC,
  198.                    unless a device and first char was CTRL-Z */
  199.                 if (dosretval != 0) {
  200.                         /* o.s. error happened, map error */
  201.                         if (dosretval == ERROR_ACCESS_DENIED) {
  202.                             /* wrong read/write mode should return EBADF, not
  203.                                EACCES */
  204.                                 errno = EBADF;
  205.                                 _doserrno = dosretval;
  206.                         }
  207.                         else
  208.                                 _dosmaperr(dosretval);
  209.                         return -1;
  210.                 }
  211.                 else if ((_osfile(fh) & FDEV) && *(char *)buf == CTRLZ)
  212.                         return 0;
  213.                 else {
  214.                         errno = ENOSPC;
  215.                         _doserrno = 0;  /* no o.s. error */
  216.                         return -1;
  217.                 }
  218.         }
  219.         else
  220.                 /* return adjusted bytes written */
  221.                 return charcount - lfcount;
  222. }
  223.  
  224.  
  225. #else  /* _MAC */
  226.  
  227.  
  228. #include <cruntime.h>
  229. #include <errno.h>
  230. #include <msdos.h>
  231. #include <stdlib.h>
  232. #include <internal.h>
  233. #include <macos\files.h>
  234. #include <macos\errors.h>
  235. #include <mpw.h>
  236.  
  237. /***
  238. *int _write(fh, buf, cnt) - write bytes to a file handle
  239. *
  240. *Purpose:
  241. *       Writes count bytes from the buffer to the handle specified.
  242. *
  243. *Entry:
  244. *       int fh - file handle to write to
  245. *       char *buf - buffer to write from
  246. *       unsigned int cnt - number of bytes to write
  247. *
  248. *Exit:
  249. *       returns number of bytes actually written.
  250. *       This may be less than cnt, for example, if out of disk space.
  251. *       returns -1 (and set errno) if fails.
  252. *
  253. *Exceptions:
  254. *
  255. *******************************************************************************/
  256.  
  257. int __cdecl _write (
  258.         int fh,
  259.         const void *buf,
  260.         unsigned cnt
  261.         )
  262. {
  263.         OSErr osErr;
  264.         int cbReturn;
  265.  
  266.         /* validate handle */
  267.         if ( ((unsigned)fh >= (unsigned)_nfile) || !(_osfile[fh] & FOPEN) ||
  268.              (_osfile[fh] & FRDONLY) )
  269.         {
  270.                 /* out of range -- return error */
  271.                 errno = EBADF;
  272.                 _macerrno = 0;
  273.                 return -1;
  274.         }
  275.         if (_osfile[fh] & FDEV)
  276.         {
  277.                 MPWFILE *pparm;
  278.  
  279.                  /* MPW console */
  280.  
  281.                 pparm =  (MPWFILE *)_osfhnd[fh];
  282.                 pparm->count = cnt;
  283.                 (const void *)(pparm->pBuff) = buf;
  284.                 osErr = (*((pparm->pDevice)->write))(pparm);
  285.                 if (osErr)
  286.                 {
  287.                         osErr = pparm->err;
  288.                 }
  289.                 else
  290.                 {
  291.                         cbReturn = cnt - pparm->count;
  292.                 }
  293.         }
  294.         else
  295.         {
  296.                 ParamBlockRec parm;
  297.  
  298.                 /* File */
  299.  
  300.                 parm.ioParam.ioRefNum = _osfhnd[fh];
  301.                 (const void *)parm.ioParam.ioBuffer = buf;
  302.                 parm.ioParam.ioReqCount = cnt;
  303.                 parm.ioParam.ioPosOffset = 0;
  304.                 if ( _osfile[fh] & FAPPEND)
  305.                 {
  306.                         parm.ioParam.ioPosMode = fsFromLEOF;
  307.                 }
  308.                 else
  309.                 {
  310.                         parm.ioParam.ioPosMode = fsAtMark;
  311.                 }
  312.                 osErr = PBWriteSync(&parm);
  313.                 cbReturn = parm.ioParam.ioActCount;
  314.         }
  315.  
  316.         if (!osErr)
  317.         {
  318.                 return cbReturn;
  319.         }
  320.         else
  321.         {
  322.                 _dosmaperr(osErr);
  323.                 return -1;
  324.         }
  325.  
  326. }
  327.  
  328.  
  329. #endif  /* _MAC */
  330.