OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libstdc++-v3/] [config/] [io/] [basic_file_stdio.cc] - Blame information for rev 20

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 20 jlechner
// Wrapper of C-language FILE struct -*- C++ -*-
2
 
3
// Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4
//
5
// This file is part of the GNU ISO C++ Library.  This library is free
6
// software; you can redistribute it and/or modify it under the
7
// terms of the GNU General Public License as published by the
8
// Free Software Foundation; either version 2, or (at your option)
9
// any later version.
10
 
11
// This library is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
// GNU General Public License for more details.
15
 
16
// You should have received a copy of the GNU General Public License along
17
// with this library; see the file COPYING.  If not, write to the Free
18
// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19
// USA.
20
 
21
// As a special exception, you may use this file as part of a free software
22
// library without restriction.  Specifically, if other files instantiate
23
// templates or use macros or inline functions from this file, or you compile
24
// this file and link it with other files to produce an executable, this
25
// file does not by itself cause the resulting executable to be covered by
26
// the GNU General Public License.  This exception does not however
27
// invalidate any other reasons why the executable file might be covered by
28
// the GNU General Public License.
29
 
30
//
31
// ISO C++ 14882: 27.8  File-based streams
32
//
33
 
34
#include <bits/basic_file.h>
35
#include <fcntl.h>
36
#include <errno.h>
37
 
38
#ifdef _GLIBCXX_HAVE_POLL
39
#include <poll.h>
40
#endif
41
 
42
// Pick up ioctl on Solaris 2.8
43
#ifdef _GLIBCXX_HAVE_UNISTD_H
44
#include <unistd.h>
45
#endif
46
 
47
// Pick up FIONREAD on Solaris 2
48
#ifdef _GLIBCXX_HAVE_SYS_IOCTL_H
49
#define BSD_COMP 
50
#include <sys/ioctl.h>
51
#endif
52
 
53
// Pick up FIONREAD on Solaris 2.5.
54
#ifdef _GLIBCXX_HAVE_SYS_FILIO_H
55
#include <sys/filio.h>
56
#endif
57
 
58
#ifdef _GLIBCXX_HAVE_SYS_UIO_H
59
#include <sys/uio.h>
60
#endif
61
 
62
#if defined(_GLIBCXX_HAVE_S_ISREG) || defined(_GLIBCXX_HAVE_S_IFREG)
63
# include <sys/stat.h>
64
# ifdef _GLIBCXX_HAVE_S_ISREG
65
#  define _GLIBCXX_ISREG(x) S_ISREG(x)
66
# else
67
#  define _GLIBCXX_ISREG(x) (((x) & S_IFMT) == S_IFREG)
68
# endif
69
#endif
70
 
71
#include <limits> // For <off_t>::max() and min() and <streamsize>::max()
72
 
