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 
22     /// \file catalogue.hpp
23     /// \brief here is defined the many classed which is build of the catalogue
24     /// \ingroup Private
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 "infinint.hpp"
39 #include "generic_file.hpp"
40 #include "path.hpp"
41 #include "compressor.hpp"
42 #include "integers.hpp"
43 #include "mask.hpp"
44 #include "user_interaction.hpp"
45 #include "label.hpp"
46 #include "escape.hpp"
47 #include "on_pool.hpp"
48 #include "datetime.hpp"
49 #include "slice_layout.hpp"
50 #include "mem_ui.hpp"
51 #include "cat_entree.hpp"
52 #include "cat_nomme.hpp"
53 #include "cat_directory.hpp"
54 
55 namespace libdar
56 {
57 
58 	/// \addtogroup Private
59 	/// @{
60 
61 	/// the catalogue class which gather all objects contained in a give archive
62     class catalogue : protected mem_ui, public on_pool
63     {
64     public :
65         catalogue(const user_interaction & dialog,
66 		  const datetime & root_last_modif,
67 		  const label & data_name);
68         catalogue(const user_interaction & dialog,
69 		  const pile_descriptor & pdesc,
70 		  const archive_version & reading_ver,
71 		  compression default_algo,
72 		  bool lax,
73 		  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
74 		  bool only_detruit = false); //< if set to true, only directories and detruit objects are read from the archive
catalogue(const catalogue & ref)75         catalogue(const catalogue & ref) : mem_ui(ref), out_compare(ref.out_compare) { partial_copy_from(ref); };
76         const catalogue & operator = (const catalogue &ref);
~catalogue()77         virtual ~catalogue() { detruire(); };
78 
79 
80 	    // reading methods. The reading is iterative and uses the current_read cat_directory pointer
81 
82         virtual void reset_read() const; // set the reading cursor to the beginning of the catalogue
83 	virtual void end_read() const; // set the reading cursor to the end of the catalogue
84         virtual void skip_read_to_parent_dir() const;
85             // skip all items of the current dir and of any subdir, the next call will return
86             // next item of the parent dir (no cat_eod to exit from the current dir !)
87         virtual bool read(const cat_entree * & ref) const;
88             // sequential read (generates cat_eod) and return false when all files have been read
89         virtual bool read_if_present(std::string *name, const cat_nomme * & ref) const;
90             // pseudo-sequential read (reading a directory still
91             // implies that following read are located in this subdirectory up to the next EOD) but
92             // it returns false if no entry of this name are present in the current directory
93             // a call with nullptr as first argument means to set the current dir the parent directory
94 	void remove_read_entry(std::string & name);
95 	    // in the currently read directory, removes the entry which name is given in argument
get_current_reading_dir() const96 	const cat_directory & get_current_reading_dir() const { if(current_read == nullptr) throw SRC_BUG; return *current_read; };
97 	    // remove from the catalogue all the entries that have not yet been read
98 	    // by read().
99 	void tail_catalogue_to_current_read();
100 
101 
102         void reset_sub_read(const path &sub); // initialise sub_read to the given directory
103         bool sub_read(const cat_entree * &ref); // sequential read of the catalogue, ignoring all that
104             // is not part of the subdirectory specified with reset_sub_read
105             // the read include the inode leading to the sub_tree as well as the pending cat_eod
106 
107 	    // return true if the last read entry has already been read
108 	    // and has not to be counted again. This is never the case for catalogue but may occure
109 	    // with escape_catalogue (where from the 'virtual').
110 	    // last this method gives a valid result only if the last read() entry is a directory as
111 	    // only directory may be read() twice.
read_second_time_dir() const112 	virtual bool read_second_time_dir() const { return false; };
113 
114 
115 	    // Additions methods. The addition is also iterative but uses its specific current_add directory pointer
116 
117         void reset_add();
118 
119 	    /// catalogue extension routines for escape sequence
120 	    // real implementation is only needed in escape_catalogue class, here there nothing to be done
pre_add(const cat_entree * ref) const121 	virtual void pre_add(const cat_entree *ref) const {};
pre_add_ea(const cat_entree * ref) const122 	virtual void pre_add_ea(const cat_entree *ref) const {};
pre_add_crc(const cat_entree * ref) const123 	virtual void pre_add_crc(const cat_entree *ref) const {};
pre_add_dirty() const124 	virtual void pre_add_dirty() const {};
pre_add_ea_crc(const cat_entree * ref) const125 	virtual void pre_add_ea_crc(const cat_entree *ref) const {};
pre_add_waste_mark() const126 	virtual void pre_add_waste_mark() const {};
pre_add_failed_mark() const127 	virtual void pre_add_failed_mark() const {};
pre_add_fsa(const cat_entree * ref) const128 	virtual void pre_add_fsa(const cat_entree *ref) const {};
pre_add_fsa_crc(const cat_entree * ref) const129 	virtual void pre_add_fsa_crc(const cat_entree *ref) const {};
get_escape_layer() const130 	virtual escape *get_escape_layer() const { return nullptr; };
131 
132         void add(cat_entree *ref); // add at end of catalogue (sequential point of view)
133 	void re_add_in(const std::string &subdirname); // return into an already existing subdirectory for further addition
134 	void re_add_in_replace(const cat_directory &dir); // same as re_add_in but also set the properties of the existing directory to those of the given argument
135         void add_in_current_read(cat_nomme *ref); // add in currently read directory
get_current_add_dir() const136 	const cat_directory & get_current_add_dir() const { if(current_add == nullptr) throw SRC_BUG; return *current_add; };
137 
138 
139 
140 	    // Comparison methods. The comparision is here also iterative and uses its specific current_compare directory pointer
141 
142         void reset_compare() const;
143         bool compare(const cat_entree * name, const cat_entree * & extracted) const;
144             // returns true if the ref exists, and gives it back in second argument as it is in the current catalogue.
145             // returns false is no entry of that nature exists in the catalogue (in the current directory)
146             // if ref is a directory, the operation is normaly relative to the directory itself, but
147             // such a call implies a chdir to that directory. thus, a call with an EOD is necessary to
148             // change to the parent directory.
149             // note :
150             // if a directory is not present, returns false, but records the inexistant subdirectory
151             // structure defined by the following calls to this routine, this to be able to know when
152             // the last available directory is back the current one when changing to parent directory,
153             // and then proceed with normal comparison of inode. In this laps of time, the call will
154             // always return false, while it temporary stores the missing directory structure
155 
156 
157 
158 	    // non interative methods
159 
160 
161 	    /// add into "this" detruit object corresponding to object of ref absent in "this"
162 	    ///
163 	    ///\note ref must have the same directory tree "this", else the operation generates an exception
164         infinint update_destroyed_with(const catalogue & ref);
165 
166 
167 	    /// copy from ref missing files in "this" and mark then as "not_saved" (no change since reference)
168 	    ///
169 	    /// in case of abortion, completes missing files as if what could not be
170 	    /// inspected had not changed since the reference was done
171 	    /// aborting_last_etoile is the highest etoile reference withing "this" current object.
172 	void update_absent_with(const catalogue & ref, infinint aborting_next_etoile);
173 
174 
175 	    /// remove/destroy from "this" all objects that are neither directory nor detruit objects
176 	void drop_all_non_detruits();
177 
178 	    /// check whether all inode existing in the "this" and ref have the same attributes
179 	    ///
180 	    /// \note stops at the first inode found in both catalogue that do not match for at least one attribute
181 	    /// including CRC for DATA, EA or FSA if present, then return false.
182 	bool is_subset_of(const catalogue & ref) const;
183 
184 	    /// before dumping the catalogue, need to set all hardlinked inode they have not been saved once
185 	void reset_dump() const;
186 
187 	    /// write down the whole catalogue to file
188         void dump(const pile_descriptor & pdesc) const;
189 
190         void listing(bool isolated,
191 		     const mask &selection,
192 		     const mask & subtree,
193 		     bool filter_unsaved,
194 		     bool list_ea,
195 		     bool sizes_in_bytes,
196 		     std::string marge) const;
197         void tar_listing(bool isolated,
198 			 const mask & selection,
199 			 const mask & subtree,
200 			 bool filter_unsaved,
201 			 bool list_ea,
202 			 bool sizes_in_bytes,
203 			 std::string beginning) const;
204         void xml_listing(bool isolated,
205 			 const mask & selection,
206 			 const mask & subtree,
207 			 bool filter_unsaved,
208 			 bool list_ea,
209 			 bool sizes_in_bytes,
210 			 std::string beginning) const;
211 	void slice_listing(bool isolated,
212 			   const mask & selection,
213 			   const mask & subtree,
214 			   const slice_layout & slicing) const;
215 
get_stats() const216         entree_stats get_stats() const { return stats; };
217 
218 	    /// whether the catalogue is empty or not
is_empty() const219 	bool is_empty() const { if(contenu == nullptr) throw SRC_BUG; return contenu->is_empty(); };
220 
get_contenu() const221         const cat_directory *get_contenu() const { return contenu; }; // used by data_tree
222 
get_data_name() const223 	const label & get_data_name() const { return ref_data_name; };
get_root_dir_last_modif() const224 	datetime get_root_dir_last_modif() const { return contenu->get_last_modif(); };
225 
226 	    /// recursive evaluation of directories that have changed (make the cat_directory::get_recurisve_has_changed() method of entry in this catalogue meaningful)
launch_recursive_has_changed_update() const227 	void launch_recursive_has_changed_update() const { contenu->recursive_has_changed_update(); };
228 
229 	    /// recursive setting of mirage inode_wrote flag
set_all_mirage_s_inode_wrote_field_to(bool val) const230 	void set_all_mirage_s_inode_wrote_field_to(bool val) const { const_cast<cat_directory *>(contenu)->set_all_mirage_s_inode_wrote_field_to(val); };
231 
get_root_mtime() const232 	datetime get_root_mtime() const { return contenu->get_last_modif(); };
233 
234 	    /// reset all pointers to the root (a bit better than reset_add() + reset_read() + reset_compare() + reset_sub_read())
235 	void reset_all();
236 
set_to_unsaved_data_and_FSA()237 	void set_to_unsaved_data_and_FSA() { if(contenu == nullptr) throw SRC_BUG; contenu->recursively_set_to_unsaved_data_and_FSA(); };
238 
239 	    /// change location where to find EA, FSA and DATA for all the objects of the catalogue
240 	void change_location(const pile_descriptor & pdesc);
241 
242     protected:
access_stats()243 	entree_stats & access_stats() { return stats; };
set_data_name(const label & val)244 	void set_data_name(const label & val) { ref_data_name = val; };
245 	void copy_detruits_from(const catalogue & ref); // needed for escape_catalogue implementation only.
246 
get_r_eod_address() const247 	const cat_eod * get_r_eod_address() const { return & r_eod; }; // cat_eod are never stored in the catalogue
248 	    // however it is sometimes required to return such a reference to a valid object
249 	    // owned by the catalogue.
250 
251 
252 	    /// invert the data tree memory management responsibility pointed to by "contenu" pointers between the current
253 	    /// catalogue and the catalogue given in argument.
254 	void swap_stuff(catalogue & ref);
255 
256     private :
257         cat_directory *contenu;           ///< catalogue contents
258         path out_compare;                 ///< stores the missing directory structure, when extracting
259         cat_directory *current_compare;   ///< points to the current directory when extracting
260         cat_directory *current_add;       ///< points to the directory where to add the next file with add_file;
261         cat_directory *current_read;      ///< points to the directory where the next item will be read
262         path *sub_tree;                   ///< path to sub_tree
263         signed int sub_count;             ///< count the depth in of read routine in the sub_tree
264         entree_stats stats;               ///< statistics catalogue contents
265 	label ref_data_name;              ///< name of the archive where is located the data
266 
267         void partial_copy_from(const catalogue &ref);
268         void detruire();
269 
270         static const cat_eod r_eod;           // needed to return eod reference, without taking risk of saturating memory
271 	static const U_I CAT_CRC_SIZE;
272     };
273 
274 
275 
276 	/// @}
277 
278 } // end of namespace
279 
280 #endif
281