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