73
namespace __gnu_internal
74
{
75
  // Map ios_base::openmode flags to a string for use in fopen().
76
  // Table of valid combinations as given in [lib.filebuf.members]/2.
77
  static const char*
78
  fopen_mode(std::ios_base::openmode mode)
79
  {
80
    enum
81
      {
82
        in     = std::ios_base::in,
83
        out    = std::ios_base::out,
84
        trunc  = std::ios_base::trunc,
85
        app    = std::ios_base::app,
86
        binary = std::ios_base::binary
87
      };
88
 
89
    switch (mode & (in|out|trunc|app|binary))
90
      {
91
      case (   out                 ): return "w";
92
      case (   out      |app       ): return "a";
93
      case (   out|trunc           ): return "w";
94
      case (in                     ): return "r";
95
      case (in|out                 ): return "r+";
96
      case (in|out|trunc           ): return "w+";
97
 
98
      case (   out          |binary): return "wb";
99
      case (   out      |app|binary): return "ab";
100
      case (   out|trunc    |binary): return "wb";
101
      case (in              |binary): return "rb";
102
      case (in|out          |binary): return "r+b";
103
      case (in|out|trunc    |binary): return "w+b";
104
 
105
      default: return 0; // invalid
106
      }
107
  }
108
 
109
  // Wrapper handling partial write.
110
  static std::streamsize
111
  xwrite(int __fd, const char* __s, std::streamsize __n)
112
  {
113
    std::streamsize __nleft = __n;
114
 
115
    for (;;)
116
      {
117
        const std::streamsize __ret = write(__fd, __s, __nleft);
118
        if (__ret == -1L && errno == EINTR)
119
          continue;
120
        if (__ret == -1L)
121
          break;
122
 
123
        __nleft -= __ret;
124
        if (__nleft == 0)
125
          break;
126
 
127
        __s += __ret;
128
      }
129
 
130
    return __n - __nleft;
131
  }
132
 
133
#ifdef _GLIBCXX_HAVE_WRITEV
134
  // Wrapper handling partial writev.
135
  static std::streamsize
136
  xwritev(int __fd, const char* __s1, std::streamsize __n1,
137
          const char* __s2, std::streamsize __n2)
138
  {
139
    std::streamsize __nleft = __n1 + __n2;
140
    std::streamsize __n1_left = __n1;
141
 
142
    struct iovec __iov[2];
143
    __iov[1].iov_base = const_cast<char*>(__s2);
144
    __iov[1].iov_len = __n2;
145
 
146
    for (;;)
147
      {
148
        __iov[0].iov_base = const_cast<char*>(__s1);
149
        __iov[0].iov_len = __n1_left;
150
 
151
        const std::streamsize __ret = writev(__fd, __iov, 2);
152
        if (__ret == -1L && errno == EINTR)
153
          continue;
154
        if (__ret == -1L)
155
          break;
156
 
157
        __nleft -= __ret;
158
        if (__nleft == 0)
159
          break;
160
 
161
        const std::streamsize __off = __ret - __n1_left;
162
        if (__off >= 0)
163
          {
164
            __nleft -= xwrite(__fd, __s2 + __off, __n2 - __off);
165
            break;
166
          }
167
 
168
        __s1 += __ret;
169
        __n1_left -= __ret;
170
      }
171
 
172
    return __n1 + __n2 - __nleft;
173
  }
174
#endif
175
} // namespace __gnu_internal
176
 
