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
|
// Copyright (c) 2012-2014 Konstantin Isakov <ikm@zbackup.org> 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 );
File( std::string const & filename, OpenMode );
File( int fd, OpenMode );
/// 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 );
template< typename T >
void read( T & value )
{ read( &value, sizeof( value ) ); }
template< typename T >
T read()
{ 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 );
/// 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 );
template< typename T >
void write( T const & value )
{ 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 );
/// 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 );
/// Like the above, but uses its own local internal buffer (1024 bytes
/// currently), and strips newlines by default
std::string gets( bool stripNl = true );
/// Seeks in the file, relative to its beginning
void seek( long offset );
/// Seeks in the file, relative to the current position
void seekCur( long offset );
/// Seeks in the file, relative to the end of file
void seekEnd( long offset = 0 );
/// Seeks to the beginning of file
void rewind();
/// Tells the current position within the file, relative to its beginning
size_t tell();
/// Returns file size
size_t size();
/// Returns true if end-of-file condition is set
bool eof();
/// Returns ferror
int error();
/// Returns the underlying FILE * record, so other operations can be
/// performed on it
FILE * file();
/// 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();
/// Closes the file. No further operations are valid
void close();
/// Checks if the file exists or not
static bool exists( char const * filename );
static bool exists( std::string const & filename )
{ 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 );
~File();
/// Erases the given file
static void erase( std::string const & );
/// Renames the given file
static void rename( std::string const & from,
std::string const & to );
/// 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();
virtual ~exReadErrorDetailed();
private:
void buildDescription( int fd );
};
private:
void open( char const * filename, OpenMode );
void open( int fd, OpenMode );
void flushWriteBuffer();
void releaseWriteBuffer();
};
#endif
|