Disk ARchive  2.4.12
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
sparse_file.hpp
Go to the documentation of this file.
00001 /*********************************************************************/
00002 // dar - disk archive - a backup/restoration program
00003 // Copyright (C) 2002-2052 Denis Corbin
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 //
00019 // to contact the author : http://dar.linux.free.fr/email.html
00020 /*********************************************************************/
00021 
00033 
00034 #ifndef SPARSE_FILE_HPP
00035 #define SPARSE_FILE_HPP
00036 
00037 #include "../my_config.h"
00038 
00039 extern "C"
00040 {
00041 #if HAVE_LIMITS_H
00042 #include <limits.h>
00043 #endif
00044 }
00045 
00046 #include "generic_file.hpp"
00047 #include "escape.hpp"
00048 
00051 
00052 
00053 #define SPARSE_FIXED_ZEROED_BLOCK 40960
00054 #ifdef SSIZE_MAX
00055 #if SSIZE_MAX < MAX_BUFFER_SIZE
00056 #undef MAX_BUFFER_SIZE
00057 #define SPARSE_FIXED_ZEROED_BLOCK SSIZE_MAX
00058 #endif
00059 #endif
00060 
00061 
00062 namespace libdar
00063 {
00064 
00065     class sparse_file : public escape
00066     {
00067     public:
00069 
00072             // this parameter is only used if "below" is in write-only mode
00073         sparse_file(generic_file *below, const infinint & hole_size = 15);
00074 
00075         void write_as_escape(bool mode) { escape_write = mode; }; // if set to true, inherited_write() call will not make any lookup for holes, the written data will simply be escaped if it could collide with a mark used to signal the start of a hole
00076         void read_as_escape(bool mode) { escape_read = mode; }; // if set to true, the data will be unescaped or eof will be signaled to the first mark met, instead of interpreting the mark and what follows as a hole data structure.
00077         void copy_to_without_skip(bool mode) { copy_to_no_skip = mode; }; // if set to true, the copy_to() methods, write zeroed data in place of skipping over a hole to restore it into the target generic_file
00078 
00079         bool has_seen_hole() const { return seen_hole; };
00080         bool has_escaped_data() const { return data_escaped; };
00081 
00083 
00092         void copy_to(generic_file & ref) { crc *tmp = NULL; copy_to(ref, 0, tmp); if(tmp != NULL) throw SRC_BUG; };
00093 
00095         void copy_to(generic_file & ref, const infinint & crc_size, crc * & value);
00096 
00097             // indirectly inherited from generic_file
00098 
00099         bool skip(const infinint & pos) { if(pos != offset) throw Efeature("skip in sparse_file"); else return true; };
00100         bool skip_to_eof() { throw Efeature("skip in sparse_file"); };
00101         bool skip_relative(S_I x)  { if(x != 0) throw Efeature("skip in sparse_file"); return true; };
00102         infinint get_position();
00103 
00104     protected:
00105 
00106             // hidden methods from the escape class
00107 
00108         void add_mark_at_current_position(sequence_type t) { escape::add_mark_at_current_position(t); };
00109         bool skip_to_next_mark(sequence_type t, bool jump) { return escape::skip_to_next_mark(t, jump); };
00110         bool next_to_read_is_mark(sequence_type t) { return escape::next_to_read_is_mark(t); };
00111         void add_unjumpable_mark(sequence_type t) { escape::add_unjumpable_mark(t); };
00112 
00113             // redefined protected methods from generic_file
00114 
00115         U_I inherited_read(char *a, U_I size);
00116         void inherited_write(const char *a, U_I size);
00117         void inherited_sync_write();
00118         void inherited_terminate() { escape::inherited_terminate(); };
00119 
00120     private:
00121         static bool initialized;
00122         static unsigned char zeroed_field[SPARSE_FIXED_ZEROED_BLOCK]; // read-only, used when the sequence of zeros is too short for a hole
00123 
00124         enum { normal, hole } mode;
00125         infinint zero_count;     //< number of zeroed byte pending in the current hole
00126         infinint offset;         //< current offset in file (as if it was a plain file).
00127         infinint min_hole_size;  //< minimum size of hole to consider
00128         U_I UI_min_hole_size;    //< if possible store min_hole_size under U_I, if not this field is set to zero which disables the hole lookup inside buffers while writing data
00129         bool escape_write;       //< whether to behave like an escape object when writing down data
00130         bool escape_read;        //< whether to behave like an escape object when reading out data
00131         bool copy_to_no_skip;    //< whether to hide holes by zeored bytes in the copy_to() methods
00132         bool seen_hole;          //< whether a hole has been seen or this is a plain file so far
00133         bool data_escaped;       //< whether some data has been escaped to not collide with a mark (may occur even when no hole is met)
00134 
00137         void dump_pending_zeros();
00138 
00140         void write_hole(const infinint & length);
00141 
00143 
00151         static bool look_for_hole(const char *a, U_I size, U_I min_hole_size, U_I & start, U_I & length);
00152 
00154 
00158         static U_I count_initial_zeros(const char *a, U_I size);
00159     };
00160 
00161 
00162 } // end of namespace
00163 
00165 
00166 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines