update for HEAD-2003091401
[reactos.git] / lib / msvcrt / stdio / fwrite.c
1 #include <msvcrt/stdio.h>
2 #include <msvcrt/stdlib.h>
3 #include <msvcrt/string.h>
4 #include <msvcrt/errno.h>
5 #include <msvcrt/internal/file.h>
6 #define NDEBUG
7 #include <msvcrt/msvcrtdbg.h>
8
9
10 /*
11  * @implemented
12  */
13 size_t fwrite(const void *vptr, size_t size, size_t count, FILE *iop)
14 {
15   size_t to_write, n_written;
16   unsigned char *ptr = (unsigned char *)vptr;
17   int copy;
18
19   DPRINT("fwrite(%x, %d, %d, %x)\n", vptr, size, count, iop);
20
21   to_write = size*count;
22   if (!OPEN4WRITING(iop))
23     {
24       __set_errno (EINVAL);
25       return 0;
26     }
27
28   if (iop == NULL)
29     {
30       __set_errno (EINVAL);
31       return 0;
32     }
33
34   if (ferror (iop))
35     return 0;
36   if (vptr == NULL || to_write == 0)
37     return 0;
38
39   if (iop->_base == NULL && !(iop->_flag&_IONBF))
40   {
41      if (EOF == _flsbuf(*ptr++, iop))
42         return 0;
43      if (--to_write == 0)
44         return 1;
45   }
46
47   if (iop->_flag & _IOLBF)
48   {
49      while (to_write > 0)
50      {
51         if (EOF == putc(*ptr++, iop))
52         {
53            iop->_flag |= _IOERR;
54            break;
55         }
56         to_write--;
57      }
58   }
59   else
60   {
61      if (iop->_cnt > 0 && to_write > 0)
62      {
63         copy = min(iop->_cnt, to_write);
64         memcpy(iop->_ptr, ptr, copy);
65         ptr += copy;
66         iop->_ptr += copy;
67         iop->_cnt -= copy;
68         to_write -= copy;
69         iop->_flag |= _IODIRTY;
70      }
71
72      if (to_write > 0)
73      {
74         // if the buffer is dirty it will have to be written now
75         // otherwise the file pointer won't match anymore.
76         fflush(iop);
77         if (to_write >= iop->_bufsiz)
78         {
79            while (to_write > 0)
80            {
81               n_written = _write(fileno(iop), ptr, to_write);
82               if (n_written <= 0)
83               {
84                  iop->_flag |= _IOERR;
85                  break;
86               }
87               to_write -= n_written;
88               ptr += n_written;
89            }
90
91            // check to see if this will work with in combination with ungetc
92
93            // the file buffer is empty and there is no read ahead information anymore.
94            iop->_flag &= ~_IOAHEAD;
95         }
96         else
97         {
98            if (EOF != _flsbuf(*ptr++, iop))
99            {
100               if (--to_write > 0)
101               {
102                  memcpy(iop->_ptr, ptr, to_write);
103                  iop->_ptr += to_write;
104                  iop->_cnt -= to_write;
105                  iop->_flag |= _IODIRTY;
106                  return count;
107               }
108            }
109         }
110      }
111   }
112
113   return count - (to_write/size);
114 }