Disk ARchive 2.4.2
|
00001 /*********************************************************************/ 00002 // dar - disk archive - a backup/restoration program 00003 // Copyright (C) 2002-2052 Denis Corbin 00004 // 00005 // This program is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU General Public License 00007 // as published by the Free Software Foundation; either version 2 00008 // of the License, or (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; if not, write to the Free Software 00017 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00018 // 00019 // to contact the author : http://dar.linux.free.fr/email.html 00020 /*********************************************************************/ 00021 // $Id: catalogue.hpp,v 1.111 2011/05/27 12:29:18 edrusb Rel $ 00022 // 00023 /*********************************************************************/ 00024 00028 00029 #ifndef CATALOGUE_HPP 00030 #define CATALOGUE_HPP 00031 00032 #include "../my_config.h" 00033 00034 extern "C" 00035 { 00036 #if HAVE_UNISTD_H 00037 #include <unistd.h> 00038 #endif 00039 } // end extern "C" 00040 00041 #include <vector> 00042 #include <map> 00043 #include "infinint.hpp" 00044 #include "generic_file.hpp" 00045 #include "path.hpp" 00046 #include "header_version.hpp" 00047 #include "ea.hpp" 00048 #include "compressor.hpp" 00049 #include "integers.hpp" 00050 #include "mask.hpp" 00051 #include "special_alloc.hpp" 00052 #include "user_interaction.hpp" 00053 #include "label.hpp" 00054 #include "escape.hpp" 00055 00056 namespace libdar 00057 { 00058 class etoile; 00059 class entree; 00060 00063 00064 enum saved_status 00065 { 00066 s_saved, //< inode is saved in the archive 00067 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. 00068 s_not_saved //< inode is not saved in the archive 00069 }; 00070 00072 struct entree_stats 00073 { 00074 infinint num_x; //< number of file referenced as destroyed since last backup 00075 infinint num_d; //< number of directories 00076 infinint num_f; //< number of plain files (hard link or not, thus file directory entries) 00077 infinint num_c; //< number of char devices 00078 infinint num_b; //< number of block devices 00079 infinint num_p; //< number of named pipes 00080 infinint num_s; //< number of unix sockets 00081 infinint num_l; //< number of symbolic links 00082 infinint num_D; //< number of Door 00083 infinint num_hard_linked_inodes; //< number of inode that have more than one link (inode with "hard links") 00084 infinint num_hard_link_entries; //< total number of hard links (file directory entry pointing to \an 00085 //< inode already linked in the same or another directory (i.e. hard linked)) 00086 infinint saved; //< total number of saved inode (unix inode, not inode class) hard links do not count here 00087 infinint total; //< total number of inode in archive (unix inode, not inode class) hard links do not count here 00088 void clear() { num_x = num_d = num_f = num_c = num_b = num_p 00089 = num_s = num_l = num_D = num_hard_linked_inodes 00090 = num_hard_link_entries = saved = total = 0; }; 00091 void add(const entree *ref); 00092 void listing(user_interaction & dialog) const; 00093 }; 00094 00096 class entree 00097 { 00098 public : 00099 static entree *read(user_interaction & dialog, 00100 generic_file & f, const archive_version & reading_ver, 00101 entree_stats & stats, 00102 std::map <infinint, etoile *> & corres, 00103 compression default_algo, 00104 generic_file *data_loc, 00105 generic_file *ea_loc, 00106 bool lax, 00107 bool only_detruit, 00108 escape *ptr); 00109 00110 virtual ~entree() {}; 00111 00113 00120 void dump(generic_file & f, bool small) const; 00121 00123 00130 void specific_dump(generic_file & f, bool small) const { inherited_dump(f, small); }; 00131 00133 00136 virtual void post_constructor(generic_file & f) {}; 00137 00138 00139 virtual unsigned char signature() const = 0; 00140 virtual entree *clone() const = 0; 00141 00142 // SPECIAL ALLOC not adapted here 00143 // because some inherited class object (eod) are 00144 // temporary 00145 00146 protected: 00147 virtual void inherited_dump(generic_file & f, bool small) const; 00148 00149 00150 private: 00151 static const U_I ENTREE_CRC_SIZE; 00152 00153 }; 00154 00155 extern bool compatible_signature(unsigned char a, unsigned char b); 00156 extern unsigned char mk_signature(unsigned char base, saved_status state); 00157 00159 class eod : public entree 00160 { 00161 public : 00162 eod() {}; 00163 eod(generic_file & f) {}; 00164 // dump defined by entree 00165 unsigned char signature() const { return 'z'; }; 00166 entree *clone() const { return new eod(); }; 00167 00168 // eod are generally temporary object they are NOT 00169 // well adapted to "SPECIAL ALLOC" 00170 }; 00171 00173 class nomme : public entree 00174 { 00175 public: 00176 nomme(const std::string & name) { xname = name; }; 00177 nomme(generic_file & f); 00178 virtual bool operator == (const nomme & ref) const { return xname == ref.xname; }; 00179 virtual bool operator < (const nomme & ref) const { return xname < ref.xname; }; 00180 00181 const std::string & get_name() const { return xname; }; 00182 void change_name(const std::string & x) { xname = x; }; 00183 bool same_as(const nomme & ref) const { return xname == ref.xname; }; 00184 // no need to have a virtual method, as signature will differ in inherited classes (argument type changes) 00185 00186 // signature() is kept as an abstract method 00187 // clone() is abstract 00188 00189 #ifdef LIBDAR_SPECIAL_ALLOC 00190 USE_SPECIAL_ALLOC(nomme); 00191 #endif 00192 00193 protected: 00194 void inherited_dump(generic_file & f, bool small) const; 00195 00196 private: 00197 std::string xname; 00198 }; 00199 00200 00202 class inode : public nomme 00203 { 00204 public: 00205 00207 00208 enum comparison_fields 00209 { 00210 cf_all, //< consider any available field for comparing inodes 00211 cf_ignore_owner, //< consider any available field except ownership fields 00212 cf_mtime, //< consider any available field except ownership and permission fields 00213 cf_inode_type //< only consider the file type 00214 }; 00215 00216 inode(const infinint & xuid, const infinint & xgid, U_16 xperm, 00217 const infinint & last_access, 00218 const infinint & last_modif, 00219 const infinint & last_change, 00220 const std::string & xname, const infinint & device); 00221 inode(user_interaction & dialog, 00222 generic_file & f, 00223 const archive_version & reading_ver, 00224 saved_status saved, 00225 generic_file *ea_loc, 00226 escape *ptr); // if ptr is not NULL, reading a partial dump(), which was done with "small" set to true 00227 inode(const inode & ref); 00228 const inode & operator = (const inode & ref); 00229 ~inode(); 00230 00231 const infinint & get_uid() const { return uid; }; 00232 const infinint & get_gid() const { return gid; }; 00233 U_16 get_perm() const { return perm; }; 00234 infinint get_last_access() const { return *last_acc; }; 00235 infinint get_last_modif() const { return *last_mod; }; 00236 void set_last_access(const infinint & x_time) { *last_acc = x_time; }; 00237 void set_last_modif(const infinint & x_time) { *last_mod = x_time; }; 00238 saved_status get_saved_status() const { return xsaved; }; 00239 void set_saved_status(saved_status x) { xsaved = x; }; 00240 infinint get_device() const { return *fs_dev; }; 00241 00242 bool same_as(const inode & ref) const; 00243 bool is_more_recent_than(const inode & ref, const infinint & hourshift) const; 00244 // used for RESTORATION 00245 virtual bool has_changed_since(const inode & ref, const infinint & hourshift, comparison_fields what_to_check) const; 00246 // signature() left as an abstract method 00247 // clone is abstract too 00248 // used for INCREMENTAL BACKUP 00249 void compare(const inode &other, 00250 const mask & ea_mask, 00251 comparison_fields what_to_check, 00252 const infinint & hourshift, 00253 bool symlink_date) const; 00254 00255 // throw Erange exception if a difference has been detected 00256 // this is not a symetrical comparison, but all what is present 00257 // in the current object is compared against the argument 00258 // which may contain supplementary informations 00259 // used for DIFFERENCE 00260 00261 00262 00264 // EXTENDED ATTRIBUTS Methods 00265 // 00266 00267 enum ea_status { ea_none, ea_partial, ea_fake, ea_full, ea_removed }; 00268 // ea_none : no EA present for this inode in filesystem 00269 // ea_partial : EA present in filesystem but not stored (ctime used to check changes) 00270 // 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. 00271 // ea_full : EA present in filesystem and attached to this inode 00272 // ea_removed : EA were present in the reference version, but not present anymore 00273 00274 // I : to know whether EA data is present or not for this object 00275 void ea_set_saved_status(ea_status status); 00276 ea_status ea_get_saved_status() const { return ea_saved; }; 00277 00278 // II : to associate EA list to an inode object (mainly for backup operation) #EA_FULL only# 00279 void ea_attach(ea_attributs *ref); 00280 const ea_attributs *get_ea() const; // #<-- EA_FULL *and* EA_REMOVED# for this call only 00281 void ea_detach() const; //discards any future call to get_ea() ! 00282 infinint ea_get_size() const; //returns the size of EA (still valid if ea have been detached) 00283 00284 // III : to record where is dump the EA in the archive #EA_FULL only# 00285 void ea_set_offset(const infinint & pos) { *ea_offset = pos; }; 00286 void ea_set_crc(const crc & val) { crc::set_crc_pointer(ea_crc, &val); }; 00287 void ea_get_crc(crc & val) const; 00288 bool ea_get_crc_size(infinint & val) const; //< returns true if crc is know and puts its width in argument 00289 00290 // IV : to know/record if EA have been modified # any EA status# 00291 infinint get_last_change() const; 00292 void set_last_change(const infinint & x_time); 00293 bool has_last_change() const { return last_cha != NULL; }; 00294 // old format did provide last_change only when EA were present, since archive 00295 // format 8, this field is always present even in absence of EA. Thus it is 00296 // still necessary to check if the inode has a last_change() before 00297 // using get_last_change() (depends on the version of the archive read). 00298 00299 00300 // V : for archive migration (merging) 00301 void change_ea_location(generic_file *loc) { storage = loc; }; 00302 00304 00305 #ifdef LIBDAR_SPECIAL_ALLOC 00306 USE_SPECIAL_ALLOC(inode); 00307 #endif 00308 00309 protected: 00310 virtual void sub_compare(const inode & other) const {}; 00311 00313 escape *get_escape_layer() const { return esc; }; 00314 00315 void inherited_dump(generic_file & f, bool small) const; 00316 00317 private : 00318 infinint uid; 00319 infinint gid; 00320 U_16 perm; 00321 infinint *last_acc, *last_mod; 00322 saved_status xsaved; 00323 ea_status ea_saved; 00324 // the following is used only if ea_saved == full 00325 infinint *ea_offset; 00326 ea_attributs *ea; 00327 infinint ea_size; 00328 // the following is used if ea_saved == full or ea_saved == partial 00329 infinint *last_cha; 00330 crc *ea_crc; 00331 infinint *fs_dev; 00332 generic_file *storage; // where are stored EA 00333 archive_version edit; // need to know EA format used in archive file 00334 00335 escape *esc; // if not NULL, the object is partially build from archive (at archive generation, dump() was called with small set to true) 00336 00337 static const ea_attributs empty_ea; 00338 }; 00339 00341 class etoile 00342 { 00343 public: 00344 00346 00350 etoile(inode *host, const infinint & etiquette_number); 00351 etoile(const etoile & ref) { throw SRC_BUG; }; // copy constructor not allowed for this class 00352 const etoile & operator = (const etoile & ref) { throw SRC_BUG; }; // assignment not allowed for this class 00353 ~etoile() { delete hosted; }; 00354 00355 void add_ref(void *ref); 00356 void drop_ref(void *ref); 00357 infinint get_ref_count() const { return refs.size(); }; 00358 inode *get_inode() const { return hosted; }; 00359 infinint get_etiquette() const { return etiquette; }; 00360 void change_etiquette(const infinint & new_val) { etiquette = new_val; }; 00361 00362 00363 bool is_counted() const { return tags.counted; }; 00364 bool is_wrote() const { return tags.wrote; }; 00365 bool is_dumped() const { return tags.dumped; }; 00366 void set_counted(bool val) { tags.counted = val ? 1 : 0; }; 00367 void set_wrote(bool val) { tags.wrote = val ? 1 : 0; }; 00368 void set_dumped(bool val) { tags.dumped = val ? 1 : 0; }; 00369 00370 // return the address of the first mirage that triggered the creation of this mirage 00371 // if this object is destroyed afterward this call returns NULL 00372 const void *get_first_ref() const { if(refs.size() == 0) throw SRC_BUG; return refs.front(); }; 00373 00374 #ifdef LIBDAR_SPECIAL_ALLOC 00375 USE_SPECIAL_ALLOC(etoile); 00376 #endif 00377 00378 private: 00379 struct bool_tags 00380 { 00381 unsigned counted : 1; //< whether the inode has been counted 00382 unsigned wrote : 1; //< whether the inode has its data copied to archive 00383 unsigned dumped : 1; //< whether the inode information has been dumped in the catalogue 00384 unsigned : 5; //< padding to get byte boundary and reserved for future use. 00385 00386 bool_tags() { counted = wrote = dumped = 0; }; 00387 }; 00388 00389 std::list<void *> refs; //< list of pointers to the mirages objects, in the order of their creation 00390 inode *hosted; 00391 infinint etiquette; 00392 bool_tags tags; 00393 }; 00394 00396 00398 class mirage : public nomme 00399 { 00400 public: 00401 enum mirage_format {fmt_mirage, //< new format 00402 fmt_hard_link, //< old dual format 00403 fmt_file_etiquette }; //< old dual format 00404 00405 mirage(const std::string & name, etoile *ref) : nomme(name) { star_ref = ref; if(ref == NULL) throw SRC_BUG; star_ref->add_ref(this); }; 00406 mirage(user_interaction & dialog, 00407 generic_file & f, 00408 const archive_version & reading_ver, 00409 saved_status saved, 00410 entree_stats & stats, 00411 std::map <infinint, etoile *> & corres, 00412 compression default_algo, 00413 generic_file *data_loc, 00414 generic_file *ea_loc, 00415 mirage_format fmt, 00416 bool lax, 00417 escape *ptr); 00418 mirage(user_interaction & dialog, 00419 generic_file & f, 00420 const archive_version & reading_ver, 00421 saved_status saved, 00422 entree_stats & stats, 00423 std::map <infinint, etoile *> & corres, 00424 compression default_algo, 00425 generic_file *data_loc, 00426 generic_file *ea_loc, 00427 bool lax, 00428 escape *ptr); 00429 mirage(const mirage & ref) : nomme (ref) { star_ref = ref.star_ref; if(star_ref == NULL) throw SRC_BUG; star_ref->add_ref(this); }; 00430 const mirage & operator = (const mirage & ref); 00431 ~mirage() { star_ref->drop_ref(this); }; 00432 00433 unsigned char signature() const { return 'm'; }; 00434 entree *clone() const { return new mirage(*this); }; 00435 00436 inode *get_inode() const { if(star_ref == NULL) throw SRC_BUG; return star_ref->get_inode(); }; 00437 infinint get_etiquette() const { return star_ref->get_etiquette(); }; 00438 infinint get_etoile_ref_count() const { return star_ref->get_ref_count(); }; 00439 etoile *get_etoile() const { return star_ref; }; 00440 00441 bool is_inode_counted() const { return star_ref->is_counted(); }; 00442 bool is_inode_wrote() const { return star_ref->is_wrote(); }; 00443 bool is_inode_dumped() const { return star_ref->is_dumped(); }; 00444 void set_inode_counted(bool val) const { star_ref->set_counted(val); }; 00445 void set_inode_wrote(bool val) const { star_ref->set_wrote(val); }; 00446 void set_inode_dumped(bool val) const { star_ref->set_dumped(val); }; 00447 00448 void post_constructor(generic_file & f); 00449 00451 bool is_first_mirage() const { return star_ref->get_first_ref() == this; }; 00452 00453 #ifdef LIBDAR_SPECIAL_ALLOC 00454 USE_SPECIAL_ALLOC(mirage); 00455 #endif 00456 00457 protected: 00458 void inherited_dump(generic_file & f, bool small) const; 00459 00460 private: 00461 etoile *star_ref; 00462 00463 void init(user_interaction & dialog, 00464 generic_file & f, 00465 const archive_version & reading_ver, 00466 saved_status saved, 00467 entree_stats & stats, 00468 std::map <infinint, etoile *> & corres, 00469 compression default_algo, 00470 generic_file *data_loc, 00471 generic_file *ea_loc, 00472 mirage_format fmt, 00473 bool lax, 00474 escape *ptr); 00475 }; 00476 00477 00479 class file : public inode 00480 { 00481 public : 00482 enum get_data_mode 00483 { 00484 keep_compressed, //< provide access to compressed data 00485 keep_hole, //< provide access to uncompressed data but sparse_file datastructure 00486 normal, //< provide access to full data (uncompressed, uses skip() to restore holes) 00487 plain //< provide access to plain data, no skip to restore holes, provide instead zeroed bytes 00488 }; 00489 00490 static const U_8 FILE_DATA_WITH_HOLE = 0x01; //< file's data contains hole datastructure 00491 static const U_8 FILE_DATA_IS_DIRTY = 0x02; //< data modified while being saved 00492 00493 file(const infinint & xuid, const infinint & xgid, U_16 xperm, 00494 const infinint & last_access, 00495 const infinint & last_modif, 00496 const infinint & last_change, 00497 const std::string & src, 00498 const path & che, 00499 const infinint & taille, 00500 const infinint & fs_device, 00501 bool x_furtive_read_mode); 00502 file(const file & ref); 00503 file(user_interaction & dialog, 00504 generic_file & f, 00505 const archive_version & reading_ver, 00506 saved_status saved, 00507 compression default_algo, 00508 generic_file *data_loc, 00509 generic_file *ea_loc, 00510 escape *ptr); 00511 ~file() { detruit(); }; 00512 00513 bool has_changed_since(const inode & ref, const infinint & hourshift, inode::comparison_fields what_to_check) const; 00514 infinint get_size() const { return *size; }; 00515 infinint get_storage_size() const { return *storage_size; }; 00516 void set_storage_size(const infinint & s) { *storage_size = s; }; 00517 virtual generic_file *get_data(get_data_mode mode) const; // returns a newly allocated object in read_only mode 00518 void clean_data(); // partially free memory (but get_data() becomes disabled) 00519 void set_offset(const infinint & r); 00520 const infinint & get_offset() const; 00521 unsigned char signature() const { return mk_signature('f', get_saved_status()); }; 00522 00523 void set_crc(const crc &c) { crc::set_crc_pointer(check, &c); }; 00524 bool get_crc(crc & c) const; 00525 bool has_crc() const { return check != NULL; }; 00526 bool get_crc_size(infinint & val) const; //< returns true if crc is know and puts its width in argument 00527 void drop_crc() { if(check != NULL) { delete check; check = NULL; } }; 00528 00529 // whether the plain file has to detect sparse file 00530 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; }; 00531 00532 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; }; 00533 00534 // whether the plain file is stored with a sparse_file datastructure in the archive 00535 bool get_sparse_file_detection_read() const { return (file_data_status_read & FILE_DATA_WITH_HOLE) != 0; }; 00536 bool get_sparse_file_detection_write() const { return (file_data_status_write & FILE_DATA_WITH_HOLE) != 0; }; 00537 00538 entree *clone() const { return new file(*this); }; 00539 00540 compression get_compression_algo_read() const { return algo_read; }; 00541 00542 compression get_compression_algo_write() const { return algo_write; }; 00543 00544 // object migration methods (merging) 00545 void change_compression_algo_write(compression x) { algo_write = x; }; 00546 void change_location(generic_file *x) { loc = x; }; 00547 00548 // dirtiness 00549 00550 bool is_dirty() const { return dirty; }; 00551 void set_dirty(bool value) { dirty = value; }; 00552 00553 #ifdef LIBDAR_SPECIAL_ALLOC 00554 USE_SPECIAL_ALLOC(file); 00555 #endif 00556 00557 protected: 00558 void sub_compare(const inode & other) const; 00559 void inherited_dump(generic_file & f, bool small) const; 00560 void post_constructor(generic_file & f); 00561 00562 enum { empty, from_path, from_cat } status; 00563 00564 private: 00565 std::string chemin; //< path to the data (when read from filesystem) 00566 infinint *offset; //< start location of the data in 'loc' 00567 infinint *size; //< size of the data (uncompressed) 00568 infinint *storage_size; //< how much data used in archive (after compression) 00569 crc *check; 00570 bool dirty; //< true when a file has been modified at the time it was saved 00571 00572 generic_file *loc; //< where to find data (eventually compressed) at the recorded offset and for storage_size length 00573 compression algo_read; //< which compression algorithm to use to read the file's data 00574 compression algo_write; //< which compression algorithm to use to write down (merging) the file's data 00575 bool furtive_read_mode; // used only when status equals "from_path" 00576 char file_data_status_read; // defines the datastructure to use when reading the data 00577 char file_data_status_write; // defines the datastructure to apply when writing down the data 00578 00579 void detruit(); 00580 }; 00581 00583 class door : public file 00584 { 00585 public: 00586 door(const infinint & xuid, const infinint & xgid, U_16 xperm, 00587 const infinint & last_access, 00588 const infinint & last_modif, 00589 const infinint & last_change, 00590 const std::string & src, 00591 const path & che, 00592 const infinint & fs_device) : file(xuid, xgid, xperm, last_access, last_modif, 00593 last_change, src, che, 0, fs_device, false) {}; 00594 door(user_interaction & dialog, 00595 generic_file & f, 00596 const archive_version & reading_ver, 00597 saved_status saved, 00598 compression default_algo, 00599 generic_file *data_loc, 00600 generic_file *ea_loc, 00601 escape *ptr) : file(dialog, f, reading_ver, saved, default_algo, data_loc, ea_loc, ptr) {}; 00602 00603 unsigned char signature() const { return mk_signature('o', get_saved_status()); }; 00604 00605 generic_file *get_data(get_data_mode mode) const; // inherited from class file 00606 }; 00607 00609 class lien : public inode 00610 { 00611 public : 00612 lien(const infinint & uid, const infinint & gid, U_16 perm, 00613 const infinint & last_access, 00614 const infinint & last_modif, 00615 const infinint & last_change, 00616 const std::string & name, 00617 const std::string & target, 00618 const infinint & fs_device); 00619 lien(user_interaction & dialog, 00620 generic_file & f, 00621 const archive_version & reading_ver, 00622 saved_status saved, 00623 generic_file *ea_loc, 00624 escape *ptr); 00625 00626 const std::string & get_target() const; 00627 void set_target(std::string x); 00628 00629 // using the method is_more_recent_than() from inode 00630 // using method has_changed_since() from inode class 00631 unsigned char signature() const { return mk_signature('l', get_saved_status()); }; 00632 entree *clone() const { return new lien(*this); }; 00633 00634 #ifdef LIBDAR_SPECIAL_ALLOC 00635 USE_SPECIAL_ALLOC(lien); 00636 #endif 00637 protected : 00638 void sub_compare(const inode & other) const; 00639 void inherited_dump(generic_file & f, bool small) const; 00640 00641 00642 private : 00643 std::string points_to; 00644 }; 00645 00647 class directory : public inode 00648 { 00649 public : 00650 directory(const infinint & xuid, const infinint & xgid, U_16 xperm, 00651 const infinint & last_access, 00652 const infinint & last_modif, 00653 const infinint & last_change, 00654 const std::string & xname, 00655 const infinint & device); 00656 directory(const directory &ref); // only the inode part is build, no children is duplicated (empty dir) 00657 const directory & operator = (const directory & ref); // set the inode part *only* no subdirectories/subfiles are copies or removed. 00658 directory(user_interaction & dialog, 00659 generic_file & f, 00660 const archive_version & reading_ver, 00661 saved_status saved, 00662 entree_stats & stats, 00663 std::map <infinint, etoile *> & corres, 00664 compression default_algo, 00665 generic_file *data_loc, 00666 generic_file *ea_loc, 00667 bool lax, 00668 bool only_detruit, // objects of other class than detruit and directory are not built in memory 00669 escape *ptr); 00670 ~directory(); // detruit aussi tous les fils et se supprime de son 'parent' 00671 00672 void add_children(nomme *r); // when r is a directory, 'parent' is set to 'this' 00673 bool has_children() const { return !fils.empty(); }; 00674 void reset_read_children() const; 00675 void end_read() const; 00676 bool read_children(const nomme * &r) const; // read the direct children of the directory, returns false if no more is available 00677 // remove all entry not yet read by read_children 00678 void tail_to_read_children(); 00679 00680 void remove(const std::string & name); // remove the given entry from the catalogue 00681 // as side effect the reset_read_children() method must be called. 00682 00683 directory * get_parent() const { return parent; }; 00684 bool search_children(const std::string &name, nomme *&ref); 00685 bool callback_for_children_of(user_interaction & dialog, const std::string & sdir, bool isolated = false) const; 00686 00687 // using is_more_recent_than() from inode class 00688 // using method has_changed_since() from inode class 00689 unsigned char signature() const { return mk_signature('d', get_saved_status()); }; 00690 00691 // some data has changed since archive of reference in this directory or subdirectories 00692 bool get_recursive_has_changed() const { return recursive_has_changed; }; 00693 // update the recursive_has_changed field 00694 void recursive_has_changed_update() const; 00695 00696 // get then number of "nomme" entry contained in this directory and subdirectories (recursive call) 00697 infinint get_tree_size() const; 00698 // get the number of entry having some EA set in the directory tree (recursive call) 00699 infinint get_tree_ea_num() const; 00700 // get the number of entry that are hard linked inode (aka mirage in dar implementation) (recursive call) 00701 infinint get_tree_mirage_num() const; 00702 // for each mirage found (hard link implementation) in the directory tree, add its etiquette to the returned 00703 // list with the number of reference that has been found in the tree. (map[etiquette] = number of occurence) 00704 // from outside of class directory, the given argument is expected to be an empty map. 00705 void get_etiquettes_found_in_tree(std::map<infinint, infinint> & already_found) const; 00706 00707 // whether this directory is empty or not 00708 bool is_empty() const { return fils.empty(); }; 00709 00710 // recursively remove all mirage entries 00711 void remove_all_mirages_and_reduce_dirs(); 00712 00713 entree *clone() const { return new directory(*this); }; 00714 00715 #ifdef LIBDAR_SPECIAL_ALLOC 00716 USE_SPECIAL_ALLOC(directory); 00717 #endif 00718 00719 protected: 00720 void inherited_dump(generic_file & f, bool small) const; 00721 00722 private : 00723 static const eod fin; 00724 00725 directory *parent; 00726 std::map<std::string, nomme *> fils; // used for fast lookup 00727 std::list<nomme *> ordered_fils; 00728 std::list<nomme *>::iterator it; 00729 bool recursive_has_changed; 00730 00731 void clear(); 00732 }; 00733 00735 class device : public inode 00736 { 00737 public : 00738 device(const infinint & uid, const infinint & gid, U_16 perm, 00739 const infinint & last_access, 00740 const infinint & last_modif, 00741 const infinint &last_change, 00742 const std::string & name, 00743 U_16 major, 00744 U_16 minor, 00745 const infinint & fs_device); 00746 device(user_interaction & dialog, 00747 generic_file & f, 00748 const archive_version & reading_ver, 00749 saved_status saved, 00750 generic_file *ea_loc, 00751 escape *ptr); 00752 00753 int get_major() const { if(get_saved_status() != s_saved) throw SRC_BUG; else return xmajor; }; 00754 int get_minor() const { if(get_saved_status() != s_saved) throw SRC_BUG; else return xminor; }; 00755 void set_major(int x) { xmajor = x; }; 00756 void set_minor(int x) { xminor = x; }; 00757 00758 // using method is_more_recent_than() from inode class 00759 // using method has_changed_since() from inode class 00760 // signature is left pure abstract 00761 00762 #ifdef LIBDAR_SPECIAL_ALLOC 00763 USE_SPECIAL_ALLOC(device); 00764 #endif 00765 00766 protected : 00767 void sub_compare(const inode & other) const; 00768 void inherited_dump(generic_file & f, bool small) const; 00769 00770 private : 00771 U_16 xmajor, xminor; 00772 }; 00773 00775 class chardev : public device 00776 { 00777 public: 00778 chardev(const infinint & uid, const infinint & gid, U_16 perm, 00779 const infinint & last_access, 00780 const infinint & last_modif, 00781 const infinint & last_change, 00782 const std::string & name, 00783 U_16 major, 00784 U_16 minor, 00785 const infinint & fs_device) : device(uid, gid, perm, 00786 last_access, 00787 last_modif, 00788 last_change, 00789 name, 00790 major, minor, fs_device) {}; 00791 chardev(user_interaction & dialog, 00792 generic_file & f, 00793 const archive_version & reading_ver, 00794 saved_status saved, 00795 generic_file *ea_loc, 00796 escape *ptr) : device(dialog, f, reading_ver, saved, ea_loc, ptr) {}; 00797 00798 // using dump from device class 00799 // using method is_more_recent_than() from device class 00800 // using method has_changed_since() from device class 00801 unsigned char signature() const { return mk_signature('c', get_saved_status()); }; 00802 entree *clone() const { return new chardev(*this); }; 00803 00804 #ifdef LIBDAR_SPECIAL_ALLOC 00805 USE_SPECIAL_ALLOC(chardev); 00806 #endif 00807 }; 00808 00810 class blockdev : public device 00811 { 00812 public: 00813 blockdev(const infinint & uid, const infinint & gid, U_16 perm, 00814 const infinint & last_access, 00815 const infinint & last_modif, 00816 const infinint & last_change, 00817 const std::string & name, 00818 U_16 major, 00819 U_16 minor, 00820 const infinint & fs_device) : device(uid, gid, perm, last_access, 00821 last_modif, last_change, name, 00822 major, minor, fs_device) {}; 00823 blockdev(user_interaction & dialog, 00824 generic_file & f, 00825 const archive_version & reading_ver, 00826 saved_status saved, 00827 generic_file *ea_loc, 00828 escape *ptr) : device(dialog, f, reading_ver, saved, ea_loc, ptr) {}; 00829 00830 // using dump from device class 00831 // using method is_more_recent_than() from device class 00832 // using method has_changed_since() from device class 00833 unsigned char signature() const { return mk_signature('b', get_saved_status()); }; 00834 entree *clone() const { return new blockdev(*this); }; 00835 00836 #ifdef LIBDAR_SPECIAL_ALLOC 00837 USE_SPECIAL_ALLOC(blockdev); 00838 #endif 00839 }; 00840 00842 class tube : public inode 00843 { 00844 public : 00845 tube(const infinint & xuid, const infinint & xgid, U_16 xperm, 00846 const infinint & last_access, 00847 const infinint & last_modif, 00848 const infinint & last_change, 00849 const std::string & xname, 00850 const infinint & fs_device) : inode(xuid, xgid, xperm, last_access, last_modif, last_change, xname, fs_device) { set_saved_status(s_saved); }; 00851 tube(user_interaction & dialog, 00852 generic_file & f, 00853 const archive_version & reading_ver, 00854 saved_status saved, 00855 generic_file *ea_loc, 00856 escape *ptr) : inode(dialog, f, reading_ver, saved, ea_loc, ptr) {}; 00857 00858 // using dump from inode class 00859 // using method is_more_recent_than() from inode class 00860 // using method has_changed_since() from inode class 00861 unsigned char signature() const { return mk_signature('p', get_saved_status()); }; 00862 entree *clone() const { return new tube(*this); }; 00863 00864 #ifdef LIBDAR_SPECIAL_ALLOC 00865 USE_SPECIAL_ALLOC(tube); 00866 #endif 00867 }; 00868 00870 class prise : public inode 00871 { 00872 public : 00873 prise(const infinint & xuid, const infinint & xgid, U_16 xperm, 00874 const infinint & last_access, 00875 const infinint & last_modif, 00876 const infinint & last_change, 00877 const std::string & xname, 00878 const infinint & fs_device) : inode(xuid, xgid, xperm, last_access, last_modif, last_change, xname, fs_device) { set_saved_status(s_saved); }; 00879 prise(user_interaction & dialog, 00880 generic_file & f, 00881 const archive_version & reading_ver, 00882 saved_status saved, 00883 generic_file *ea_loc, 00884 escape *ptr) : inode(dialog, f, reading_ver, saved, ea_loc, ptr) {}; 00885 00886 // using dump from inode class 00887 // using method is_more_recent_than() from inode class 00888 // using method has_changed_since() from inode class 00889 unsigned char signature() const { return mk_signature('s', get_saved_status()); }; 00890 entree *clone() const { return new prise(*this); }; 00891 00892 #ifdef LIBDAR_SPECIAL_ALLOC 00893 USE_SPECIAL_ALLOC(prise); 00894 #endif 00895 }; 00896 00898 class detruit : public nomme 00899 { 00900 public : 00901 detruit(const std::string & name, unsigned char firm, const infinint & date) : nomme(name) , del_date(date) { signe = firm; }; 00902 detruit(generic_file & f, const archive_version & reading_ver); 00903 detruit(const nomme &ref) : nomme(ref.get_name()), del_date(0) { signe = ref.signature(); }; 00904 00905 unsigned char get_signature() const { return signe; }; 00906 void set_signature(unsigned char x) { signe = x; }; 00907 unsigned char signature() const { return 'x'; }; 00908 entree *clone() const { return new detruit(*this); }; 00909 00910 const infinint & get_date() const { return del_date; }; 00911 void set_date(const infinint & ref) { del_date = ref; }; 00912 00913 #ifdef LIBDAR_SPECIAL_ALLOC 00914 USE_SPECIAL_ALLOC(detruit); 00915 #endif 00916 protected: 00917 void inherited_dump(generic_file & f, bool small) const; 00918 00919 private : 00920 unsigned char signe; 00921 infinint del_date; 00922 }; 00923 00925 class ignored : public nomme 00926 { 00927 public : 00928 ignored(const std::string & name) : nomme(name) {}; 00929 ignored(generic_file & f) : nomme(f) { throw SRC_BUG; }; 00930 00931 unsigned char signature() const { return 'i'; }; 00932 entree *clone() const { return new ignored(*this); }; 00933 #ifdef LIBDAR_SPECIAL_ALLOC 00934 USE_SPECIAL_ALLOC(ignored); 00935 #endif 00936 00937 protected: 00938 void inherited_dump(generic_file & f, bool small) const { throw SRC_BUG; }; 00939 00940 }; 00941 00943 class ignored_dir : public inode 00944 { 00945 public: 00946 ignored_dir(const directory &target) : inode(target) {}; 00947 ignored_dir(user_interaction & dialog, 00948 generic_file & f, 00949 const archive_version & reading_ver, 00950 generic_file *ea_loc, 00951 escape *ptr) : inode(dialog, f, reading_ver, s_not_saved, ea_loc, ptr) { throw SRC_BUG; }; 00952 00953 unsigned char signature() const { return 'j'; }; 00954 entree *clone() const { return new ignored_dir(*this); }; 00955 #ifdef LIBDAR_SPECIAL_ALLOC 00956 USE_SPECIAL_ALLOC(ignored_dir); 00957 #endif 00958 00959 protected: 00960 void inherited_dump(generic_file & f, bool small) const; // behaves like an empty directory 00961 00962 }; 00963 00965 class catalogue : protected mem_ui 00966 { 00967 public : 00968 catalogue(user_interaction & dialog, 00969 const infinint & root_last_modif, 00970 const label & data_name); 00971 catalogue(user_interaction & dialog, 00972 generic_file & f, 00973 const archive_version & reading_ver, 00974 compression default_algo, 00975 generic_file *data_loc, 00976 generic_file *ea_loc, 00977 bool lax, 00978 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 00979 bool only_detruit = false); //< if set to true, only directories and detruit objects are read from the archive 00980 catalogue(const catalogue & ref) : mem_ui(ref), out_compare(ref.out_compare) { partial_copy_from(ref); }; 00981 const catalogue & operator = (const catalogue &ref); 00982 virtual ~catalogue() { detruire(); }; 00983 00984 00985 // reading methods. The reading is iterative and uses the current_read directory pointer 00986 00987 virtual void reset_read() const; // set the reading cursor to the beginning of the catalogue 00988 virtual void end_read() const; // set the reading cursor to the end of the catalogue 00989 virtual void skip_read_to_parent_dir() const; 00990 // skip all items of the current dir and of any subdir, the next call will return 00991 // next item of the parent dir (no eod to exit from the current dir !) 00992 virtual bool read(const entree * & ref) const; 00993 // sequential read (generates eod) and return false when all files have been read 00994 virtual bool read_if_present(std::string *name, const nomme * & ref) const; 00995 // pseudo-sequential read (reading a directory still 00996 // implies that following read are located in this subdirectory up to the next EOD) but 00997 // it returns false if no entry of this name are present in the current directory 00998 // a call with NULL as first argument means to set the current dir the parent directory 00999 void remove_read_entry(std::string & name); 01000 // in the currently read directory, removes the entry which name is given in argument 01001 const directory & get_current_reading_dir() const { return *current_read; }; 01002 // remove from the catalogue all the entries that have not yet been read 01003 // by read(). 01004 void tail_catalogue_to_current_read(); 01005 01006 01007 void reset_sub_read(const path &sub); // initialise sub_read to the given directory 01008 bool sub_read(const entree * &ref); // sequential read of the catalogue, ignoring all that 01009 // is not part of the subdirectory specified with reset_sub_read 01010 // the read include the inode leading to the sub_tree as well as the pending eod 01011 01012 // return true if the last read entry has already been read 01013 // and has not to be counted again. This is never the case for catalogue but may occure 01014 // with escape_catalogue (where from the 'virtual'). 01015 // last this method gives a valid result only if the last read() entry is a directory as 01016 // only directory may be read() twice. 01017 virtual bool read_second_time_dir() const { return false; }; 01018 01019 01020 // Additions methods. The addition is also iterative but uses its specific current_add directory pointer 01021 01022 void reset_add(); 01023 01025 // real implementation is only needed in escape_catalogue class, here there nothing to be done 01026 virtual void pre_add(const entree *ref, compressor *compr) const {}; 01027 virtual void pre_add_ea(const entree *ref, compressor *compr) const {}; 01028 virtual void pre_add_crc(const entree *ref, compressor *compr) const {}; 01029 virtual void pre_add_dirty(compressor *compr) const {}; 01030 virtual void pre_add_ea_crc(const entree *ref, compressor *compr) const {}; 01031 virtual void pre_add_waste_mark(compressor *compr) const {}; 01032 virtual void pre_add_failed_mark(compressor *compr) const {}; 01033 virtual escape *get_escape_layer() const { return NULL; }; 01034 01035 void add(entree *ref); // add at end of catalogue (sequential point of view) 01036 void re_add_in(const std::string &subdirname); // return into an already existing subdirectory for further addition 01037 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 01038 void add_in_current_read(nomme *ref); // add in currently read directory 01039 01040 01041 01042 // Comparison methods. The comparision is here also iterative and uses its specific current_compare directory pointer 01043 01044 void reset_compare(); 01045 bool compare(const entree * name, const entree * & extracted); 01046 // returns true if the ref exists, and gives it back in second argument as it is in the current catalogue. 01047 // returns false is no entry of that nature exists in the catalogue (in the current directory) 01048 // if ref is a directory, the operation is normaly relative to the directory itself, but 01049 // such a call implies a chdir to that directory. thus, a call with an EOD is necessary to 01050 // change to the parent directory. 01051 // note : 01052 // if a directory is not present, returns false, but records the inexistant subdirectory 01053 // structure defined by the following calls to this routine, this to be able to know when 01054 // the last available directory is back the current one when changing to parent directory, 01055 // and then proceed with normal comparison of inode. In this laps of time, the call will 01056 // always return false, while it temporary stores the missing directory structure 01057 01058 01059 01060 // non interative methods 01061 01062 bool direct_read(const path & ref, const nomme * &ret); 01063 infinint update_destroyed_with(catalogue & ref); 01064 // ref must have the same root, else the operation generates an exception 01065 01066 void update_absent_with(catalogue & ref, infinint aborting_next_etoile); 01067 // in case of abortion, completes missing files as if what could not be 01068 // inspected had not changed since the reference was done 01069 // aborting_last_etoile is the highest etoile reference withing "this" current object. 01070 01071 void dump(generic_file & f) const; 01072 void listing(bool isolated, 01073 const mask &selection, 01074 const mask & subtree, 01075 bool filter_unsaved, 01076 bool list_ea, 01077 std::string marge) const; 01078 void tar_listing(bool isolated, 01079 const mask & selection, 01080 const mask & subtree, 01081 bool filter_unsaved, 01082 bool list_ea, 01083 std::string beginning) const; 01084 void xml_listing(bool isolated, 01085 const mask & selection, 01086 const mask & subtree, 01087 bool filter_unsaved, 01088 bool list_ea, 01089 std::string beginning) const; 01090 01091 entree_stats get_stats() const { return stats; }; 01092 01094 bool is_empty() const { if(contenu == NULL) throw SRC_BUG; return contenu->is_empty(); }; 01095 01096 const directory *get_contenu() const { return contenu; }; // used by data_tree 01097 01098 const label & get_data_name() const { return ref_data_name; }; 01099 infinint get_root_dir_last_modif() const { return contenu->get_last_modif(); }; 01100 01102 void launch_recursive_has_changed_update() const { contenu->recursive_has_changed_update(); }; 01103 01104 infinint get_root_mtime() const { return contenu->get_last_modif(); }; 01105 01107 void reset_all(); 01108 01109 #ifdef LIBDAR_SPECIAL_ALLOC 01110 USE_SPECIAL_ALLOC(catalogue); 01111 #endif 01112 01113 protected: 01114 entree_stats & access_stats() { return stats; }; 01115 void set_data_name(const label & val) { ref_data_name = val; }; 01116 void copy_detruits_from(const catalogue & ref); // needed for escape_catalogue implementation only. 01117 01118 const eod * get_r_eod_address() const { return & r_eod; }; // eod are never stored in the catalogue 01119 // however it is sometimes required to return such a reference to a valid object 01120 // owned by the catalogue. 01121 01122 01125 void swap_stuff(catalogue & ref); 01126 01127 private : 01128 directory *contenu; 01129 path out_compare; 01130 directory *current_compare; 01131 directory *current_add; 01132 directory *current_read; 01133 path *sub_tree; 01134 signed int sub_count; 01135 entree_stats stats; 01136 label ref_data_name; 01137 01138 void partial_copy_from(const catalogue &ref); 01139 void detruire(); 01140 01141 static const eod r_eod; // needed to return eod reference, without taking risk of saturating memory 01142 static const U_I CAT_CRC_SIZE; 01143 }; 01144 01145 01146 01148 01149 } // end of namespace 01150 01151 #endif