Disk ARchive  2.4.21
catalogue.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 
25 
26 #ifndef CATALOGUE_HPP
27 #define CATALOGUE_HPP
28 
29 #include "../my_config.h"
30 
31 extern "C"
32 {
33 #if HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 } // end extern "C"
37 
38 #include <vector>
39 #include <map>
40 #include <new>
41 #include "infinint.hpp"
42 #include "generic_file.hpp"
43 #include "path.hpp"
44 #include "header_version.hpp"
45 #include "ea.hpp"
46 #include "compressor.hpp"
47 #include "integers.hpp"
48 #include "mask.hpp"
49 #include "special_alloc.hpp"
50 #include "user_interaction.hpp"
51 #include "label.hpp"
52 #include "escape.hpp"
53 
54 namespace libdar
55 {
56  class etoile;
57  class entree;
58 
61 
62  enum saved_status
63  {
64  s_saved, //< inode is saved in the archive
65  s_fake, //< inode is not saved in the archive but is in the archive of reference (isolation context) s_fake is no more used in archive format "08" and above: isolated catalogue do keep the data pointers and s_saved stays a valid status in isolated catalogues.
66  s_not_saved //< inode is not saved in the archive
67  };
68 
70  struct entree_stats
71  {
72  infinint num_x; //< number of file referenced as destroyed since last backup
73  infinint num_d; //< number of directories
74  infinint num_f; //< number of plain files (hard link or not, thus file directory entries)
75  infinint num_c; //< number of char devices
76  infinint num_b; //< number of block devices
77  infinint num_p; //< number of named pipes
78  infinint num_s; //< number of unix sockets
79  infinint num_l; //< number of symbolic links
80  infinint num_D; //< number of Door
81  infinint num_hard_linked_inodes; //< number of inode that have more than one link (inode with "hard links")
82  infinint num_hard_link_entries; //< total number of hard links (file directory entry pointing to \an
83  //< inode already linked in the same or another directory (i.e. hard linked))
84  infinint saved; //< total number of saved inode (unix inode, not inode class) hard links do not count here
85  infinint total; //< total number of inode in archive (unix inode, not inode class) hard links do not count here
86  void clear() { num_x = num_d = num_f = num_c = num_b = num_p
87  = num_s = num_l = num_D = num_hard_linked_inodes
88  = num_hard_link_entries = saved = total = 0; };
89  void add(const entree *ref);
90  void listing(user_interaction & dialog) const;
91  };
92 
94  class entree
95  {
96  public :
97  static entree *read(user_interaction & dialog,
98  generic_file & f, const archive_version & reading_ver,
99  entree_stats & stats,
100  std::map <infinint, etoile *> & corres,
101  compression default_algo,
102  generic_file *data_loc,
103  generic_file *ea_loc,
104  bool lax,
105  bool only_detruit,
106  escape *ptr);
107 
108  virtual ~entree() {};
109 
111 
118  void dump(generic_file & f, bool small) const;
119 
121 
128  void specific_dump(generic_file & f, bool small) const { inherited_dump(f, small); };
129 
131 
134  virtual void post_constructor(generic_file & f) {};
135 
136 
137  virtual unsigned char signature() const = 0;
138  virtual entree *clone() const = 0;
139 
140 #ifdef LIBDAR_SPECIAL_ALLOC
141  USE_SPECIAL_ALLOC(entree);
142 #endif
143 
144  protected:
145  virtual void inherited_dump(generic_file & f, bool small) const;
146 
147 
148  private:
149  static const U_I ENTREE_CRC_SIZE;
150 
151  };
152 
153  extern bool compatible_signature(unsigned char a, unsigned char b);
154  extern unsigned char mk_signature(unsigned char base, saved_status state);
155  extern unsigned char get_base_signature(unsigned char a);
156 
158  class eod : public entree
159  {
160  public :
161  eod() {};
162  eod(generic_file & f) {};
163  // dump defined by entree
164  unsigned char signature() const { return 'z'; };
165  entree *clone() const { return new (std::nothrow) eod(); };
166 
167 
168 #ifdef LIBDAR_SPECIAL_ALLOC
169  USE_SPECIAL_ALLOC(eod);
170 #endif
171  };
172 
174  class nomme : public entree
175  {
176  public:
177  nomme(const std::string & name) { xname = name; };
178  nomme(generic_file & f);
179  virtual bool operator == (const nomme & ref) const { return xname == ref.xname; };
180  virtual bool operator < (const nomme & ref) const { return xname < ref.xname; };
181 
182  const std::string & get_name() const { return xname; };
183  void change_name(const std::string & x) { xname = x; };
184  bool same_as(const nomme & ref) const { return xname == ref.xname; };
185  // no need to have a virtual method, as signature will differ in inherited classes (argument type changes)
186 
187  // signature() is kept as an abstract method
188  // clone() is abstract
189 
190 #ifdef LIBDAR_SPECIAL_ALLOC
191  USE_SPECIAL_ALLOC(nomme);
192 #endif
193 
194  protected:
195  void inherited_dump(generic_file & f, bool small) const;
196 
197  private:
198  std::string xname;
199  };
200 
201 
203  class inode : public nomme
204  {
205  public:
206 
208 
210  {
211  cf_all, //< consider any available field for comparing inodes
212  cf_ignore_owner, //< consider any available field except ownership fields
213  cf_mtime, //< consider any available field except ownership and permission fields
214  cf_inode_type //< only consider the file type
215  };
216 
217  inode(const infinint & xuid, const infinint & xgid, U_16 xperm,
218  const infinint & last_access,
219  const infinint & last_modif,
220  const infinint & last_change,
221  const std::string & xname, const infinint & device);
222  inode(user_interaction & dialog,
223  generic_file & f,
224  const archive_version & reading_ver,
225  saved_status saved,
226  generic_file *ea_loc,
227  escape *ptr); // if ptr is not NULL, reading a partial dump(), which was done with "small" set to true
228  inode(const inode & ref);
229  const inode & operator = (const inode & ref);
230  ~inode();
231 
232  const infinint & get_uid() const { return uid; };
233  const infinint & get_gid() const { return gid; };
234  U_16 get_perm() const { return perm; };
235  infinint get_last_access() const { return *last_acc; };
236  infinint get_last_modif() const { return *last_mod; };
237  void set_last_access(const infinint & x_time) { *last_acc = x_time; };
238  void set_last_modif(const infinint & x_time) { *last_mod = x_time; };
239  saved_status get_saved_status() const { return xsaved; };
240  void set_saved_status(saved_status x) { xsaved = x; };
241  infinint get_device() const { return *fs_dev; };
242 
243  bool same_as(const inode & ref) const;
244  bool is_more_recent_than(const inode & ref, const infinint & hourshift) const;
245  // used for RESTORATION
246  virtual bool has_changed_since(const inode & ref, const infinint & hourshift, comparison_fields what_to_check) const;
247  // signature() left as an abstract method
248  // clone is abstract too
249  // used for INCREMENTAL BACKUP
250  void compare(const inode &other,
251  const mask & ea_mask,
252  comparison_fields what_to_check,
253  const infinint & hourshift,
254  bool symlink_date) const;
255 
256  // throw Erange exception if a difference has been detected
257  // this is not a symetrical comparison, but all what is present
258  // in the current object is compared against the argument
259  // which may contain supplementary informations
260  // used for DIFFERENCE
261 
262 
263 
265  // EXTENDED ATTRIBUTS Methods
266  //
267 
268  enum ea_status { ea_none, ea_partial, ea_fake, ea_full, ea_removed };
269  // ea_none : no EA present for this inode in filesystem
270  // ea_partial : EA present in filesystem but not stored (ctime used to check changes)
271  // ea_fake : EA present in filesystem but not attached to this inode (isolation context) no more used in archive version "08" and above, ea_partial or ea_full stays a valid status in isolated catalogue because pointers to EA and data are no more removed during isolation process.
272  // ea_full : EA present in filesystem and attached to this inode
273  // ea_removed : EA were present in the reference version, but not present anymore
274 
275  // I : to know whether EA data is present or not for this object
276  void ea_set_saved_status(ea_status status);
277  ea_status ea_get_saved_status() const { return ea_saved; };
278 
279  // II : to associate EA list to an inode object (mainly for backup operation) #EA_FULL only#
280  void ea_attach(ea_attributs *ref);
281  const ea_attributs *get_ea() const; // #<-- EA_FULL *and* EA_REMOVED# for this call only
282  void ea_detach() const; //discards any future call to get_ea() !
283  infinint ea_get_size() const; //returns the size of EA (still valid if ea have been detached)
284 
285  // III : to record where is dump the EA in the archive #EA_FULL only#
286  void ea_set_offset(const infinint & pos) { *ea_offset = pos; };
287  void ea_set_crc(const crc & val);
288  void ea_get_crc(const crc * & ptr) const; //< the argument is set the an allocated crc object owned by this "inode" object, this reference stays valid while the "inode" object exists and MUST NOT be deleted by the caller in any case
289  bool ea_get_crc_size(infinint & val) const; //< returns true if crc is know and puts its width in argument
290 
291  // IV : to know/record if EA have been modified # any EA status#
292  infinint get_last_change() const;
293  void set_last_change(const infinint & x_time);
294  bool has_last_change() const { return last_cha != NULL; };
295  // old format did provide last_change only when EA were present, since archive
296  // format 8, this field is always present even in absence of EA. Thus it is
297  // still necessary to check if the inode has a last_change() before
298  // using get_last_change() (depends on the version of the archive read).
299 
300 
301  // V : for archive migration (merging)
302  void change_ea_location(generic_file *loc) { storage = loc; };
303 
305 
306 #ifdef LIBDAR_SPECIAL_ALLOC
307  USE_SPECIAL_ALLOC(inode);
308 #endif
309 
310  protected:
311  virtual void sub_compare(const inode & other) const {};
312 
314  escape *get_escape_layer() const { return esc; };
315 
316  void inherited_dump(generic_file & f, bool small) const;
317 
318  private :
319  infinint uid;
320  infinint gid;
321  U_16 perm;
322  infinint *last_acc, *last_mod;
323  saved_status xsaved;
324  ea_status ea_saved;
325  // the following is used only if ea_saved == full
326  infinint *ea_offset;
327  ea_attributs *ea;
328  infinint ea_size;
329  // the following is used if ea_saved == full or ea_saved == partial
330  infinint *last_cha;
331  crc *ea_crc;
332  infinint *fs_dev;
333  generic_file *storage; // where are stored EA
334  archive_version edit; // need to know EA format used in archive file
335 
336  escape *esc; // if not NULL, the object is partially build from archive (at archive generation, dump() was called with small set to true)
337 
338  static const ea_attributs empty_ea;
339  };
340 
342  class etoile
343  {
344  public:
345 
347 
351  etoile(inode *host, const infinint & etiquette_number);
352  etoile(const etoile & ref) { throw SRC_BUG; }; // copy constructor not allowed for this class
353  const etoile & operator = (const etoile & ref) { throw SRC_BUG; }; // assignment not allowed for this class
354  ~etoile() { delete hosted; };
355 
356  void add_ref(void *ref);
357  void drop_ref(void *ref);
358  infinint get_ref_count() const { return refs.size(); };
359  inode *get_inode() const { return hosted; };
360  infinint get_etiquette() const { return etiquette; };
361  void change_etiquette(const infinint & new_val) { etiquette = new_val; };
362 
363 
364  bool is_counted() const { return tags.counted; };
365  bool is_wrote() const { return tags.wrote; };
366  bool is_dumped() const { return tags.dumped; };
367  void set_counted(bool val) { tags.counted = val ? 1 : 0; };
368  void set_wrote(bool val) { tags.wrote = val ? 1 : 0; };
369  void set_dumped(bool val) { tags.dumped = val ? 1 : 0; };
370 
371  // return the address of the first mirage that triggered the creation of this mirage
372  // if this object is destroyed afterward this call returns NULL
373  const void *get_first_ref() const { if(refs.size() == 0) throw SRC_BUG; return refs.front(); };
374 
375 #ifdef LIBDAR_SPECIAL_ALLOC
376  USE_SPECIAL_ALLOC(etoile);
377 #endif
378 
379  private:
380  struct bool_tags
381  {
382  unsigned counted : 1; //< whether the inode has been counted
383  unsigned wrote : 1; //< whether the inode has its data copied to archive
384  unsigned dumped : 1; //< whether the inode information has been dumped in the catalogue
385  unsigned : 5; //< padding to get byte boundary and reserved for future use.
386 
387  bool_tags() { counted = wrote = dumped = 0; };
388  };
389 
390  std::list<void *> refs; //< list of pointers to the mirages objects, in the order of their creation
391  inode *hosted;
392  infinint etiquette;
393  bool_tags tags;
394  };
395 
397 
399  class mirage : public nomme
400  {
401  public:
402  enum mirage_format {fmt_mirage, //< new format
403  fmt_hard_link, //< old dual format
404  fmt_file_etiquette }; //< old dual format
405 
406  mirage(const std::string & name, etoile *ref) : nomme(name) { star_ref = ref; if(ref == NULL) throw SRC_BUG; star_ref->add_ref(this); };
407  mirage(user_interaction & dialog,
408  generic_file & f,
409  const archive_version & reading_ver,
410  saved_status saved,
411  entree_stats & stats,
412  std::map <infinint, etoile *> & corres,
413  compression default_algo,
414  generic_file *data_loc,
415  generic_file *ea_loc,
416  mirage_format fmt,
417  bool lax,
418  escape *ptr);
419  mirage(user_interaction & dialog,
420  generic_file & f,
421  const archive_version & reading_ver,
422  saved_status saved,
423  entree_stats & stats,
424  std::map <infinint, etoile *> & corres,
425  compression default_algo,
426  generic_file *data_loc,
427  generic_file *ea_loc,
428  bool lax,
429  escape *ptr);
430  mirage(const mirage & ref) : nomme (ref) { star_ref = ref.star_ref; if(star_ref == NULL) throw SRC_BUG; star_ref->add_ref(this); };
431  const mirage & operator = (const mirage & ref);
432  ~mirage() { star_ref->drop_ref(this); };
433 
434  unsigned char signature() const { return 'm'; };
435  entree *clone() const { return new (std::nothrow) mirage(*this); };
436 
437  inode *get_inode() const { if(star_ref == NULL) throw SRC_BUG; return star_ref->get_inode(); };
438  infinint get_etiquette() const { return star_ref->get_etiquette(); };
439  infinint get_etoile_ref_count() const { return star_ref->get_ref_count(); };
440  etoile *get_etoile() const { return star_ref; };
441 
442  bool is_inode_counted() const { return star_ref->is_counted(); };
443  bool is_inode_wrote() const { return star_ref->is_wrote(); };
444  bool is_inode_dumped() const { return star_ref->is_dumped(); };
445  void set_inode_counted(bool val) const { star_ref->set_counted(val); };
446  void set_inode_wrote(bool val) const { star_ref->set_wrote(val); };
447  void set_inode_dumped(bool val) const { star_ref->set_dumped(val); };
448 
449  void post_constructor(generic_file & f);
450 
452  bool is_first_mirage() const { return star_ref->get_first_ref() == this; };
453 
454 #ifdef LIBDAR_SPECIAL_ALLOC
455  USE_SPECIAL_ALLOC(mirage);
456 #endif
457 
458  protected:
459  void inherited_dump(generic_file & f, bool small) const;
460 
461  private:
462  etoile *star_ref;
463 
464  void init(user_interaction & dialog,
465  generic_file & f,
466  const archive_version & reading_ver,
467  saved_status saved,
468  entree_stats & stats,
469  std::map <infinint, etoile *> & corres,
470  compression default_algo,
471  generic_file *data_loc,
472  generic_file *ea_loc,
473  mirage_format fmt,
474  bool lax,
475  escape *ptr);
476  };
477 
478 
480  class file : public inode
481  {
482  public :
483  enum get_data_mode
484  {
485  keep_compressed, //< provide access to compressed data
486  keep_hole, //< provide access to uncompressed data but sparse_file datastructure
487  normal, //< provide access to full data (uncompressed, uses skip() to restore holes)
488  plain //< provide access to plain data, no skip to restore holes, provide instead zeroed bytes
489  };
490 
491  static const U_8 FILE_DATA_WITH_HOLE = 0x01; //< file's data contains hole datastructure
492  static const U_8 FILE_DATA_IS_DIRTY = 0x02; //< data modified while being saved
493 
494  file(const infinint & xuid, const infinint & xgid, U_16 xperm,
495  const infinint & last_access,
496  const infinint & last_modif,
497  const infinint & last_change,
498  const std::string & src,
499  const path & che,
500  const infinint & taille,
501  const infinint & fs_device,
502  bool x_furtive_read_mode);
503  file(const file & ref);
504  file(user_interaction & dialog,
505  generic_file & f,
506  const archive_version & reading_ver,
507  saved_status saved,
508  compression default_algo,
509  generic_file *data_loc,
510  generic_file *ea_loc,
511  escape *ptr);
512  ~file() { detruit(); };
513 
514  bool has_changed_since(const inode & ref, const infinint & hourshift, inode::comparison_fields what_to_check) const;
515  infinint get_size() const { return *size; };
516  void change_size(const infinint & s) const { *size = s; };
517  infinint get_storage_size() const { return *storage_size; };
518  void set_storage_size(const infinint & s) { *storage_size = s; };
519  virtual generic_file *get_data(get_data_mode mode) const; // returns a newly allocated object in read_only mode
520  void clean_data(); // partially free memory (but get_data() becomes disabled)
521  void set_offset(const infinint & r);
522  const infinint & get_offset() const;
523  unsigned char signature() const { return mk_signature('f', get_saved_status()); };
524 
525  void set_crc(const crc &c);
526  bool get_crc(const crc * & c) const; //< the argument is set the an allocated crc object the owned by the "file" object, its stay valid while this "file" object exists and MUST NOT be deleted by the caller in any case
527  bool has_crc() const { return check != NULL; };
528  bool get_crc_size(infinint & val) const; //< returns true if crc is know and puts its width in argument
529  void drop_crc() { if(check != NULL) { delete check; check = NULL; } };
530 
531  // whether the plain file has to detect sparse file
532  void set_sparse_file_detection_read(bool val) { if(status == from_cat) throw SRC_BUG; if(val) file_data_status_read |= FILE_DATA_WITH_HOLE; else file_data_status_read &= ~FILE_DATA_WITH_HOLE; };
533 
534  void set_sparse_file_detection_write(bool val) { if(val) file_data_status_write |= FILE_DATA_WITH_HOLE; else file_data_status_write &= ~FILE_DATA_WITH_HOLE; };
535 
536  // whether the plain file is stored with a sparse_file datastructure in the archive
537  bool get_sparse_file_detection_read() const { return (file_data_status_read & FILE_DATA_WITH_HOLE) != 0; };
538  bool get_sparse_file_detection_write() const { return (file_data_status_write & FILE_DATA_WITH_HOLE) != 0; };
539 
540  entree *clone() const { return new (std::nothrow) file(*this); };
541 
542  compression get_compression_algo_read() const { return algo_read; };
543 
544  compression get_compression_algo_write() const { return algo_write; };
545 
546  // object migration methods (merging)
547  void change_compression_algo_write(compression x) { algo_write = x; };
548  void change_location(generic_file *x) { loc = x; };
549 
550  // dirtiness
551 
552  bool is_dirty() const { return dirty; };
553  void set_dirty(bool value) { dirty = value; };
554 
555 #ifdef LIBDAR_SPECIAL_ALLOC
556  USE_SPECIAL_ALLOC(file);
557 #endif
558 
559  protected:
560  void sub_compare(const inode & other) const;
561  void inherited_dump(generic_file & f, bool small) const;
562  void post_constructor(generic_file & f);
563 
564  enum { empty, from_path, from_cat } status;
565 
566  private:
567  std::string chemin; //< path to the data (when read from filesystem)
568  infinint *offset; //< start location of the data in 'loc'
569  infinint *size; //< size of the data (uncompressed)
570  infinint *storage_size; //< how much data used in archive (after compression)
571  crc *check;
572  bool dirty; //< true when a file has been modified at the time it was saved
573 
574  generic_file *loc; //< where to find data (eventually compressed) at the recorded offset and for storage_size length
575  compression algo_read; //< which compression algorithm to use to read the file's data
576  compression algo_write; //< which compression algorithm to use to write down (merging) the file's data
577  bool furtive_read_mode; // used only when status equals "from_path"
578  char file_data_status_read; // defines the datastructure to use when reading the data
579  char file_data_status_write; // defines the datastructure to apply when writing down the data
580 
581  void detruit();
582  };
583 
585  class door : public file
586  {
587  public:
588  door(const infinint & xuid, const infinint & xgid, U_16 xperm,
589  const infinint & last_access,
590  const infinint & last_modif,
591  const infinint & last_change,
592  const std::string & src,
593  const path & che,
594  const infinint & fs_device) : file(xuid, xgid, xperm, last_access, last_modif,
595  last_change, src, che, 0, fs_device, false) {};
596  door(user_interaction & dialog,
597  generic_file & f,
598  const archive_version & reading_ver,
599  saved_status saved,
600  compression default_algo,
601  generic_file *data_loc,
602  generic_file *ea_loc,
603  escape *ptr) : file(dialog, f, reading_ver, saved, default_algo, data_loc, ea_loc, ptr) {};
604 
605  unsigned char signature() const { return mk_signature('o', get_saved_status()); };
606 
607  generic_file *get_data(get_data_mode mode) const; // inherited from class file
608 
609 #ifdef LIBDAR_SPECIAL_ALLOC
610  USE_SPECIAL_ALLOC(door);
611 #endif
612  };
613 
615  class lien : public inode
616  {
617  public :
618  lien(const infinint & uid, const infinint & gid, U_16 perm,
619  const infinint & last_access,
620  const infinint & last_modif,
621  const infinint & last_change,
622  const std::string & name,
623  const std::string & target,
624  const infinint & fs_device);
625  lien(user_interaction & dialog,
626  generic_file & f,
627  const archive_version & reading_ver,
628  saved_status saved,
629  generic_file *ea_loc,
630  escape *ptr);
631 
632  const std::string & get_target() const;
633  void set_target(std::string x);
634 
635  // using the method is_more_recent_than() from inode
636  // using method has_changed_since() from inode class
637  unsigned char signature() const { return mk_signature('l', get_saved_status()); };
638  entree *clone() const { return new (std::nothrow) lien(*this); };
639 
640 #ifdef LIBDAR_SPECIAL_ALLOC
641  USE_SPECIAL_ALLOC(lien);
642 #endif
643  protected :
644  void sub_compare(const inode & other) const;
645  void inherited_dump(generic_file & f, bool small) const;
646 
647 
648  private :
649  std::string points_to;
650  };
651 
653  class directory : public inode
654  {
655  public :
656  directory(const infinint & xuid, const infinint & xgid, U_16 xperm,
657  const infinint & last_access,
658  const infinint & last_modif,
659  const infinint & last_change,
660  const std::string & xname,
661  const infinint & device);
662  directory(const directory &ref); // only the inode part is build, no children is duplicated (empty dir)
663  const directory & operator = (const directory & ref); // set the inode part *only* no subdirectories/subfiles are copies or removed.
664  directory(user_interaction & dialog,
665  generic_file & f,
666  const archive_version & reading_ver,
667  saved_status saved,
668  entree_stats & stats,
669  std::map <infinint, etoile *> & corres,
670  compression default_algo,
671  generic_file *data_loc,
672  generic_file *ea_loc,
673  bool lax,
674  bool only_detruit, // objects of other class than detruit and directory are not built in memory
675  escape *ptr);
676  ~directory(); // detruit aussi tous les fils et se supprime de son 'parent'
677 
678  void add_children(nomme *r); // when r is a directory, 'parent' is set to 'this'
679  bool has_children() const { return !ordered_fils.empty(); };
680  void reset_read_children() const;
681  void end_read() const;
682  bool read_children(const nomme * &r) const; // read the direct children of the directory, returns false if no more is available
683  // remove all entry not yet read by read_children
684  void tail_to_read_children();
685 
686  void remove(const std::string & name); // remove the given entry from the catalogue
687  // as side effect the reset_read_children() method must be called.
688 
689  directory * get_parent() const { return parent; };
690  bool search_children(const std::string &name, nomme *&ref);
691  bool callback_for_children_of(user_interaction & dialog, const std::string & sdir, bool isolated = false) const;
692 
693  // using is_more_recent_than() from inode class
694  // using method has_changed_since() from inode class
695  unsigned char signature() const { return mk_signature('d', get_saved_status()); };
696 
697  // some data has changed since archive of reference in this directory or subdirectories
698  bool get_recursive_has_changed() const { return recursive_has_changed; };
699  // update the recursive_has_changed field
700  void recursive_has_changed_update() const;
701 
703  infinint get_tree_size() const;
704 
706  infinint get_tree_ea_num() const;
707 
709  infinint get_tree_mirage_num() const;
710 
711  // for each mirage found (hard link implementation) in the directory tree, add its etiquette to the returned
712  // list with the number of reference that has been found in the tree. (map[etiquette] = number of occurence)
713  // from outside of class directory, the given argument is expected to be an empty map.
714  void get_etiquettes_found_in_tree(std::map<infinint, infinint> & already_found) const;
715 
717  bool is_empty() const { return ordered_fils.empty(); };
718 
720  void remove_all_mirages_and_reduce_dirs();
721 
723  void recursive_set_mirage_inode_wrote(bool val);
724 
725  entree *clone() const { return new (std::nothrow) directory(*this); };
726 
727 #ifdef LIBDAR_SPECIAL_ALLOC
728  USE_SPECIAL_ALLOC(directory);
729 #endif
730 
731  protected:
732  void inherited_dump(generic_file & f, bool small) const;
733 
734  private :
735  static const eod fin;
736 
737  directory *parent;
738 #ifdef LIBDAR_FAST_DIR
739  std::map<std::string, nomme *> fils; // used for fast lookup
740 #endif
741  std::list<nomme *> ordered_fils;
742  std::list<nomme *>::iterator it;
743  bool recursive_has_changed;
744 
745  void clear();
746  };
747 
749  class device : public inode
750  {
751  public :
752  device(const infinint & uid, const infinint & gid, U_16 perm,
753  const infinint & last_access,
754  const infinint & last_modif,
755  const infinint &last_change,
756  const std::string & name,
757  U_16 major,
758  U_16 minor,
759  const infinint & fs_device);
760  device(user_interaction & dialog,
761  generic_file & f,
762  const archive_version & reading_ver,
763  saved_status saved,
764  generic_file *ea_loc,
765  escape *ptr);
766 
767  int get_major() const { if(get_saved_status() != s_saved) throw SRC_BUG; else return xmajor; };
768  int get_minor() const { if(get_saved_status() != s_saved) throw SRC_BUG; else return xminor; };
769  void set_major(int x) { xmajor = x; };
770  void set_minor(int x) { xminor = x; };
771 
772  // using method is_more_recent_than() from inode class
773  // using method has_changed_since() from inode class
774  // signature is left pure abstract
775 
776 #ifdef LIBDAR_SPECIAL_ALLOC
777  USE_SPECIAL_ALLOC(device);
778 #endif
779 
780  protected :
781  void sub_compare(const inode & other) const;
782  void inherited_dump(generic_file & f, bool small) const;
783 
784  private :
785  U_16 xmajor, xminor;
786  };
787 
789  class chardev : public device
790  {
791  public:
792  chardev(const infinint & uid, const infinint & gid, U_16 perm,
793  const infinint & last_access,
794  const infinint & last_modif,
795  const infinint & last_change,
796  const std::string & name,
797  U_16 major,
798  U_16 minor,
799  const infinint & fs_device) : device(uid, gid, perm,
800  last_access,
801  last_modif,
802  last_change,
803  name,
804  major, minor, fs_device) {};
805  chardev(user_interaction & dialog,
806  generic_file & f,
807  const archive_version & reading_ver,
808  saved_status saved,
809  generic_file *ea_loc,
810  escape *ptr) : device(dialog, f, reading_ver, saved, ea_loc, ptr) {};
811 
812  // using dump from device class
813  // using method is_more_recent_than() from device class
814  // using method has_changed_since() from device class
815  unsigned char signature() const { return mk_signature('c', get_saved_status()); };
816  entree *clone() const { return new (std::nothrow) chardev(*this); };
817 
818 #ifdef LIBDAR_SPECIAL_ALLOC
819  USE_SPECIAL_ALLOC(chardev);
820 #endif
821  };
822 
824  class blockdev : public device
825  {
826  public:
827  blockdev(const infinint & uid, const infinint & gid, U_16 perm,
828  const infinint & last_access,
829  const infinint & last_modif,
830  const infinint & last_change,
831  const std::string & name,
832  U_16 major,
833  U_16 minor,
834  const infinint & fs_device) : device(uid, gid, perm, last_access,
835  last_modif, last_change, name,
836  major, minor, fs_device) {};
837  blockdev(user_interaction & dialog,
838  generic_file & f,
839  const archive_version & reading_ver,
840  saved_status saved,
841  generic_file *ea_loc,
842  escape *ptr) : device(dialog, f, reading_ver, saved, ea_loc, ptr) {};
843 
844  // using dump from device class
845  // using method is_more_recent_than() from device class
846  // using method has_changed_since() from device class
847  unsigned char signature() const { return mk_signature('b', get_saved_status()); };
848  entree *clone() const { return new (std::nothrow) blockdev(*this); };
849 
850 #ifdef LIBDAR_SPECIAL_ALLOC
851  USE_SPECIAL_ALLOC(blockdev);
852 #endif
853  };
854 
856  class tube : public inode
857  {
858  public :
859  tube(const infinint & xuid, const infinint & xgid, U_16 xperm,
860  const infinint & last_access,
861  const infinint & last_modif,
862  const infinint & last_change,
863  const std::string & xname,
864  const infinint & fs_device) : inode(xuid, xgid, xperm, last_access, last_modif, last_change, xname, fs_device) { set_saved_status(s_saved); };
865  tube(user_interaction & dialog,
866  generic_file & f,
867  const archive_version & reading_ver,
868  saved_status saved,
869  generic_file *ea_loc,
870  escape *ptr) : inode(dialog, f, reading_ver, saved, ea_loc, ptr) {};
871 
872  // using dump from inode class
873  // using method is_more_recent_than() from inode class
874  // using method has_changed_since() from inode class
875  unsigned char signature() const { return mk_signature('p', get_saved_status()); };
876  entree *clone() const { return new (std::nothrow) tube(*this); };
877 
878 #ifdef LIBDAR_SPECIAL_ALLOC
879  USE_SPECIAL_ALLOC(tube);
880 #endif
881  };
882 
884  class prise : public inode
885  {
886  public :
887  prise(const infinint & xuid, const infinint & xgid, U_16 xperm,
888  const infinint & last_access,
889  const infinint & last_modif,
890  const infinint & last_change,
891  const std::string & xname,
892  const infinint & fs_device) : inode(xuid, xgid, xperm, last_access, last_modif, last_change, xname, fs_device) { set_saved_status(s_saved); };
893  prise(user_interaction & dialog,
894  generic_file & f,
895  const archive_version & reading_ver,
896  saved_status saved,
897  generic_file *ea_loc,
898  escape *ptr) : inode(dialog, f, reading_ver, saved, ea_loc, ptr) {};
899 
900  // using dump from inode class
901  // using method is_more_recent_than() from inode class
902  // using method has_changed_since() from inode class
903  unsigned char signature() const { return mk_signature('s', get_saved_status()); };
904  entree *clone() const { return new (std::nothrow) prise(*this); };
905 
906 #ifdef LIBDAR_SPECIAL_ALLOC
907  USE_SPECIAL_ALLOC(prise);
908 #endif
909  };
910 
912  class detruit : public nomme
913  {
914  public :
915  detruit(const std::string & name, unsigned char firm, const infinint & date) : nomme(name) , del_date(date) { signe = firm; };
916  detruit(generic_file & f, const archive_version & reading_ver);
917  detruit(const nomme &ref) : nomme(ref.get_name()), del_date(0) { signe = ref.signature(); };
918 
919  unsigned char get_signature() const { return signe; };
920  void set_signature(unsigned char x) { signe = x; };
921  unsigned char signature() const { return 'x'; };
922  entree *clone() const { return new (std::nothrow) detruit(*this); };
923 
924  const infinint & get_date() const { return del_date; };
925  void set_date(const infinint & ref) { del_date = ref; };
926 
927 #ifdef LIBDAR_SPECIAL_ALLOC
928  USE_SPECIAL_ALLOC(detruit);
929 #endif
930  protected:
931  void inherited_dump(generic_file & f, bool small) const;
932 
933  private :
934  unsigned char signe;
935  infinint del_date;
936  };
937 
939  class ignored : public nomme
940  {
941  public :
942  ignored(const std::string & name) : nomme(name) {};
943  ignored(generic_file & f) : nomme(f) { throw SRC_BUG; };
944 
945  unsigned char signature() const { return 'i'; };
946  entree *clone() const { return new (std::nothrow) ignored(*this); };
947 #ifdef LIBDAR_SPECIAL_ALLOC
948  USE_SPECIAL_ALLOC(ignored);
949 #endif
950 
951  protected:
952  void inherited_dump(generic_file & f, bool small) const { throw SRC_BUG; };
953 
954  };
955 
957  class ignored_dir : public inode
958  {
959  public:
960  ignored_dir(const directory &target) : inode(target) {};
961  ignored_dir(user_interaction & dialog,
962  generic_file & f,
963  const archive_version & reading_ver,
964  generic_file *ea_loc,
965  escape *ptr) : inode(dialog, f, reading_ver, s_not_saved, ea_loc, ptr) { throw SRC_BUG; };
966 
967  unsigned char signature() const { return 'j'; };
968  entree *clone() const { return new (std::nothrow) ignored_dir(*this); };
969 #ifdef LIBDAR_SPECIAL_ALLOC
970  USE_SPECIAL_ALLOC(ignored_dir);
971 #endif
972 
973  protected:
974  void inherited_dump(generic_file & f, bool small) const; // behaves like an empty directory
975 
976  };
977 
979  class catalogue : protected mem_ui
980  {
981  public :
982  catalogue(user_interaction & dialog,
983  const infinint & root_last_modif,
984  const label & data_name);
985  catalogue(user_interaction & dialog,
986  generic_file & f,
987  const archive_version & reading_ver,
988  compression default_algo,
989  generic_file *data_loc,
990  generic_file *ea_loc,
991  bool lax,
992  const label & lax_layer1_data_name, //< ignored unless in lax mode, in lax mode unless it is a cleared label, forces the catalogue label to be equal to the lax_layer1_data_name for it be considered a plain internal catalogue, even in case of corruption
993  bool only_detruit = false); //< if set to true, only directories and detruit objects are read from the archive
994  catalogue(const catalogue & ref) : mem_ui(ref), out_compare(ref.out_compare) { partial_copy_from(ref); };
995  const catalogue & operator = (const catalogue &ref);
996  virtual ~catalogue() { detruire(); };
997 
998 
999  // reading methods. The reading is iterative and uses the current_read directory pointer
1000 
1001  virtual void reset_read() const; // set the reading cursor to the beginning of the catalogue
1002  virtual void end_read() const; // set the reading cursor to the end of the catalogue
1003  virtual void skip_read_to_parent_dir() const;
1004  // skip all items of the current dir and of any subdir, the next call will return
1005  // next item of the parent dir (no eod to exit from the current dir !)
1006  virtual bool read(const entree * & ref) const;
1007  // sequential read (generates eod) and return false when all files have been read
1008  virtual bool read_if_present(std::string *name, const nomme * & ref) const;
1009  // pseudo-sequential read (reading a directory still
1010  // implies that following read are located in this subdirectory up to the next EOD) but
1011  // it returns false if no entry of this name are present in the current directory
1012  // a call with NULL as first argument means to set the current dir the parent directory
1013  void remove_read_entry(std::string & name);
1014  // in the currently read directory, removes the entry which name is given in argument
1015  const directory & get_current_reading_dir() const { return *current_read; };
1016  // remove from the catalogue all the entries that have not yet been read
1017  // by read().
1018  void tail_catalogue_to_current_read();
1019 
1020 
1021  void reset_sub_read(const path &sub); // initialise sub_read to the given directory
1022  bool sub_read(const entree * &ref); // sequential read of the catalogue, ignoring all that
1023  // is not part of the subdirectory specified with reset_sub_read
1024  // the read include the inode leading to the sub_tree as well as the pending eod
1025 
1026  // return true if the last read entry has already been read
1027  // and has not to be counted again. This is never the case for catalogue but may occure
1028  // with escape_catalogue (where from the 'virtual').
1029  // last this method gives a valid result only if the last read() entry is a directory as
1030  // only directory may be read() twice.
1031  virtual bool read_second_time_dir() const { return false; };
1032 
1033 
1034  // Additions methods. The addition is also iterative but uses its specific current_add directory pointer
1035 
1036  void reset_add();
1037 
1039  // real implementation is only needed in escape_catalogue class, here there nothing to be done
1040  virtual void pre_add(const entree *ref, compressor *compr) const {};
1041  virtual void pre_add_ea(const entree *ref, compressor *compr) const {};
1042  virtual void pre_add_crc(const entree *ref, compressor *compr) const {};
1043  virtual void pre_add_dirty(compressor *compr) const {};
1044  virtual void pre_add_ea_crc(const entree *ref, compressor *compr) const {};
1045  virtual void pre_add_waste_mark(compressor *compr) const {};
1046  virtual void pre_add_failed_mark(compressor *compr) const {};
1047  virtual escape *get_escape_layer() const { return NULL; };
1048 
1049  void add(entree *ref); // add at end of catalogue (sequential point of view)
1050  void re_add_in(const std::string &subdirname); // return into an already existing subdirectory for further addition
1051  void re_add_in_replace(const directory &dir); // same as re_add_in but also set the properties of the existing directory to those of the given argument
1052  void add_in_current_read(nomme *ref); // add in currently read directory
1053 
1054 
1055 
1056  // Comparison methods. The comparision is here also iterative and uses its specific current_compare directory pointer
1057 
1058  void reset_compare();
1059  bool compare(const entree * name, const entree * & extracted);
1060  // returns true if the ref exists, and gives it back in second argument as it is in the current catalogue.
1061  // returns false is no entry of that nature exists in the catalogue (in the current directory)
1062  // if ref is a directory, the operation is normaly relative to the directory itself, but
1063  // such a call implies a chdir to that directory. thus, a call with an EOD is necessary to
1064  // change to the parent directory.
1065  // note :
1066  // if a directory is not present, returns false, but records the inexistant subdirectory
1067  // structure defined by the following calls to this routine, this to be able to know when
1068  // the last available directory is back the current one when changing to parent directory,
1069  // and then proceed with normal comparison of inode. In this laps of time, the call will
1070  // always return false, while it temporary stores the missing directory structure
1071 
1072 
1073 
1074  // non interative methods
1075 
1076  bool direct_read(const path & ref, const nomme * &ret);
1077  infinint update_destroyed_with(catalogue & ref);
1078  // ref must have the same root, else the operation generates an exception
1079 
1080  void update_absent_with(catalogue & ref, infinint aborting_next_etoile);
1081  // in case of abortion, completes missing files as if what could not be
1082  // inspected had not changed since the reference was done
1083  // aborting_last_etoile is the highest etoile reference withing "this" current object.
1084 
1085  void dump(generic_file & f) const;
1086  void listing(bool isolated,
1087  const mask &selection,
1088  const mask & subtree,
1089  bool filter_unsaved,
1090  bool list_ea,
1091  std::string marge) const;
1092  void tar_listing(bool isolated,
1093  const mask & selection,
1094  const mask & subtree,
1095  bool filter_unsaved,
1096  bool list_ea,
1097  std::string beginning) const;
1098  void xml_listing(bool isolated,
1099  const mask & selection,
1100  const mask & subtree,
1101  bool filter_unsaved,
1102  bool list_ea,
1103  std::string beginning) const;
1104 
1105  entree_stats get_stats() const { return stats; };
1106 
1108  bool is_empty() const { if(contenu == NULL) throw SRC_BUG; return contenu->is_empty(); };
1109 
1110  const directory *get_contenu() const { return contenu; }; // used by data_tree
1111 
1112  const label & get_data_name() const { return ref_data_name; };
1113  infinint get_root_dir_last_modif() const { return contenu->get_last_modif(); };
1114 
1116  void launch_recursive_has_changed_update() const { contenu->recursive_has_changed_update(); };
1117 
1119  void recursive_set_mirage_inode_wrote(bool val) { contenu->recursive_set_mirage_inode_wrote(val); };
1120 
1121  infinint get_root_mtime() const { return contenu->get_last_modif(); };
1122 
1124  void reset_all();
1125 
1126 
1127  protected:
1128  entree_stats & access_stats() { return stats; };
1129  void set_data_name(const label & val) { ref_data_name = val; };
1130  void copy_detruits_from(const catalogue & ref); // needed for escape_catalogue implementation only.
1131 
1132  const eod * get_r_eod_address() const { return & r_eod; }; // eod are never stored in the catalogue
1133  // however it is sometimes required to return such a reference to a valid object
1134  // owned by the catalogue.
1135 
1136 
1139  void swap_stuff(catalogue & ref);
1140 
1141  private :
1142  directory *contenu;
1143  path out_compare;
1144  directory *current_compare;
1145  directory *current_add;
1146  directory *current_read;
1147  path *sub_tree;
1148  signed int sub_count;
1149  entree_stats stats;
1150  label ref_data_name;
1151 
1152  void partial_copy_from(const catalogue &ref);
1153  void detruire();
1154 
1155  static const eod r_eod; // needed to return eod reference, without taking risk of saturating memory
1156  static const U_I CAT_CRC_SIZE;
1157  };
1158 
1159 
1160 
1162 
1163 } // end of namespace
1164 
1165 #endif
the char device class
Definition: catalogue.hpp:789
the symbolic link inode class
Definition: catalogue.hpp:615
the generic class, parent of all masks
Definition: mask.hpp:61
are defined here basic integer types that tend to be portable
the catalogue class which gather all objects contained in a give archive
Definition: catalogue.hpp:979
holds the statistics contents of a catalogue
Definition: catalogue.hpp:70
the block device class
Definition: catalogue.hpp:824
virtual void post_constructor(generic_file &f)
called by entree::read and mirage::post_constructor, let inherited classes builds object&#39;s data after...
Definition: catalogue.hpp:134
the Unix socket inode class
Definition: catalogue.hpp:884
class generic_file is defined here as well as class fichierthe generic_file interface is widely used ...
the deleted file entry
Definition: catalogue.hpp:912
define the datastructure "label" used to identify slice membership to an archive
virtual void pre_add(const entree *ref, compressor *compr) const
catalogue extension routines for escape sequence
Definition: catalogue.hpp:1040
bool is_empty() const
whether this directory is empty or not
Definition: catalogue.hpp:717
void recursive_set_mirage_inode_wrote(bool val)
recursive setting of mirage inode_wrote flag
Definition: catalogue.hpp:1119
bool ea()
returns whether EA support has been activated at compilation time
This is a pure virtual class that is used by libdar when interaction with the user is required...
the present file to ignore (not to be recorded as deleted later)
Definition: catalogue.hpp:939
the root class from all other inherite for any entry in the catalogue
Definition: catalogue.hpp:94
the base class for all entry that have a name
Definition: catalogue.hpp:174
the plain file class
Definition: catalogue.hpp:480
the hard link implementation, mirage is the named entry owned by a directory it points to a common "e...
Definition: catalogue.hpp:399
re-definition of new and delete class operatorthis is a set of macro that makes the new and delete op...
the directory inode class
Definition: catalogue.hpp:653
comparison_fields
flag used to only consider certain fields when comparing/restoring inodes
Definition: catalogue.hpp:209
the End of Directory entry class
Definition: catalogue.hpp:158
the hard link implementation (etoile means star in French, seen a star as a point from which are thro...
Definition: catalogue.hpp:342
archive global header structure is defined here
defines the interaction between libdar and the user.Three classes are defined
here is the definition of the path classthe path class handle path and provide several operation on t...
the root class for all inode
Definition: catalogue.hpp:203
the class for Door IPC (mainly for Solaris)
Definition: catalogue.hpp:585
void launch_recursive_has_changed_update() const
recursive evaluation of directories that have changed (make the directory::get_recurisve_has_changed(...
Definition: catalogue.hpp:1116
class escape definition, used for sequential reading of archivesThe class escape is used to insert es...
arbitrary large storage structure
Definition: storage.hpp:57
the special device root class
Definition: catalogue.hpp:749
switch module to limitint (32 ou 64 bits integers) or infinint
here lies a collection of mask classes
compression class for gzip and bzip2 algorithms
Definition: compressor.hpp:60
compression
the different compression algorithm available
Definition: compressor.hpp:43
this is the interface class from which all other data transfer classes inherit
the named pipe class
Definition: catalogue.hpp:856
class mem_ui to keep a copy of a user_interaction object
Definition: mem_ui.hpp:53
bool is_empty() const
whether the catalogue is empty or not
Definition: catalogue.hpp:1108
compression engine implementation
bool is_first_mirage() const
whether we are the mirage that triggered this hard link creation
Definition: catalogue.hpp:452
the arbitrary large positive integer class
class archive_version manages the version of the archive format
contains a set of routines to manage EA values associated to a file
escape * get_escape_layer() const
escape generic_file relative methods
Definition: catalogue.hpp:314
the class ea_attributs manages the set of EA that can be associated to an inode
Definition: ea.hpp:47
the ignored directory class, to be promoted later as empty directory if needed
Definition: catalogue.hpp:957
libdar namespace encapsulate all libdar symbols
Definition: archive.hpp:43
void specific_dump(generic_file &f, bool small) const
this call gives an access to inherited_dump
Definition: catalogue.hpp:128
the class path is here to manipulate paths in the Unix notation: using&#39;/&#39;
Definition: path.hpp:50