|
Disk ARchive
2.4.12
|
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
1.7.6.1