00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <assert.h>
00020 #include <sys/types.h>
00021 #include <sys/stat.h>
00022 #include <fcntl.h>
00023 #include <unistd.h>
00024 #include <stdio.h>
00025 #include <string.h>
00026 #include <errno.h>
00027
00028 #include <Basics.H>
00029 #include "FdStream.H"
00030
00031
00032
00033
00034
00035 bool FS::FdStreambuf::get_pos_to_fd_pos()
00036 {
00037
00038
00039 if(gptr() && (gptr() < egptr()))
00040 {
00041 long int unread_count = (egptr() - gptr());
00042 off_t seek_res;
00043 do
00044 seek_res = lseek(this->_fd, -unread_count, SEEK_CUR);
00045 while((seek_res == ((off_t)-1)) && (errno == EINTR));
00046
00047
00048 if (seek_res < 0)
00049 return false;
00050 }
00051
00052
00053 setg(0,0,0);
00054
00055 return true;
00056 }
00057
00058
00059
00060 FS::FdStreambuf::FdStreambuf(int fd)
00061 : _fd(-1), should_close(false), buffer(0), buf_size(0)
00062 {
00063 this->attach(fd);
00064 }
00065
00066 FS::FdStreambuf::FdStreambuf(const char *filename, stream_mode_t mode,
00067 mode_t prot,
00068 bool create, bool replace)
00069 : _fd(-1), should_close(false), buffer(0), buf_size(0)
00070 {
00071 this->open(filename, mode, prot, create, replace);
00072 }
00073
00074 FS::FdStreambuf::~FdStreambuf()
00075 {
00076 (void) this->close();
00077
00078
00079 if(buffer)
00080 delete [] buffer;
00081 }
00082
00083
00084
00085 FS::FdStreambuf* FS::FdStreambuf::attach(int fd)
00086 {
00087
00088 if(is_open())
00089 return NULL;
00090 this->_fd = fd;
00091 this->should_close = false;
00092
00093 off_t seek_res;
00094 do
00095 seek_res = lseek(this->_fd, 0, SEEK_CUR);
00096 while((seek_res == ((off_t)-1)) && (errno == EINTR));
00097 if(seek_res == ((off_t)-1))
00098 {
00099 this->_fd = -1;
00100 return 0;
00101 }
00102
00103 this->mode = std::ios::in|std::ios::out;
00104
00105 return this;
00106 }
00107
00108 FS::FdStreambuf* FS::FdStreambuf::open(const char *filename,
00109 stream_mode_t mode,
00110 mode_t prot,
00111 bool create, bool replace)
00112 {
00113
00114 int openflag;
00115 if((mode & std::ios::in) && (mode & std::ios::out))
00116 openflag = O_RDWR;
00117 else if(mode & std::ios::in)
00118 openflag = O_RDONLY;
00119 else if(mode & std::ios::out)
00120 openflag = O_WRONLY;
00121 else
00122
00123 return 0;
00124
00125
00126 if(create)
00127 openflag |= O_CREAT;
00128 if(!replace)
00129 openflag |= O_EXCL;
00130 if(mode & std::ios::trunc)
00131 openflag |= O_TRUNC;
00132 if(mode & std::ios::app)
00133 openflag |= O_APPEND;
00134
00135
00136 do
00137 this->_fd = ::open(filename, openflag, prot);
00138 while((this->_fd < 0) && (errno == EINTR));
00139 if(this->_fd < 0)
00140 return 0;
00141 else
00142
00143 this->should_close = true;
00144
00145
00146 this->mode = mode;
00147
00148
00149 if(mode & std::ios::ate)
00150 {
00151 off_t seek_res;
00152 do
00153 seek_res = lseek(this->_fd, 0, SEEK_END);
00154 while((seek_res == ((off_t)-1)) && (errno == EINTR));
00155 if(seek_res == ((off_t)-1))
00156 return 0;
00157 }
00158
00159
00160 return this;
00161 }
00162
00163 FS::FdStreambuf* FS::FdStreambuf::close()
00164 {
00165
00166 if(is_open())
00167 {
00168
00169 sync();
00170
00171 if(should_close)
00172 {
00173
00174 int close_res;
00175 do
00176 close_res = ::close(this->_fd);
00177 while((close_res != 0) && (errno == EINTR));
00178
00179 if(close_res != 0)
00180 return 0;
00181 }
00182
00183 this->_fd = -1;
00184
00185 return this;
00186 }
00187
00188 return 0;
00189 }
00190
00191 FS::FdStreambuf::stream_pos_t FS::FdStreambuf::seekoff(stream_off_t offset,
00192 stream_seek_t way,
00193
00194 stream_mode_t mode)
00195 {
00196
00197 if(pptr() && (pptr() > pbase()))
00198 {
00199
00200 if(overflow() == EOF)
00201 return ((stream_pos_t)-1);
00202 }
00203
00204
00205 else if(!get_pos_to_fd_pos())
00206 return ((stream_pos_t)-1);
00207
00208
00209 setg(0,0,0);
00210 setp(0,0);
00211
00212
00213 int whence = SEEK_END;
00214 if(way == std::ios::beg)
00215 whence = SEEK_SET;
00216 else if(way == std::ios::cur)
00217 whence = SEEK_CUR;
00218
00219
00220 off_t result;
00221 do
00222 result = lseek(this->_fd, offset, whence);
00223 while((result == ((off_t)-1)) && (errno == EINTR));
00224
00225 if (result < 0)
00226 return ((stream_pos_t)-1);
00227
00228 return result;
00229 }
00230
00231 FS::FdStreambuf::stream_pos_t FS::FdStreambuf::seekpos(stream_pos_t pos,
00232
00233 stream_mode_t mode)
00234 {
00235 return this->seekoff(pos, std::ios::beg, mode);
00236 }
00237
00238
00239
00240 int FS::FdStreambuf::underflow()
00241 {
00242
00243
00244 if(!(mode & std::ios::in))
00245 return EOF;
00246 if(!is_open())
00247 return EOF;
00248
00249
00250 if(pptr() && (pptr() > pbase()))
00251 return overflow();
00252
00253
00254 assert(pptr() == pbase());
00255 setp(0,0);
00256
00257
00258 if(buffer == 0)
00259 {
00260 buf_size = BUFSIZ;
00261 buffer = NEW_PTRFREE_ARRAY(char, buf_size);
00262 }
00263
00264 int read_count;
00265 do
00266 read_count = ::read(this->_fd, buffer, buf_size);
00267 while((read_count == -1) && (errno == EINTR));
00268 if(read_count < 1)
00269 {
00270
00271
00272 setg(0,0,0);
00273 return EOF;
00274 }
00275
00276
00277 assert(read_count <= buf_size);
00278 setg(buffer, buffer, buffer+read_count);
00279
00280
00281 return ((*eback())&0x00ff);
00282 }
00283
00284 std::streamsize FS::FdStreambuf::xsgetn(char* s, std::streamsize n)
00285 {
00286 std::streamsize result = 0;
00287
00288
00289
00290 if(gptr() && (gptr() < egptr()))
00291 {
00292 unsigned int unread_count = (egptr() - gptr());
00293
00294 unsigned int use_count = (unread_count < n) ? unread_count : n;
00295
00296 memcpy(s, gptr(), use_count);
00297
00298 gbump(use_count);
00299 result += use_count;
00300 s += use_count;
00301 }
00302
00303
00304
00305 if(result < n)
00306 {
00307 int read_count;
00308 do
00309 read_count = ::read(this->_fd, s, n-result);
00310 while((read_count == -1) && (errno == EINTR));
00311 if(read_count >= 0)
00312 {
00313 result += read_count;
00314 }
00315 }
00316
00317 return result;
00318 }
00319
00320 int FS::FdStreambuf::overflow(int c)
00321 {
00322
00323
00324 if(!(mode & std::ios::out))
00325 return EOF;
00326 if(!is_open())
00327 return EOF;
00328
00329
00330
00331 if(!get_pos_to_fd_pos())
00332 return EOF;
00333
00334
00335 if(!pptr())
00336 {
00337
00338 if(buffer == 0)
00339 {
00340 buf_size = BUFSIZ;
00341 buffer = NEW_PTRFREE_ARRAY(char, buf_size);
00342 }
00343
00344
00345
00346 setp(buffer, buffer+(buf_size-1));
00347 }
00348 assert(pbase() == buffer);
00349
00350
00351 unsigned int count = pptr() - pbase();
00352 assert(count < buf_size);
00353
00354
00355
00356
00357 if(c != EOF)
00358 {
00359 *pptr() = c;
00360 count++;
00361 }
00362
00363 if(count > 0)
00364 {
00365
00366 int written_count;
00367 do
00368 written_count = ::write(this->_fd, pbase(), count);
00369 while((written_count == -1) && (errno == EINTR));
00370
00371 if(written_count < count)
00372 {
00373 setp(0,0);
00374 return EOF;
00375 }
00376
00377 assert(written_count == count);
00378 }
00379
00380
00381 assert(buffer != 0);
00382 setp(buffer, buffer+(buf_size-1));
00383
00384
00385
00386 return (c & 0x00ff);
00387 }
00388
00389 std::streamsize FS::FdStreambuf::xsputn(const char* s, std::streamsize n)
00390 {
00391
00392 if(n < 1)
00393 return 0;
00394
00395
00396 if(buffer == 0)
00397 {
00398 assert(pptr() == 0);
00399 buf_size = BUFSIZ;
00400 buffer = NEW_PTRFREE_ARRAY(char, buf_size);
00401
00402
00403
00404 setp(buffer, buffer+(buf_size-1));
00405 }
00406
00407
00408 if((pptr() != 0) &&
00409 (((pptr() - pbase()) + n) <= (buf_size - 1)))
00410 {
00411 memcpy(pptr(), s, n);
00412 pbump(n);
00413 return n;
00414 }
00415
00416
00417
00418 if(overflow() == EOF)
00419 return -1;
00420
00421
00422
00423 if(n <= (buf_size - 1))
00424 {
00425 memcpy(pptr(), s, n);
00426 pbump(n);
00427 return n;
00428 }
00429
00430
00431
00432 assert(n >= buf_size);
00433 assert(pptr() == pbase());
00434 int written_count;
00435 do
00436 written_count = ::write(this->_fd, s, n);
00437 while((written_count == -1) && (errno == EINTR));
00438
00439
00440 if(written_count < n)
00441 {
00442 setp(0,0);
00443 }
00444
00445
00446 return written_count;
00447 }
00448
00449 int FS::FdStreambuf::sync()
00450 {
00451
00452 if(pptr() && (pptr() > pbase()))
00453
00454 return (overflow() == EOF) ? -1 : 0;
00455
00456
00457 return 0;
00458 }