Disk ARchive  2.5.6
Full featured and portable backup and archiving tool
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 = nullptr; copy_to(ref, 0, tmp); if(tmp != nullptr) 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  bool skippable(skippability direction, const infinint & amount) { return false; };
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() const;
103 
104  protected:
105 
106  // methods from the escape class we hide from the (public) class interface
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  // methods from generic_file redefined as protected
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  // inherited_flush_read() kept as is from the escape class
119  // inherited_terminate() kept as is from the escape class
120 
121  private:
122  static bool initialized; //< whether static field "zeroed_field" has been initialized
123  static unsigned char zeroed_field[SPARSE_FIXED_ZEROED_BLOCK]; //< read-only, used when the sequence of zeros is too short for a hole
124 
125  enum { normal, hole } mode; //< wether we are currently reading/writing a hole or normal data
126  infinint zero_count; //< number of zeroed byte pending in the current hole
127  infinint offset; //< current offset in file (as if it was a plain file).
128  infinint min_hole_size; //< minimum size of hole to consider
129  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
130  bool escape_write; //< whether to behave like an escape object when writing down data
131  bool escape_read; //< whether to behave like an escape object when reading out data
132  bool copy_to_no_skip; //< whether to hide holes by zeored bytes in the copy_to() methods
133  bool seen_hole; //< whether a hole has been seen or this is a plain file so far
134  bool data_escaped; //< whether some data has been escaped to not collide with a mark (may occur even when no hole is met)
135 
138  void dump_pending_zeros();
139 
141  void write_hole(const infinint & length);
142 
146  void reset();
147 
148 
150 
158  static bool look_for_hole(const char *a, U_I size, U_I min_hole_size, U_I & start, U_I & length);
159 
161 
165  static U_I count_initial_zeros(const char *a, U_I size);
166  };
167 
168 
169 } // end of namespace
170 
172 
173 #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...
libdar namespace encapsulate all libdar symbols
Definition: archive.hpp:47