Disk ARchive  2.5.2
Full featured and portable backup and archiving tool
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 = nullptr; copy_to(ref, 0, tmp); if(tmp != nullptr) 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     bool skippable(skippability direction, const infinint & amount) { return false; };
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() const;
00103 
00104     protected:
00105 
00106         // methods from the escape class we hide from the (public) class interface
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         // methods from generic_file redefined as protected
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         // inherited_flush_read() kept as is from the escape class
00119         // inherited_terminate() kept as is from the escape class
00120 
00121     private:
00122     static bool initialized; //< whether static field "zeroed_field" has been initialized
00123         static unsigned char zeroed_field[SPARSE_FIXED_ZEROED_BLOCK]; //< read-only, used when the sequence of zeros is too short for a hole
00124 
00125     enum { normal, hole } mode; //< wether we are currently reading/writing a hole or normal data
00126     infinint zero_count;     //< number of zeroed byte pending in the current hole
00127     infinint offset;         //< current offset in file (as if it was a plain file).
00128     infinint min_hole_size;  //< minimum size of hole to consider
00129     U_I UI_min_hole_size;    //< if possible store min_hole_size as U_I, if not this field is set to zero which disables the hole lookup inside buffers while writing data
00130     bool escape_write;       //< whether to behave like an escape object when writing down data
00131     bool escape_read;        //< whether to behave like an escape object when reading out data
00132     bool copy_to_no_skip;    //< whether to hide holes by zeored bytes in the copy_to() methods
00133     bool seen_hole;          //< whether a hole has been seen or this is a plain file so far
00134     bool data_escaped;       //< whether some data has been escaped to not collide with a mark (may occur even when no hole is met)
00135 
00138     void dump_pending_zeros();
00139 
00141     void write_hole(const infinint & length);
00142 
00146     void reset();
00147 
00148 
00150 
00158     static bool look_for_hole(const char *a, U_I size, U_I min_hole_size, U_I & start, U_I & length);
00159 
00161 
00165     static U_I count_initial_zeros(const char *a, U_I size);
00166     };
00167 
00168 
00169 } // end of namespace
00170 
00172 
00173 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines