Disable all code related to libXp
[oweals/cde.git] / cde / programs / dtinfo / DtMmdb / utility / filebuf.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: filebuf.C /main/9 1996/10/04 10:44:52 drk $ */
24
25 #include <stdio.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28
29 #if !defined(hpux) && !defined(__osf__) && !defined(USL) && \
30     !defined(linux) && !defined(CSRG_BASED) && !defined(sun)
31 #include <sysent.h>
32 #endif
33
34 #include <fcntl.h>
35 #include <string.h>
36
37 #include "utility/c_filebuf.h"
38
39 #include <sys/stat.h>
40
41 filebuf::~filebuf() 
42 {
43    close();
44    delete _name;
45 }
46
47 /////////////////////////////////////////////
48 // only current_pos is used.
49 /////////////////////////////////////////////
50
51 filebuf::filebuf(int __fd) :
52    _fd(__fd), _prev_action(-1), _name(0),
53    current_pos(0), new_pos(0), default_new_pos(0)
54 {
55    _mode = 0;
56
57    struct stat statbuf;
58    if ( fstat(_fd, &statbuf ) == 0 ) {
59      if ( BIT_TEST( statbuf.st_mode, S_IRUSR) )
60         _mode |= ios::in;
61
62      if ( BIT_TEST( statbuf.st_mode, S_IWUSR) )
63         _mode |= ios::out;
64    } else {
65      _mode = 0;
66    }
67 }
68
69 filebuf::filebuf(const char* name, int mode, int protect) :
70    _fd(-1), _prev_action(-1), _name(strdup(name)),
71    current_pos(0), new_pos(0), default_new_pos(0)
72 {
73    open(name, mode, protect);
74 }
75
76 int filebuf::open(const char* name, int mode, int protect)
77 {
78    if ( _fd != -1 && 
79         _name && strcmp(name, _name) == 0 && 
80         mode == _mode 
81    )
82       return 0;
83
84
85    close();
86
87    delete _name; _name = strdup(name);
88
89    _mode = mode;
90
91    int flag = 0;
92
93    if ( BIT_TEST(mode, ios::app) || BIT_TEST(mode, ios::out) ) {
94       if ( BIT_TEST(mode, ios::in) )
95          flag |= O_RDWR;
96       else
97          flag |= O_WRONLY;
98    } else {
99       if ( BIT_TEST(mode, ios::in) )
100          flag |= O_RDONLY;
101    }
102
103    if ( BIT_TEST(mode, ios::trunc) ||
104         (
105          BIT_TEST(mode, ios::trunc) && 
106          !(BIT_TEST(mode, ios::in)||BIT_TEST(mode, ios::app))
107         ) 
108       ) 
109       flag |= O_TRUNC;
110   
111 //fprintf(stderr, "flag=%x\n", flag);
112
113    _fd = ::open(name, flag);
114
115    if ( _fd < 0 ) {
116 //fprintf(stderr, "use O_CREAT\n");
117       flag |= O_CREAT;
118       _fd = ::open(name, flag, protect);
119    }
120
121    if ( _fd >= 0 ) {
122 //fprintf(stderr, "filebuf::open OK, name = %s, fd = %d, this = %d\n", name, _fd, (void*)this);
123       return 0;
124    } else
125       return EOF;
126 }
127
128 int filebuf::close()
129 {
130    if ( _prev_action == streambuf::PUT ) 
131       flush();
132    
133    ::close(_fd);
134    _fd = -1;
135    return 0;
136 }
137
138 int filebuf::is_open()
139 {
140    return (_fd>=0) ? 1 : 0;
141 }
142
143 void filebuf::notify(int action_t) 
144 {
145       if ( _prev_action == -1 ) {
146          _prev_action = action_t;
147       } else
148         if ( _prev_action != action_t )
149           _notify(action_t);
150 }
151
152 void filebuf::_notify(int action_t)
153 {
154    switch ( action_t ) {
155      case streambuf::GET:
156 //////////////////////////////////////////////////////////////
157 // previous action was PUT. Now calculate the number of chars
158 // that have been put and write them out. 
159 //
160 // Note: put_ptr always starts at base. And at this time, 
161 //       get_ptr == base.
162 //
163 //////////////////////////////////////////////////////////////
164        overflow();
165        break;
166
167      case streambuf::PUT:
168 //////////////////////////////////////////////////////////////
169 // previous action was a GET. 
170 //
171 // Note: get_ptr always starts at base.
172 //
173 //////////////////////////////////////////////////////////////
174        empty_buffer(); 
175        break;
176
177      default:
178        return;
179    }
180    _prev_action = action_t;
181 }
182
183 int filebuf::_write(char* ptr, int size)
184 {
185 //fprintf(stderr, "_write() size = %d, fd = %d\n", size, _fd);
186
187    int _written_size = ::write(_fd, ptr, size);
188    if ( _written_size != size ) {
189       //fprintf(stderr, "fwrite only writes %d bytes\n.", size - _written_size);
190       return EOF;
191    } 
192    return _written_size;
193 }
194
195 int filebuf::overflow()
196 {
197 // write to the file if possible and clean the buffer
198
199    if ( !BIT_TEST(_mode, ios::out) && !BIT_TEST(_mode, ios::app) )
200       return EOF;
201
202    if ( _size == 0 ) return 0;
203
204    if ( BIT_TEST(_mode, ios::app) ) {
205       if ( _seek(0L, SEEK_END) != 0 ) return EOF;
206    } else
207       if ( _seek() != 0 ) return EOF;
208
209    int ok;
210
211    if ( get_ptr + _size <= end ) {
212       ok = _write(get_ptr, _size);
213    } else {
214       int l = end - get_ptr;
215
216       ok = _write(get_ptr, l);
217
218       if ( ok != EOF ) 
219          ok = _write(base, _size - l);
220    }
221
222    if ( ok == EOF ) return EOF;
223
224    current_pos += _size;
225
226    empty_buffer(); 
227
228    return ok;
229 }
230
231 int filebuf::underflow() 
232 {
233 // get more from the file if possible
234
235    if ( !BIT_TEST(_mode, ios::in) )
236       return EOF;
237
238    if ( _seek() != 0 ) return EOF;
239
240    _size = ::read(_fd, base, _capacity);
241
242 //fprintf(stderr, "read in _underflow() this = %d, _size = %d, current_pos = %d, fd = %d\n", (void*)this, _size, current_pos, _fd);
243
244    if (_size <=0)
245       return EOF;
246    else {
247       get_ptr = base;
248       put_ptr = base + _size;
249    }
250
251    current_pos += _size;
252
253    return 0;
254 }
255
256 int filebuf::_seek() 
257 {
258 //fprintf(stderr, "_seek() [1] current_pos= %d\n", current_pos);
259    if ( ::lseek(_fd, current_pos, SEEK_SET) == -1 ) {
260       fprintf(stderr, "lseek failed. current_pos= %ld\n", current_pos);
261       return EOF;
262    } else 
263       return 0;
264 }
265
266 int filebuf::_seek(streampos pos, int whence) 
267 {
268       
269 //fprintf(stderr, "_seek() [2]: pos= %d, whence=%d\n", pos, whence);
270    current_pos = pos;
271    if ( ::lseek(_fd, pos, whence) == -1 ) {
272       fprintf(stderr, "lseek failed. pos= %ld, whence=%d\n", pos, whence);
273       return EOF;
274    } else 
275       return 0;
276 }
277
278 int filebuf::seekg(long delta) 
279 {
280    if ( _prev_action == streambuf::PUT )
281       overflow();
282    else
283       empty_buffer(); 
284
285    current_pos = delta;
286
287    return 0;
288 }
289
290 int filebuf::flush() 
291 {
292    if ( overflow() == EOF )
293       return EOF;
294
295    if ( ::fsync(_fd) != 0 )
296       return EOF;
297    else
298       return 0;
299 }
300
301