1 /**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the mingw-w64 runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6 #include <stdio.h>
7 #include <io.h>
8 #include <errno.h>
9 #include <internal.h>
10
11 #define _IOYOURBUF 0x0100
12 #define _IOSETVBUF 0x0400
13 #define _IOFEOF 0x0800
14 #define _IOFLRTN 0x1000
15 #define _IOCTRLZ 0x2000
16 #define _IOCOMMIT 0x4000
17
18 /* General use macros */
19
20 #define inuse(s) ((s)->_flag & (_IOREAD|_IOWRT|_IORW))
21 #define mbuf(s) ((s)->_flag & _IOMYBUF)
22 #define nbuf(s) ((s)->_flag & _IONBF)
23 #define ybuf(s) ((s)->_flag & _IOYOURBUF)
24 #define bigbuf(s) ((s)->_flag & (_IOMYBUF|_IOYOURBUF))
25 #define anybuf(s) ((s)->_flag & (_IOMYBUF|_IONBF|_IOYOURBUF))
26
27 #define _INTERNAL_BUFSIZ 4096
28 #define _SMALL_BUFSIZ 512
29
30 #define FOPEN 0x01 /* file handle open */
31 #define FEOFLAG 0x02 /* end of file has been encountered */
32 #define FCRLF 0x04 /* CR-LF across read buffer (in text mode) */
33 #define FPIPE 0x08 /* file handle refers to a pipe */
34 #define FNOINHERIT 0x10 /* file handle opened _O_NOINHERIT */
35 #define FAPPEND 0x20 /* file handle opened O_APPEND */
36 #define FDEV 0x40 /* file handle refers to device */
37 #define FTEXT 0x80 /* file handle is in text mode */
38
39 _CRTIMP __int64 __cdecl _lseeki64(int fh,__int64 pos,int mthd);
40 __int64 __cdecl _ftelli64(FILE *str);
41
42 #if !defined(__arm__) && !defined(__aarch64__) /* we have F_ARM_ANY(_fseeki64) in msvcrt.def.in */
43 int __cdecl _flush (FILE *str);
44
_flush(FILE * str)45 int __cdecl _flush (FILE *str)
46 {
47 FILE *stream;
48 int rc = 0; /* assume good return */
49 __int64 nchar;
50
51 stream = str;
52 if ((stream->_flag & (_IOREAD | _IOWRT)) == _IOWRT && bigbuf(stream)
53 && (nchar = (__int64) (stream->_ptr - stream->_base)) > 0ll)
54 {
55 if ( _write(_fileno(stream), stream->_base, nchar) == nchar) {
56 if (_IORW & stream->_flag)
57 stream->_flag &= ~_IOWRT;
58 } else {
59 stream->_flag |= _IOERR;
60 rc = EOF;
61 }
62 }
63 stream->_ptr = stream->_base;
64 stream->_cnt = 0ll;
65 return rc;
66 }
67
_fseeki64(FILE * str,__int64 offset,int whence)68 int __cdecl _fseeki64(FILE *str,__int64 offset,int whence)
69 {
70 FILE *stream;
71 /* Init stream pointer */
72 stream = str;
73 errno=0;
74 if(!stream || ((whence != SEEK_SET) && (whence != SEEK_CUR) && (whence != SEEK_END)))
75 {
76 errno=EINVAL;
77 return -1;
78 }
79 /* Clear EOF flag */
80 stream->_flag &= ~_IOEOF;
81
82 if (whence == SEEK_CUR) {
83 offset += _ftelli64(stream);
84 whence = SEEK_SET;
85 }
86 /* Flush buffer as necessary */
87 _flush(stream);
88
89 /* If file opened for read/write, clear flags since we don't know
90 what the user is going to do next. If the file was opened for
91 read access only, decrease _bufsiz so that the next _filbuf
92 won't cost quite so much */
93
94 if (stream->_flag & _IORW)
95 stream->_flag &= ~(_IOWRT|_IOREAD);
96 else if ( (stream->_flag & _IOREAD) && (stream->_flag & _IOMYBUF) &&
97 !(stream->_flag & _IOSETVBUF) )
98 stream->_bufsiz = _SMALL_BUFSIZ;
99
100 /* Seek to the desired locale and return. */
101
102 return (_lseeki64(_fileno(stream), offset, whence) == -1ll ? -1 : 0);
103 }
104
105 int __cdecl (*__MINGW_IMP_SYMBOL(_fseeki64))(FILE *, __int64, int) = _fseeki64;
106 #endif /* !defined(__arm__) && !defined(__aarch64__) */
107
_ftelli64(FILE * str)108 __int64 __cdecl _ftelli64(FILE *str)
109 {
110 FILE *stream;
111 size_t offset;
112 __int64 filepos;
113 register char *p;
114 char *max;
115 int fd;
116 size_t rdcnt = 0;
117
118 errno=0;
119 stream = str;
120 fd = _fileno(stream);
121 if (stream->_cnt < 0ll) stream->_cnt = 0ll;
122 if ((filepos = _lseeki64(fd, 0ll, SEEK_CUR)) < 0L)
123 return -1ll;
124
125 if (!bigbuf(stream)) /* _IONBF or no buffering designated */
126 return (filepos - (__int64) stream->_cnt);
127
128 offset = (size_t)(stream->_ptr - stream->_base);
129
130 if (stream->_flag & (_IOWRT|_IOREAD))
131 {
132 if (_osfile(fd) & FTEXT)
133 for (p = stream->_base; p < stream->_ptr; p++)
134 if (*p == '\n') /* adjust for '\r' */
135 offset++;
136 }
137 else if (!(stream->_flag & _IORW)) {
138 errno=EINVAL;
139 return -1ll;
140 }
141 if (filepos == 0ll)
142 return ((__int64)offset);
143
144 if (stream->_flag & _IOREAD) /* go to preceding sector */
145 {
146 if (stream->_cnt == 0ll) /* filepos holds correct location */
147 offset = 0ll;
148 else
149 {
150 rdcnt = ((size_t) stream->_cnt) + ((size_t) (size_t)(stream->_ptr - stream->_base));
151 if (_osfile(fd) & FTEXT) {
152 if (_lseeki64(fd, 0ll, SEEK_END) == filepos) {
153 max = stream->_base + rdcnt;
154 for (p = stream->_base; p < max; p++)
155 if (*p == '\n') /* adjust for '\r' */
156 rdcnt++;
157 if (stream->_flag & _IOCTRLZ)
158 ++rdcnt;
159 } else {
160 _lseeki64(fd, filepos, SEEK_SET);
161 if ( (rdcnt <= _SMALL_BUFSIZ) && (stream->_flag & _IOMYBUF) &&
162 !(stream->_flag & _IOSETVBUF))
163 rdcnt = _SMALL_BUFSIZ;
164 else
165 rdcnt = stream->_bufsiz;
166 if (_osfile(fd) & FCRLF)
167 ++rdcnt;
168 }
169 } /* end if FTEXT */
170 }
171 filepos -= (__int64)rdcnt;
172 } /* end else stream->_cnt != 0 */
173 return (filepos + (__int64)offset);
174 }
175
176 __int64 __cdecl (*__MINGW_IMP_SYMBOL(_ftelli64))(FILE *) = _ftelli64;
177
178