forked from zbackup/zbackup
-
Notifications
You must be signed in to change notification settings - Fork 0
/
file.hh
173 lines (132 loc) · 5.75 KB
/
file.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// Copyright (c) 2012-2014 Konstantin Isakov <[email protected]> and ZBackup contributors, see CONTRIBUTORS
// Part of ZBackup. Licensed under GNU GPLv2 or later + OpenSSL, see LICENSE
#ifndef FILE_HH_INCLUDED
#define FILE_HH_INCLUDED
#include <stddef.h>
#include <cstdio>
#include <exception>
#include <string>
#include "ex.hh"
using std::string;
/// A simple wrapper over FILE * operations with added write-buffering
class File
{
FILE * f;
char * writeBuffer;
size_t writeBufferLeft;
public:
DEF_EX( Ex, "File exception", std::exception )
DEF_EX_STR( exCantOpen, "Can't open", Ex )
DEF_EX( exReadError, "Error reading from file", Ex )
DEF_EX( exShortRead, "Short read from the file", exReadError )
DEF_EX( exWriteError, "Error writing to the file", Ex )
DEF_EX( exSeekError, "File seek error", Ex )
DEF_EX_STR( exCantErase, "Can't erase file", Ex )
DEF_EX_STR( exCantRename, "Can't rename file", Ex )
enum OpenMode
{
ReadOnly,
WriteOnly,
Update
};
typedef long Offset;
File( char const * filename, OpenMode )
throw( exCantOpen );
File( std::string const & filename, OpenMode )
throw( exCantOpen );
File( int fd, OpenMode )
throw( exCantOpen );
/// Reads the number of bytes to the buffer, throws an error if it
/// failed to fill the whole buffer (short read, i/o error etc)
void read( void * buf, size_t size ) throw( exReadError, exWriteError );
template< typename T >
void read( T & value ) throw( exReadError, exWriteError )
{ read( &value, sizeof( value ) ); }
template< typename T >
T read() throw( exReadError, exWriteError )
{ T value; read( value ); return value; }
/// Attempts reading at most 'count' records sized 'size'. Returns
/// the number of records it managed to read, up to 'count'
size_t readRecords( void * buf, size_t size, size_t count ) throw( exWriteError );
/// Writes the number of bytes from the buffer, throws an error if it
/// failed to write the whole buffer (short write, i/o error etc).
/// This function employs write buffering, and as such, writes may not
/// end up on disk immediately, or a short write may occur later
/// than it really did. If you don't want write buffering, use
/// writeRecords() function instead
void write( void const * buf, size_t size ) throw( exWriteError );
template< typename T >
void write( T const & value ) throw( exWriteError )
{ write( &value, sizeof( value ) ); }
/// Attempts writing at most 'count' records sized 'size'. Returns
/// the number of records it managed to write, up to 'count'.
/// This function does not employ buffering, but flushes the buffer if it
/// was used before
size_t writeRecords( void const * buf, size_t size, size_t count )
throw( exWriteError );
/// Reads a string from the file. Unlike the normal fgets(), this one
/// can strip the trailing newline character, if this was requested.
/// Returns either s or 0 if no characters were read
char * gets( char * s, int size, bool stripNl = false ) throw( exWriteError );
/// Like the above, but uses its own local internal buffer (1024 bytes
/// currently), and strips newlines by default
std::string gets( bool stripNl = true ) throw( exReadError, exWriteError );
/// Seeks in the file, relative to its beginning
void seek( long offset ) throw( exSeekError, exWriteError );
/// Seeks in the file, relative to the current position
void seekCur( long offset ) throw( exSeekError, exWriteError );
/// Seeks in the file, relative to the end of file
void seekEnd( long offset = 0 ) throw( exSeekError, exWriteError );
/// Seeks to the beginning of file
void rewind() throw( exSeekError, exWriteError );
/// Tells the current position within the file, relative to its beginning
size_t tell() throw( exSeekError );
/// Returns file size
size_t size() throw( exSeekError, exWriteError );
/// Returns true if end-of-file condition is set
bool eof() throw( exWriteError );
/// Returns ferror
int error() throw( exReadError );
/// Returns the underlying FILE * record, so other operations can be
/// performed on it
FILE * file() throw( exWriteError );
/// Releases the file handle out of the control of the class. No further
/// operations are valid. The file will not be closed on destruction
FILE * release() throw( exWriteError );
/// Closes the file. No further operations are valid
void close() throw( exWriteError );
/// Checks if the file exists or not
static bool exists( char const * filename ) throw();
static bool exists( std::string const & filename ) throw()
{ return exists( filename.c_str() ); }
/// Returns false when lstat returns stat::st_mode having
/// S_IFREG (filename is a file, or softlink to a file, and
/// is not a socket, fifo, device node, etc.
static bool special( std::string const & filename ) throw();
~File() throw();
/// Erases the given file
static void erase( std::string const & ) throw( exCantErase );
/// Renames the given file
static void rename( std::string const & from,
std::string const & to ) throw( exCantRename,
exCantErase );
/// Throwing this class instead of exReadError will make the description
/// include the file name
class exReadErrorDetailed: public exReadError
{
string description;
public:
exReadErrorDetailed( int fd );
exReadErrorDetailed( FILE * f );
virtual const char * what() const throw();
virtual ~exReadErrorDetailed() throw ();
private:
void buildDescription( int fd );
};
private:
void open( char const * filename, OpenMode ) throw( exCantOpen );
void open( int fd, OpenMode ) throw( exCantOpen );
void flushWriteBuffer() throw( exWriteError );
void releaseWriteBuffer() throw( exWriteError );
};
#endif