177
namespace std
178
{
179
  // Definitions for __basic_file<char>.
180
  __basic_file<char>::__basic_file(__c_lock* /*__lock*/)
181
  : _M_cfile(NULL), _M_cfile_created(false) { }
182
 
183
  __basic_file<char>::~__basic_file()
184
  { this->close(); }
185
 
186
  __basic_file<char>*
187
  __basic_file<char>::sys_open(__c_file* __file, ios_base::openmode)
188
  {
189
    __basic_file* __ret = NULL;
190
    if (!this->is_open() && __file)
191
      {
192
        int __err;
193
        errno = 0;
194
        do
195
          __err = this->sync();
196
        while (__err && errno == EINTR);
197
        if (!__err)
198
          {
199
            _M_cfile = __file;
200
            _M_cfile_created = false;
201
            __ret = this;
202
          }
203
      }
204
    return __ret;
205
  }
206
 
207
  __basic_file<char>*
208
  __basic_file<char>::sys_open(int __fd, ios_base::openmode __mode)
209
  {
210
    __basic_file* __ret = NULL;
211
    const char* __c_mode = __gnu_internal::fopen_mode(__mode);
212
    if (__c_mode && !this->is_open() && (_M_cfile = fdopen(__fd, __c_mode)))
213
      {
214
        char* __buf = NULL;
215
        _M_cfile_created = true;
216
        if (__fd == 0)
217
          setvbuf(_M_cfile, __buf, _IONBF, 0);
218
        __ret = this;
219
      }
220
    return __ret;
221
  }
222
 
223
  __basic_file<char>*
224
  __basic_file<char>::open(const char* __name, ios_base::openmode __mode,
225
                           int /*__prot*/)
226
  {
227
    __basic_file* __ret = NULL;
228
    const char* __c_mode = __gnu_internal::fopen_mode(__mode);
229
    if (__c_mode && !this->is_open())
230
      {
231
#ifdef _GLIBCXX_USE_LFS
232
        if ((_M_cfile = fopen64(__name, __c_mode)))
233
#else
234
        if ((_M_cfile = fopen(__name, __c_mode)))
235
#endif
236
          {
237
            _M_cfile_created = true;
238
            __ret = this;
239
          }
240
      }
241
    return __ret;
242
  }
243
 
244
  bool
245
  __basic_file<char>::is_open() const
246
  { return _M_cfile != 0; }
247
 
248
  int
249
  __basic_file<char>::fd()
250
  { return fileno(_M_cfile); }
251
 
252
  __c_file*
253
  __basic_file<char>::file()
254
  { return _M_cfile; }
255
 
256
  __basic_file<char>*
257
  __basic_file<char>::close()
258
  {
259
    __basic_file* __ret = static_cast<__basic_file*>(NULL);
260
    if (this->is_open())
261
      {
262
        int __err = 0;
263
        if (_M_cfile_created)
264
          {
265
            // In general, no need to zero errno in advance if checking
266
            // for error first. However, C89/C99 (at variance with IEEE
267
            // 1003.1, f.i.) do not mandate that fclose must set errno
268
            // upon error.
269
            errno = 0;
270
            do
271
              __err = fclose(_M_cfile);
272
            while (__err && errno == EINTR);
273
          }
274
        _M_cfile = 0;
275
        if (!__err)
276
          __ret = this;
277
      }
278
    return __ret;
279
  }
280
 
281
  streamsize
282
  __basic_file<char>::xsgetn(char* __s, streamsize __n)
283
  {
284
    streamsize __ret;
285
    do
286
      __ret = read(this->fd(), __s, __n);
287
    while (__ret == -1L && errno == EINTR);
288
    return __ret;
289
  }
290
 
291
  streamsize
292
  __basic_file<char>::xsputn(const char* __s, streamsize __n)
293
  { return __gnu_internal::xwrite(this->fd(), __s, __n); }
294
 
295
  streamsize
296
  __basic_file<char>::xsputn_2(const char* __s1, streamsize __n1,
297
                               const char* __s2, streamsize __n2)
298
  {
299
    streamsize __ret = 0;
300
#ifdef _GLIBCXX_HAVE_WRITEV
301
    __ret = __gnu_internal::xwritev(this->fd(), __s1, __n1, __s2, __n2);
302
#else
303
    if (__n1)
304
      __ret = __gnu_internal::xwrite(this->fd(), __s1, __n1);
305
 
306
    if (__ret == __n1)
307
      __ret += __gnu_internal::xwrite(this->fd(), __s2, __n2);
308
#endif
309
    return __ret;
310
  }
311
 
312
  streamoff
313
  __basic_file<char>::seekoff(streamoff __off, ios_base::seekdir __way)
314
  {
315
#ifdef _GLIBCXX_USE_LFS
316
    return lseek64(this->fd(), __off, __way);
317
#else
318
    if (__off > numeric_limits<off_t>::max()
319
        || __off < numeric_limits<off_t>::min())
320
      return -1L;
321
    return lseek(this->fd(), __off, __way);
322
#endif
323
  }
324
 
325
  int
326
  __basic_file<char>::sync()
327
  { return fflush(_M_cfile); }
328
 
329
  streamsize
330
  __basic_file<char>::showmanyc()
331
  {
332
#ifdef FIONREAD
333
    // Pipes and sockets.    
334
#ifdef _GLIBCXX_FIONREAD_TAKES_OFF_T
335
    off_t __num = 0;
336
#else
337
    int __num = 0;
338
#endif
339
    int __r = ioctl(this->fd(), FIONREAD, &__num);
340
    if (!__r && __num >= 0)
341
      return __num;
342
#endif    
343
 
344
#ifdef _GLIBCXX_HAVE_POLL
345
    // Cheap test.
346
    struct pollfd __pfd[1];
347
    __pfd[0].fd = this->fd();
348
    __pfd[0].events = POLLIN;
349
    if (poll(__pfd, 1, 0) <= 0)
350
      return 0;
351
#endif   
352
 
353
#if defined(_GLIBCXX_HAVE_S_ISREG) || defined(_GLIBCXX_HAVE_S_IFREG)
354
    // Regular files.
355
#ifdef _GLIBCXX_USE_LFS
356
    struct stat64 __buffer;
357
    const int __err = fstat64(this->fd(), &__buffer);
358
    if (!__err && _GLIBCXX_ISREG(__buffer.st_mode))
359
      {
360
        const streamoff __off = __buffer.st_size - lseek64(this->fd(), 0,
361
                                                           ios_base::cur);
362
        return std::min(__off, streamoff(numeric_limits<streamsize>::max()));
363
      }
364
#else
365
    struct stat __buffer;
366
    const int __err = fstat(this->fd(), &__buffer);
367
    if (!__err && _GLIBCXX_ISREG(__buffer.st_mode))
368
      return __buffer.st_size - lseek(this->fd(), 0, ios_base::cur);
369
#endif
370
#endif
371
    return 0;
372
  }
373
}  // namespace std

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.