Disk ARchive  2.4.5
 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 // $Id$
00022 //
00023 /*********************************************************************/
00024 
00036 
00037 #ifndef SPARSE_FILE_HPP
00038 #define SPARSE_FILE_HPP
00039 
00040 #include "../my_config.h"
00041 
00042 extern "C"
00043 {
00044 #if HAVE_LIMITS_H
00045 #include <limits.h>
00046 #endif
00047 }
00048 
00049 #include "generic_file.hpp"
00050 #include "escape.hpp"
00051 
00054 
00055 
00056 #define SPARSE_FIXED_ZEROED_BLOCK 40960
00057 #ifdef SSIZE_MAX
00058 #if SSIZE_MAX < MAX_BUFFER_SIZE
00059 #undef MAX_BUFFER_SIZE
00060 #define SPARSE_FIXED_ZEROED_BLOCK SSIZE_MAX
00061 #endif
00062 #endif
00063 
00064 
00065 namespace libdar
00066 {
00067 
00068     class sparse_file : public escape
00069     {
00070     public:
00072 
00075             // this parameter is only used if "below" is in write-only mode
00076         sparse_file(generic_file *below, const infinint & hole_size = 15);
00077 
00078         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
00079         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.
00080         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
00081 
00082         bool has_seen_hole() const { return seen_hole; };
00083         bool has_escaped_data() const { return data_escaped; };
00084 
00086 
00095         void copy_to(generic_file & ref) { crc *tmp = NULL; copy_to(ref, 0, tmp); if(tmp != NULL) throw SRC_BUG; };
00096 
00098         void copy_to(generic_file & ref, const infinint & crc_size, crc * & value);
00099 
00100             // indirectly inherited from generic_file
00101 
00102         bool skip(const infinint & pos) { if(pos != offset) throw Efeature("skip in sparse_file"); else return true; };
00103         bool skip_to_eof() { throw Efeature("skip in sparse_file"); };
00104         bool skip_relative(S_I x)  { if(x != 0) throw Efeature("skip in sparse_file"); return true; };
00105         infinint get_position();
00106 
00107     protected:
00108 
00109             // hidden methods from the escape class
00110 
00111         void add_mark_at_current_position(sequence_type t) { escape::add_mark_at_current_position(t); };
00112         bool skip_to_next_mark(sequence_type t, bool jump) { return escape::skip_to_next_mark(t, jump); };
00113         bool next_to_read_is_mark(sequence_type t) { return escape::next_to_read_is_mark(t); };
00114         void add_unjumpable_mark(sequence_type t) { escape::add_unjumpable_mark(t); };
00115 
00116             // redefined protected methods from generic_file
00117 
00118         U_I inherited_read(char *a, U_I size);
00119         void inherited_write(const char *a, U_I size);
00120         void inherited_sync_write();
00121         void inherited_terminate() { escape::inherited_terminate(); };
00122 
00123     private:
00124         static bool initialized;
00125         static unsigned char zeroed_field[SPARSE_FIXED_ZEROED_BLOCK]; // read-only, used when the sequence of zeros is too short for a hole
00126 
00127         enum { normal, hole } mode;
00128         infinint zero_count;     //< number of zeroed byte pending in the current hole
00129         infinint offset;         //< current offset in file (as if it was a plain file).
00130         infinint min_hole_size;  //< minimum size of hole to consider
00131         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
00132         bool escape_write;       //< whether to behave like an escape object when writing down data
00133         bool escape_read;        //< whether to behave like an escape object when reading out data
00134         bool copy_to_no_skip;    //< whether to hide holes by zeored bytes in the copy_to() methods
00135         bool seen_hole;          //< whether a hole has been seen or this is a plain file so far
00136         bool data_escaped;       //< whether some data has been escaped to not collide with a mark (may occur even when no hole is met)
00137 
00140         void dump_pending_zeros();
00141 
00143         void write_hole(const infinint & length);
00144 
00146 
00154         static bool look_for_hole(const char *a, U_I size, U_I min_hole_size, U_I & start, U_I & length);
00155 
00157 
00161         static U_I count_initial_zeros(const char *a, U_I size);
00162     };
00163 
00164 
00165 } // end of namespace
00166 
00168 
00169 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines