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