Disk ARchive  2.4.15
 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 
33 
34 #ifndef SPARSE_FILE_HPP
35 #define SPARSE_FILE_HPP
36 
37 #include "../my_config.h"
38 
39 extern "C"
40 {
41 #if HAVE_LIMITS_H
42 #include <limits.h>
43 #endif
44 }
45 
46 #include "generic_file.hpp"
47 #include "escape.hpp"
48 
51 
52 
53 #define SPARSE_FIXED_ZEROED_BLOCK 40960
54 #ifdef SSIZE_MAX
55 #if SSIZE_MAX < MAX_BUFFER_SIZE
56 #undef MAX_BUFFER_SIZE
57 #define SPARSE_FIXED_ZEROED_BLOCK SSIZE_MAX
58 #endif
59 #endif
60 
61 
62 namespace libdar
63 {
64 
65  class sparse_file : public escape
66  {
67  public:
69 
72  // this parameter is only used if "below" is in write-only mode
73  sparse_file(generic_file *below, const infinint & hole_size = 15);
74 
75  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
76  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.
77  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
78 
79  bool has_seen_hole() const { return seen_hole; };
80  bool has_escaped_data() const { return data_escaped; };
81 
83 
92  void copy_to(generic_file & ref) { crc *tmp = NULL; copy_to(ref, 0, tmp); if(tmp != NULL) throw SRC_BUG; };
93 
95  void copy_to(generic_file & ref, const infinint & crc_size, crc * & value);
96 
97  // indirectly inherited from generic_file
98 
99  bool skip(const infinint & pos) { if(pos != offset) throw Efeature("skip in sparse_file"); else return true; };
100  bool skip_to_eof() { throw Efeature("skip in sparse_file"); };
101  bool skip_relative(S_I x) { if(x != 0) throw Efeature("skip in sparse_file"); return true; };
102  infinint get_position();
103 
104  protected:
105 
106  // hidden methods from the escape class
107 
108  void add_mark_at_current_position(sequence_type t) { escape::add_mark_at_current_position(t); };
109  bool skip_to_next_mark(sequence_type t, bool jump) { return escape::skip_to_next_mark(t, jump); };
110  bool next_to_read_is_mark(sequence_type t) { return escape::next_to_read_is_mark(t); };
111  void add_unjumpable_mark(sequence_type t) { escape::add_unjumpable_mark(t); };
112 
113  // redefined protected methods from generic_file
114 
115  U_I inherited_read(char *a, U_I size);
116  void inherited_write(const char *a, U_I size);
117  void inherited_sync_write();
118  void inherited_terminate() { escape::inherited_terminate(); };
119 
120  private:
121  static bool initialized;
122  static unsigned char zeroed_field[SPARSE_FIXED_ZEROED_BLOCK]; // read-only, used when the sequence of zeros is too short for a hole
123 
124  enum { normal, hole } mode;
125  infinint zero_count; //< number of zeroed byte pending in the current hole
126  infinint offset; //< current offset in file (as if it was a plain file).
127  infinint min_hole_size; //< minimum size of hole to consider
128  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
129  bool escape_write; //< whether to behave like an escape object when writing down data
130  bool escape_read; //< whether to behave like an escape object when reading out data
131  bool copy_to_no_skip; //< whether to hide holes by zeored bytes in the copy_to() methods
132  bool seen_hole; //< whether a hole has been seen or this is a plain file so far
133  bool data_escaped; //< whether some data has been escaped to not collide with a mark (may occur even when no hole is met)
134 
137  void dump_pending_zeros();
138 
140  void write_hole(const infinint & length);
141 
143 
151  static bool look_for_hole(const char *a, U_I size, U_I min_hole_size, U_I & start, U_I & length);
152 
154 
158  static U_I count_initial_zeros(const char *a, U_I size);
159  };
160 
161 
162 } // end of namespace
163 
165 
166 #endif
U_32 copy_to(generic_file &ref, U_32 size)
small copy (up to 4GB) with CRC calculation
class generic_file is defined here as well as class fichierthe generic_file interface is widely used ...
class escape definition, used for sequential reading of archivesThe class escape is used to insert es...