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