Disk ARchive  2.6.8
Full featured and portable backup and archiving tool
escape.hpp
Go to the documentation of this file.
1 /*********************************************************************/
2 // dar - disk archive - a backup/restoration program
3 // Copyright (C) 2002-2020 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 //
19 // to contact the author : http://dar.linux.free.fr/email.html
20 /*********************************************************************/
21 
37 
38 
39 #ifndef ESCAPE_HPP
40 #define ESCAPE_HPP
41 
42 #include "../my_config.h"
43 
44 extern "C"
45 {
46 #if HAVE_LIMITS_H
47 #include <limits.h>
48 #endif
49 }
50 
51 #include <set>
52 
53 #include "generic_file.hpp"
54 
55 #define ESCAPE_FIXED_SEQUENCE_NORMAL 0xAD
56 #define ESCAPE_FIXED_SEQUENCE_SPARSE_FILE 0xAE
57 
58 #define MAX_BUFFER_SIZE 102400
59 #ifdef SSIZE_MAX
60 #if SSIZE_MAX < MAX_BUFFER_SIZE
61 #undef MAX_BUFFER_SIZE
62 #define MAX_BUFFER_SIZE SSIZE_MAX
63 #endif
64 #endif
65 
66 namespace libdar
67 {
68 
71 
72  class escape : public generic_file
73  {
74  public:
75  enum sequence_type
76  {
77  seqt_undefined,
78  seqt_not_a_sequence,
79  seqt_file,
80  seqt_ea,
81  seqt_catalogue,
82  seqt_data_name,
83  seqt_file_crc,
84  seqt_ea_crc,
85  seqt_changed,
86  seqt_dirty,
87  seqt_failed_backup,
88  seqt_fsa,
89  seqt_fsa_crc,
90  seqt_delta_sig
91  };
92 
93  // the archive layout of marks is for each entry:
94  // #seqt_file# <inode> [<file data> [#seqt_changed# <new copy of data> [...] ] #seqt_file_crc# <CRC>[#seqt_dirty#]] [#seqt_ea# <EA> #seqt_ea_crc# <CRC>]
95  // this previous sequence that we will call <SEQ> is repeated for each file, then on the overall archive we have :
96  // #seqt_data_name# <data_name> <SEQ> ... <SEQ> #seqt_catalogue# <catalogue> <terminator>
97 
98  // the provided "below" object must exist during the whole live of the escape object,
99  // the escape object does not own this "below" object
100  // it must be destroyed by the caller/creator of the escape object.
101 
102 
103  // constructors & destructors
104 
105  escape(generic_file *below,
106  const std::set<sequence_type> & x_unjumpable);
107  escape(const escape & ref) : generic_file(ref) { copy_from(ref); };
108  escape(escape && ref) noexcept : generic_file(std::move(ref)) { nullifyptr(); move_from(std::move(ref)); };
109  escape & operator = (const escape & ref);
110  escape & operator = (escape && ref) noexcept { generic_file::operator = (std::move(ref)); move_from(std::move(ref)); return *this; };
111  ~escape();
112 
113  // escape specific routines
114 
115  void add_mark_at_current_position(sequence_type t);
116 
118 
123  bool skip_to_next_mark(sequence_type t, bool jump);
124  bool next_to_read_is_mark(sequence_type t);
125  bool next_to_read_is_which_mark(sequence_type & t);
126 
127  void add_unjumpable_mark(sequence_type t) { if(is_terminated()) throw SRC_BUG; unjumpable.insert(t); };
128  void remove_unjumpable_mark(sequence_type t);
129  bool is_unjumpable_mark(sequence_type t) const { return unjumpable.find(t) != unjumpable.end(); };
130  void clear_all_unjumpable_marks() { unjumpable.clear(); };
131 
132 
133  // generic_file inherited routines
134  // NOTA: Nothing is done to prevent skip* operation to put the read cursor in the middle of an escape sequence and
135  // thus incorrectly consider it as normal data. Such event should only occure upon archive corruption and will be detected
136  // by checksum mechanisms.
137 
138  virtual bool skippable(skippability direction, const infinint & amount) override;
139  virtual bool skip(const infinint & pos) override;
140  virtual bool skip_to_eof() override;
141  virtual bool skip_relative(S_I x) override;
142  virtual infinint get_position() const override;
143 
144  protected:
145  virtual void inherited_read_ahead(const infinint & amount) override;
146  virtual U_I inherited_read(char *a, U_I size) override;
147  virtual void inherited_write(const char *a, U_I size) override;
148  virtual void inherited_sync_write() override { flush_write(); };
149  virtual void inherited_flush_read() override { flush_write(); clean_read(); };
150  virtual void inherited_terminate() override { flush_or_clean(); };
151 
152  void change_fixed_escape_sequence(unsigned char value) { fixed_sequence[0] = value; };
153  bool has_escaped_data_since_last_skip() const { return escaped_data_count_since_last_skip > 0; };
154 
155  private:
156 
157  //-- constants
158 
160  static constexpr U_I ESCAPE_SEQUENCE_LENGTH = 6;
161  static constexpr U_I WRITE_BUFFER_SIZE = 2*ESCAPE_SEQUENCE_LENGTH;
162  static constexpr U_I READ_BUFFER_SIZE = MAX_BUFFER_SIZE;
163  static const infinint READ_BUFFER_SIZE_INFININT;
164 
166 
172  static const unsigned char usual_fixed_sequence[ESCAPE_SEQUENCE_LENGTH];
173 
174  //-- variables
175 
176  generic_file *x_below;
177  U_I write_buffer_size;
178  char write_buffer[WRITE_BUFFER_SIZE];
179  U_I read_buffer_size;
181  U_I already_read;
182  bool read_eof;
183  U_I escape_seq_offset_in_buffer;
184  char read_buffer[READ_BUFFER_SIZE];
185  std::set<sequence_type> unjumpable;
186  unsigned char fixed_sequence[ESCAPE_SEQUENCE_LENGTH];
187  infinint escaped_data_count_since_last_skip;
188  infinint below_position;
189 
190  //-- routines
191 
192  void set_fixed_sequence_for(sequence_type t) { fixed_sequence[ESCAPE_SEQUENCE_LENGTH - 1] = type2char(t); };
193  void check_below() const { if(x_below == nullptr) throw SRC_BUG; };
194  void clean_read();
195  void flush_write();
196  void flush_or_clean()
197  {
198  switch(get_mode())
199  {
200  case gf_read_only:
201  clean_read();
202  break;
203  case gf_write_only:
204  case gf_read_write:
205  flush_write();
206  break;
207  default:
208  throw SRC_BUG;
209  }
210  };
211  void nullifyptr() noexcept { x_below = nullptr; };
212  void copy_from(const escape & ref);
213  void move_from(escape && ref) noexcept;
214  bool mini_read_buffer();
215 
216  //-- static routine(s)
217 
218  // some convertion routines
219  static char type2char(sequence_type x);
220  static sequence_type char2type(char x);
221 
223 
225 
228  static U_I trouve_amorce(const char *a, U_I size, const unsigned char escape_sequence[ESCAPE_SEQUENCE_LENGTH]);
229 
231 
238  static U_I remove_data_marks_and_stop_at_first_real_mark(char *a, U_I size, U_I & delta, const unsigned char escape_sequence[ESCAPE_SEQUENCE_LENGTH]);
239  };
240 
242 
243 } // end of namespace
244 
245 #endif
libdar::generic_file::generic_file
generic_file(gf_mode m)
main constructor
Definition: generic_file.hpp:80
libdar::saved_status::delta
inode is saved but as delta binary from the content (delta signature) of what was found in the archiv...
libdar::generic_file::is_terminated
bool is_terminated() const
Definition: generic_file.hpp:300
libdar::generic_file::get_mode
gf_mode get_mode() const
retreive the openning mode for this object
Definition: generic_file.hpp:109
generic_file.hpp
class generic_file is defined here as well as class fichier
libdar::gf_write_only
write only access
Definition: gf_mode.hpp:46
libdar::gf_read_write
read and write access
Definition: gf_mode.hpp:47
libdar::gf_read_only
read only access
Definition: gf_mode.hpp:45
libdar::generic_file::operator=
generic_file & operator=(const generic_file &ref)
assignment operator
Definition: generic_file.hpp:89
libdar
libdar namespace encapsulate all libdar symbols
Definition: archive.hpp:46