summaryrefslogtreecommitdiff
path: root/src/stable/file.cpp
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2012-03-25 20:00:08 +0000
committerMike Buland <eichlan@xagasoft.com>2012-03-25 20:00:08 +0000
commit469bbcf0701e1eb8a6670c23145b0da87357e178 (patch)
treeb5b062a16e46a6c5d3410b4e574cd0cc09057211 /src/stable/file.cpp
parentee1b79396076edc4e30aefb285fada03bb45e80d (diff)
downloadlibbu++-469bbcf0701e1eb8a6670c23145b0da87357e178.tar.gz
libbu++-469bbcf0701e1eb8a6670c23145b0da87357e178.tar.bz2
libbu++-469bbcf0701e1eb8a6670c23145b0da87357e178.tar.xz
libbu++-469bbcf0701e1eb8a6670c23145b0da87357e178.zip
Code is all reorganized. We're about ready to release. I should write up a
little explenation of the arrangement.
Diffstat (limited to 'src/stable/file.cpp')
-rw-r--r--src/stable/file.cpp305
1 files changed, 305 insertions, 0 deletions
diff --git a/src/stable/file.cpp b/src/stable/file.cpp
new file mode 100644
index 0000000..8c8f540
--- /dev/null
+++ b/src/stable/file.cpp
@@ -0,0 +1,305 @@
1/*
2 * Copyright (C) 2007-2011 Xagasoft, All rights reserved.
3 *
4 * This file is part of the libbu++ library and is released under the
5 * terms of the license contained in the file LICENSE.
6 */
7
8#include "bu/file.h"
9#include <errno.h>
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <fcntl.h>
13#include <unistd.h>
14#include <time.h>
15
16#include "bu/config.h"
17
18namespace Bu { subExceptionDef( FileException ) }
19
20Bu::File::File( const Bu::String &sName, int iFlags ) :
21 fd( -1 ),
22 bEos( true )
23{
24#ifdef USE_64BIT_IO
25 fd = ::open64( sName.getStr(), getPosixFlags( iFlags ), 0666 );
26#else
27 fd = ::open( sName.getStr(), getPosixFlags( iFlags ), 0666 );
28#endif
29 if( fd < 0 )
30 {
31 throw Bu::FileException( errno, "%s: %s",
32 strerror(errno), sName.getStr() );
33 }
34 bEos = false;
35}
36
37Bu::File::File( int fd ) :
38 fd( fd )
39{
40 bEos = false;
41}
42
43Bu::File::~File()
44{
45 close();
46}
47
48void Bu::File::close()
49{
50 if( fd >= 0 )
51 {
52 if( ::close( fd ) )
53 {
54 throw Bu::FileException( errno, "%s",
55 strerror(errno) );
56 }
57 fd = -1;
58 bEos = true;
59 }
60}
61
62Bu::size Bu::File::read( void *pBuf, Bu::size nBytes )
63{
64 if( fd < 0 )
65 throw FileException("File not open.");
66
67 Bu::size iRead = ::read( fd, pBuf, nBytes );
68 if( iRead == 0 )
69 bEos = true;
70 else if( iRead == -1 && errno == EAGAIN )
71 return 0;
72 else if( iRead < 0 )
73 throw FileException( errno, "%s", strerror( errno ) );
74 return iRead;
75}
76
77Bu::size Bu::File::write( const void *pBuf, Bu::size nBytes )
78{
79 if( fd < 0 )
80 throw FileException("File not open.");
81
82 Bu::size iWrote = ::write( fd, pBuf, nBytes );
83 if( iWrote < 0 )
84 throw FileException( errno, "%s", strerror( errno ) );
85 return iWrote;
86}
87
88Bu::size Bu::File::tell()
89{
90 if( fd < 0 )
91 throw FileException("File not open.");
92
93 return lseek( fd, 0, SEEK_CUR );
94}
95
96void Bu::File::seek( Bu::size offset )
97{
98 if( fd < 0 )
99 throw FileException("File not open.");
100
101 lseek( fd, offset, SEEK_CUR );
102 bEos = false;
103}
104
105void Bu::File::setPos( Bu::size pos )
106{
107 if( fd < 0 )
108 throw FileException("File not open.");
109
110 lseek( fd, pos, SEEK_SET );
111 bEos = false;
112}
113
114void Bu::File::setPosEnd( Bu::size pos )
115{
116 if( fd < 0 )
117 throw FileException("File not open.");
118
119 lseek( fd, pos, SEEK_END );
120 bEos = false;
121}
122
123bool Bu::File::isEos()
124{
125 return bEos;
126}
127
128bool Bu::File::canRead()
129{
130#ifdef WIN32
131 return true;
132#else
133 int iMode = fcntl( fd, F_GETFL, 0 )&O_ACCMODE;
134 if( iMode == O_RDONLY || iMode == O_RDWR )
135 return true;
136 return false;
137#endif
138}
139
140bool Bu::File::canWrite()
141{
142#ifdef WIN32
143 return true;
144#else
145 int iMode = fcntl( fd, F_GETFL, 0 )&O_ACCMODE;
146 if( iMode == O_WRONLY || iMode == O_RDWR )
147 return true;
148 return false;
149#endif
150}
151
152bool Bu::File::isReadable()
153{
154 return true;
155}
156
157bool Bu::File::isWritable()
158{
159 return true;
160}
161
162bool Bu::File::isSeekable()
163{
164 return true;
165}
166
167bool Bu::File::isBlocking()
168{
169 return true;
170}
171
172void Bu::File::setBlocking( bool bBlocking )
173{
174#ifdef WIN32
175 fprintf(stderr, "STUB: Bu::File::setBlocking\n");
176#else
177 if( bBlocking )
178 fcntl(
179 fd,
180 F_SETFL, fcntl( fd, F_GETFL, 0 )&(~O_NONBLOCK)
181 );
182 else
183 fcntl(
184 fd,
185 F_SETFL, fcntl( fd, F_GETFL, 0 )|O_NONBLOCK
186 );
187#endif
188}
189
190Bu::File Bu::File::tempFile( Bu::String &sName )
191{
192 uint32_t iX;
193 iX = time( NULL ) + getpid();
194 int iXes;
195 for( iXes = sName.getSize()-1; iXes >= 0; iXes-- )
196 {
197 if( sName[iXes] != 'X' )
198 break;
199 }
200 iXes++;
201 if( iXes == sName.getSize() )
202 throw Bu::ExceptionBase("Invalid temporary filename template.");
203 for( int iter = 0; iter < 100; iter++ )
204 {
205 for( int j = iXes; j < sName.getSize(); j++ )
206 {
207 iX = (1103515245 * iX + 12345);
208 sName[j] = ('A'+(iX%26)) | ((iX&0x1000)?(0x20):(0));
209 }
210
211 try
212 {
213 return Bu::File( sName, Bu::File::Read|Bu::File::Write
214 |Bu::File::Create|Bu::File::Exclusive );
215 } catch(...) { }
216 }
217 throw Bu::FileException("Failed to create unique temporary file after 100"
218 " iterations.");
219}
220
221void Bu::File::setSize( Bu::size iSize )
222{
223#ifdef WIN32
224 chsize( fd, iSize );
225#else
226 ftruncate( fd, iSize );
227#endif
228}
229
230Bu::size Bu::File::getSize() const
231{
232 struct stat st;
233 fstat( fd, &st );
234 return st.st_size;
235}
236
237Bu::size Bu::File::getBlockSize() const
238{
239#ifdef WIN32
240 return 4096;
241#else
242 struct stat st;
243 fstat( fd, &st );
244 return st.st_blksize;
245#endif
246}
247
248Bu::String Bu::File::getLocation() const
249{
250 return "to be implemented";
251}
252
253#ifndef WIN32
254void Bu::File::chmod( mode_t t )
255{
256 fchmod( fd, t );
257}
258#endif
259
260void Bu::File::flush()
261{
262 // There is no flushing with direct I/O...
263 //fflush( fh );
264}
265
266bool Bu::File::isOpen()
267{
268 return (fd > -1);
269}
270
271int Bu::File::getPosixFlags( int iFlags )
272{
273 int iRet = 0;
274 switch( (iFlags&ReadWrite) )
275 {
276 // According to posix, O_RDWR is not necesarilly O_RDONLY|O_WRONLY, so
277 // lets be proper and use the right value in the right place.
278 case Read: iRet = O_RDONLY; break;
279 case Write: iRet = O_WRONLY; break;
280 case ReadWrite: iRet = O_RDWR; break;
281 default:
282 throw FileException(
283 "You must specify Read, Write, or both when opening a file.");
284 }
285
286 if( (iFlags&Create) )
287 iRet |= O_CREAT;
288 if( (iFlags&Append) )
289 iRet |= O_APPEND;
290 if( (iFlags&Truncate) )
291 iRet |= O_TRUNC;
292#ifndef WIN32
293 if( (iFlags&NonBlock) )
294 iRet |= O_NONBLOCK;
295#endif
296 if( (iFlags&Exclusive) == Exclusive )
297 iRet |= O_EXCL;
298
299#ifdef O_BINARY
300 iRet |= O_BINARY;
301#endif
302
303 return iRet;
304}
305