1/* This is part of libio/iostream, providing -*- C++ -*- input/output.
2Copyright (C) 1993, 1995, 1999 Free Software Foundation
3
4This file is part of the GNU IO Library.  This library is free
5software; you can redistribute it and/or modify it under the
6terms of the GNU General Public License as published by the
7Free Software Foundation; either version 2, or (at your option)
8any later version.
9
10This library is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this library; see the file COPYING.  If not, write to the Free
17Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19As a special exception, if you link this library with files
20compiled with a GNU compiler to produce an executable, this does not cause
21the resulting executable to be covered by the GNU General Public License.
22This exception does not however invalidate any other reasons why
23the executable file might be covered by the GNU General Public License.
24
25Written by Per Bothner (bothner@cygnus.com). */
26
27#include "iostreamP.h"
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <fcntl.h>
31#include <errno.h>
32#include "builtinbuf.h"
33
34void filebuf::init()
35{
36  _IO_file_init(reinterpret_cast<_IO_FILE_plus*>(this));
37}
38
39filebuf::filebuf()
40{
41  _IO_file_init(reinterpret_cast<_IO_FILE_plus*>(this));
42}
43
44#if !_IO_UNIFIED_JUMPTABLES
45/* This is like "new filebuf()", but it uses the _IO_file_jump jumptable,
46   for eficiency. */
47
48filebuf* filebuf::__new()
49{
50  filebuf *fb = new filebuf;
51  _IO_JUMPS(fb) = &_IO_file_jumps;
52  fb->_vtable() = builtinbuf_vtable;
53  return fb;
54}
55#endif
56
57filebuf::filebuf(int fd)
58{
59  _IO_file_init(reinterpret_cast<_IO_FILE_plus*>(this));
60  _IO_file_attach(this, fd);
61}
62
63filebuf::filebuf(int fd, char* p, int len)
64{
65  _IO_file_init(reinterpret_cast<_IO_FILE_plus*>(this));
66  _IO_file_attach(this, fd);
67  setbuf(p, len);
68}
69
70filebuf::~filebuf()
71{
72  if (_IO_file_is_open(this))
73    {
74      _IO_do_flush (this);
75      if (!(xflags() & _IO_DELETE_DONT_CLOSE))
76	_IO_SYSCLOSE (this);
77    }
78}
79
80filebuf* filebuf::open(const char *filename, ios::openmode mode, int prot)
81{
82  if (_IO_file_is_open (this))
83    return NULL;
84  int posix_mode;
85  int read_write;
86  if (mode & ios::app)
87    mode |= ios::out;
88  if ((mode & (ios::in|ios::out)) == (ios::in|ios::out)) {
89    posix_mode = O_RDWR;
90    read_write = 0;
91  }
92  else if (mode & ios::out)
93    posix_mode = O_WRONLY, read_write = _IO_NO_READS;
94  else if (mode & (int)ios::in)
95    posix_mode = O_RDONLY, read_write = _IO_NO_WRITES;
96  else
97    posix_mode = 0, read_write = _IO_NO_READS+_IO_NO_WRITES;
98  if (mode & ios::binary)
99    {
100      mode &= ~ios::binary;
101#ifdef O_BINARY
102      /* This is a (mis-)feature of DOS/Windows C libraries. */
103      posix_mode |= O_BINARY;
104#endif
105    }
106  if ((mode & (int)ios::trunc) || mode == (int)ios::out)
107    posix_mode |= O_TRUNC;
108  if (mode & ios::app)
109    posix_mode |= O_APPEND, read_write |= _IO_IS_APPENDING;
110  if (!(mode & (int)ios::nocreate) && mode != ios::in)
111    posix_mode |= O_CREAT;
112  if (mode & (int)ios::noreplace)
113    posix_mode |= O_EXCL;
114#if _G_HAVE_IO_FILE_OPEN
115  if (!_IO_file_open (this, filename, posix_mode, prot,
116		      read_write, 0))
117    return NULL;
118  if (mode & ios::ate) {
119    if (pubseekoff(0, ios::end) == EOF) {
120      _IO_un_link (reinterpret_cast<_IO_FILE_plus*>(this));
121      return NULL;
122    }
123  }
124  return this;
125#else
126  int fd = ::open(filename, posix_mode, prot);
127  if (fd < 0)
128    return NULL;
129  _fileno = fd;
130  xsetflags(read_write, _IO_NO_READS+_IO_NO_WRITES+_IO_IS_APPENDING);
131  if (mode & ios::ate) {
132    if (pubseekoff(0, ios::end) == EOF)
133      return NULL;
134  }
135  _IO_link_in(this);
136  return this;
137#endif
138}
139
140filebuf* filebuf::open(const char *filename, const char *mode)
141{
142#if _G_IO_IO_FILE_VERSION == 0x20001
143  return (filebuf*)_IO_file_fopen(this, filename, mode, 0);
144#else
145  return (filebuf*)_IO_file_fopen(this, filename, mode);
146#endif
147}
148
149filebuf* filebuf::attach(int fd)
150{
151  return (filebuf*)_IO_file_attach(this, fd);
152}
153
154streambuf* filebuf::setbuf(char* p, int len)
155{
156  return (streambuf*)_IO_file_setbuf (this, p, len);
157}
158
159int filebuf::doallocate() { return _IO_file_doallocate(this); }
160
161int filebuf::overflow(int c)
162{
163  return _IO_file_overflow(this, c);
164}
165
166int filebuf::underflow()
167{
168  return _IO_file_underflow(this);
169}
170
171int filebuf::sync()
172{
173  return _IO_file_sync(this);
174}
175
176streampos filebuf::seekoff(streamoff offset, _seek_dir dir, int mode)
177{
178  return _IO_file_seekoff (this, offset, dir, mode);
179}
180
181filebuf* filebuf::close()
182{
183  return (_IO_file_close_it(this) ? (filebuf*)NULL : this);
184}
185
186streamsize filebuf::sys_read(char* buf, streamsize size)
187{
188  return _IO_file_read(this, buf, size);
189}
190
191streampos filebuf::sys_seek(streamoff offset, _seek_dir dir)
192{
193  return _IO_file_seek(this, offset, dir);
194}
195
196streamsize filebuf::sys_write(const char *buf, streamsize n)
197{
198  return _IO_file_write (this, buf, n);
199}
200
201int filebuf::sys_stat(void* st)
202{
203  return _IO_file_stat (this, st);
204}
205
206int filebuf::sys_close()
207{
208  return _IO_file_close (this);
209}
210
211streamsize filebuf::xsputn(const char *s, streamsize n)
212{
213  return _IO_file_xsputn(this, s, n);
214}
215
216streamsize filebuf::xsgetn(char *s, streamsize n)
217{
218    // FIXME: OPTIMIZE THIS (specifically, when unbuffered()).
219    return streambuf::xsgetn(s, n);
220}
221
222// Non-ANSI AT&T-ism:  Default open protection.
223const int filebuf::openprot = 0644;
224