Disk ARchive  2.4.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
sparse_file.hpp
Go to the documentation of this file.
1 /*********************************************************************/
2 // dar - disk archive - a backup/restoration program
3 // Copyright (C) 2002-2052 Denis Corbin
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 //
19 // to contact the author : http://dar.linux.free.fr/email.html
20 /*********************************************************************/
21 // $Id: sparse_file.hpp,v 1.20 2011/05/20 10:23:07 edrusb Rel $
22 //
23 /*********************************************************************/
24 
36 
37 #ifndef SPARSE_FILE_HPP
38 #define SPARSE_FILE_HPP
39 
40 #include "../my_config.h"
41 
42 extern "C"
43 {
44 #if HAVE_LIMITS_H
45 #include <limits.h>
46 #endif
47 }
48 
49 #include "generic_file.hpp"
50 #include "escape.hpp"
51 
54 
55 
56 #define SPARSE_FIXED_ZEROED_BLOCK 40960
57 #ifdef SSIZE_MAX
58 #if SSIZE_MAX < MAX_BUFFER_SIZE
59 #undef MAX_BUFFER_SIZE
60 #define SPARSE_FIXED_ZEROED_BLOCK SSIZE_MAX
61 #endif
62 #endif
63 
64 
65 namespace libdar
66 {
67 
68  class sparse_file : public escape
69  {
70  public:
72 
75  // this parameter is only used if "below" is in write-only mode
76  sparse_file(generic_file *below, const infinint & hole_size = 15);
77 
78  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
79  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.
80  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
81 
82  bool has_seen_hole() const { return seen_hole; };
83  bool has_escaped_data() const { return data_escaped; };
84 
86 
95  void copy_to(generic_file & ref) { crc value = infinint(1); copy_to(ref, value); };
96 
98  void copy_to(generic_file & ref, crc & value);
99 
100  // indirectly inherited from generic_file
101 
102  bool skip(const infinint & pos) { if(pos != offset) throw Efeature("skip in sparse_file"); else return true; };
103  bool skip_to_eof() { throw Efeature("skip in sparse_file"); };
104  bool skip_relative(S_I x) { if(x != 0) throw Efeature("skip in sparse_file"); return true; };
105  infinint get_position();
106 
107  protected:
108 
109  // hidden methods from the escape class
110 
111  void add_mark_at_current_position(sequence_type t) { escape::add_mark_at_current_position(t); };
112  bool skip_to_next_mark(sequence_type t, bool jump) { return escape::skip_to_next_mark(t, jump); };
113  bool next_to_read_is_mark(sequence_type t) { return escape::next_to_read_is_mark(t); };
114  void add_unjumpable_mark(sequence_type t) { escape::add_unjumpable_mark(t); };
115 
116  // redefined protected methods from generic_file
117 
118  U_I inherited_read(char *a, U_I size);
119  void inherited_write(const char *a, U_I size);
120  void inherited_sync_write();
121  void inherited_terminate() { escape::inherited_terminate(); };
122 
123  private:
124  static bool initialized;
125  static unsigned char zeroed_field[SPARSE_FIXED_ZEROED_BLOCK]; // read-only, used when the sequence of zeros is too short for a hole
126 
127  enum { normal, hole } mode;
128  infinint zero_count; //< number of zeroed byte pending in the current hole
129  infinint offset; //< current offset in file (as if it was a plain file).
130  infinint min_hole_size; //< minimum size of hole to consider
131  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
132  bool escape_write; //< whether to behave like an escape object when writing down data
133  bool escape_read; //< whether to behave like an escape object when reading out data
134  bool copy_to_no_skip; //< whether to hide holes by zeored bytes in the copy_to() methods
135  bool seen_hole; //< whether a hole has been seen or this is a plain file so far
136  bool data_escaped; //< whether some data has been escaped to not collide with a mark (may occur even when no hole is met)
137 
140  void dump_pending_zeros();
141 
143  void write_hole(const infinint & length);
144 
146 
154  static bool look_for_hole(const char *a, U_I size, U_I min_hole_size, U_I & start, U_I & length);
155 
157 
161  static U_I count_initial_zeros(const char *a, U_I size);
162  };
163 
164 
165 } // end of namespace
166 
168 
169 #endif